Skip to content

Instantly share code, notes, and snippets.

@oligazar
Created May 31, 2021 09:50
Show Gist options
  • Save oligazar/b84003ef9ce7cb7d8237a20433d74aa1 to your computer and use it in GitHub Desktop.
Save oligazar/b84003ef9ce7cb7d8237a20433d74aa1 to your computer and use it in GitHub Desktop.
class IsolateHolderService : MethodChannel.MethodCallHandler, LocationUpdateListener, Service() {
// ... other code ...
companion object {
private var notificationChannelName = "Flutter Locator Plugin"
private var notificationTitle = "Start Location Tracking"
private var notificationMsg = "Track location in background"
private var notificationBigMsg = "Background location is on to keep the app up-tp-date with your location. This is required for main features to work properly when the app is not running."
private var icon = 0
private var notificationIconColor = 0
fun getNotification(context: Context): Notification {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// Notification channel is available in Android O and up
val channel = NotificationChannel(Keys.CHANNEL_ID,
notificationChannelName,
NotificationManager.IMPORTANCE_LOW)
(context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager)
.createNotificationChannel(channel)
}
val intent = Intent(context, getMainActivityClass(context))
intent.action = Keys.NOTIFICATION_ACTION
val pendingIntent: PendingIntent = PendingIntent.getActivity(context,
1, intent,
PendingIntent.FLAG_UPDATE_CURRENT)
return NotificationCompat.Builder(context, Keys.CHANNEL_ID)
.setContentTitle(notificationTitle)
.setContentText(notificationMsg)
.setStyle(NotificationCompat.BigTextStyle()
.bigText(notificationBigMsg))
.setSmallIcon(icon)
.setColor(notificationIconColor)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setContentIntent(pendingIntent)
.setOnlyAlertOnce(true) // so when data is updated don't make sound and alert in android 8.0+
.setOngoing(true)
.build()
}
private fun getMainActivityClass(context: Context): Class<*>? {
val packageName = context.packageName
val launchIntent = context.packageManager.getLaunchIntentForPackage(packageName)
val className = launchIntent?.component?.className ?: return null
return try {
Class.forName(className)
} catch (e: ClassNotFoundException) {
e.printStackTrace()
null
}
}
}
class LocalBinder : Binder() {
val service: IsolateHolderService
get() = this@IsolateHolderService
}
// Create the instance on the service.
private val binder = LocalBinder()
override fun onBind(intent: Intent?): IBinder? {
context?.d("onBind")
return binder
}
}
class BackgroundLocatorPlugin
: MethodCallHandler, FlutterPlugin, PluginRegistry.NewIntentListener, ActivityAware {
// ... other code ...
companion object {
private var context: Context? = null
private fun bindService(context: Context, intent: Intent) {
try {
context.bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE)
} catch (ignored: RuntimeException) {
// This is probably a broadcast receiver context even though we are calling getApplicationContext().
// Just call startForegroundService instead since we cannot bind a service to a
// broadcast receiver context. The service also have to call startForeground in
// this case.
// context.startForegroundService(getServiceIntent(context))
ContextCompat.startForegroundService(context, intent)
}
context.bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE)
}
private var serviceConnection: ServiceConnection = object : ServiceConnection {
override fun onServiceConnected(name: ComponentName, service: IBinder) {
// The binder of the service that returns the instance that is created.
val binder: IsolateHolderService.LocalBinder = service as IsolateHolderService.LocalBinder
// The getter method to acquire the service.
val myService: IsolateHolderService = binder.service
// getServiceIntent(context) returns the relative service intent
// context!!.startForegroundService(getServiceIntent(context))
context?.let {
ContextCompat.startForegroundService(it, getServiceIntent(context)) // getServiceIntent has to be implemented
// This is the key: Without waiting Android Framework to call this method
// inside Service.onCreate(), immediately call here to post the notification.
myService.startForeground(IsolateHolderService.notificationId, IsolateHolderService.getNotification(it))
}
// Release the connection to prevent leaks.
context!!.unbindService(this)
}
override fun onServiceDisconnected(name: ComponentName?) {
TODO("Not yet implemented")
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment