-
Notifications
You must be signed in to change notification settings - Fork 1.5k
[flutter_local_notifications] Added ability to bind to ForegroundService #2677
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -413,6 +413,75 @@ When specifying the large icon bitmap or big picture bitmap (associated with the | |
|
|
||
| ⚠️ For Android 8.0+, sounds and vibrations are associated with notification channels and can only be configured when they are first created. Showing/scheduling a notification will create a channel with the specified id if it doesn't exist already. If another notification specifies the same channel id but tries to specify another sound or vibration pattern then nothing occurs. | ||
|
|
||
|
|
||
| ### Bind ForegroundService to your FlutterActivity | ||
|
|
||
| In your activity (e.g., `MainActivity.kt`), set up a broadcast receiver and a `ServiceConnection` to manage binding and unbinding. This is not required to use a `ForegroundService` but it will decrease the likelyhood of your activity being [killed or frozen by the OS while the activity is in the background](https://source.android.com/docs/core/perf/cached-apps-freezer#handling-custom-features): | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can this start off by saying it's optional and only applicable for apps using foreground services? Thinking behind this is some readers may not pick this up or know enough about Android development to realise |
||
|
|
||
| ```kotlin | ||
| class MainActivity: FlutterActivity() { | ||
| private var isServiceBound = false | ||
| private val serviceStartedAction = "com.dexterous.flutterlocalnotifications.FOREGROUND_SERVICE_STARTED" | ||
| private val serviceStoppedAction = "com.dexterous.flutterlocalnotifications.FOREGROUND_SERVICE_STOPPED" | ||
|
|
||
| private val serviceConnection = object : ServiceConnection { | ||
| override fun onServiceConnected(name: ComponentName?, binder: IBinder?) { | ||
| isServiceBound = true | ||
| Log.d("MainActivity", "Service bound") | ||
| } | ||
| override fun onServiceDisconnected(name: ComponentName?) { | ||
| isServiceBound = false | ||
| Log.d("MainActivity", "Service disconnected") | ||
| } | ||
| } | ||
|
|
||
| private val serviceBroadcastReceiver = object : android.content.BroadcastReceiver() { | ||
| override fun onReceive(context: Context?, intent: Intent?) { | ||
| Log.d("MainActivity", "Received broadcast: ${intent?.action}") | ||
| when (intent?.action) { | ||
| serviceStartedAction -> { | ||
| if (!isServiceBound) { | ||
| val bindIntent = Intent(context, ForegroundService::class.java) | ||
| bindService(bindIntent, serviceConnection, Context.BIND_AUTO_CREATE) | ||
| } | ||
| } | ||
| serviceStoppedAction -> { | ||
| if (isServiceBound) { | ||
| unbindService(serviceConnection) | ||
| isServiceBound = false | ||
| Log.d("MainActivity", "Service unbound from broadcast") | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| @SuppressLint("UnspecifiedRegisterReceiverFlag") | ||
| override fun onCreate(savedInstanceState: android.os.Bundle?) { | ||
| super.onCreate(savedInstanceState) | ||
| val filter = android.content.IntentFilter().apply { | ||
| addAction(serviceStartedAction) | ||
| addAction(serviceStoppedAction) | ||
| } | ||
| if (android.os.Build.VERSION.SDK_INT >= 33) { | ||
| registerReceiver(serviceBroadcastReceiver, filter, Context.RECEIVER_NOT_EXPORTED) | ||
| } else { | ||
| registerReceiver(serviceBroadcastReceiver, filter) | ||
| } | ||
| } | ||
|
|
||
| override fun onDestroy() { | ||
| super.onDestroy() | ||
| unregisterReceiver(serviceBroadcastReceiver) | ||
| if (isServiceBound) { | ||
| unbindService(serviceConnection) | ||
| isServiceBound = false | ||
| } | ||
| } | ||
| // ...existing code... | ||
| } | ||
| ``` | ||
|
|
||
| ### Full-screen intent notifications | ||
|
|
||
| If your application needs the ability to schedule full-screen intent notifications, add the following attributes to the activity you're opening. For a Flutter application, there is typically only one activity extends from `FlutterActivity`. These attributes ensure the screen turns on and shows when the device is locked. | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2306,6 +2306,8 @@ private void startForegroundService(MethodCall call, Result result) { | |
| Intent intent = new Intent(applicationContext, ForegroundService.class); | ||
| intent.putExtra(ForegroundServiceStartParameter.EXTRA, parameter); | ||
| ContextCompat.startForegroundService(applicationContext, intent); | ||
| applicationContext.sendBroadcast(new Intent("com.dexterous.flutterlocalnotifications.FOREGROUND_SERVICE_STARTED") | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let me know what you think but I believe it's best to do the following
|
||
| .setPackage(applicationContext.getPackageName())); | ||
| result.success(null); | ||
| } else { | ||
| result.error( | ||
|
|
@@ -2326,6 +2328,7 @@ private void startForegroundService(MethodCall call, Result result) { | |
|
|
||
| private void stopForegroundService(Result result) { | ||
| applicationContext.stopService(new Intent(applicationContext, ForegroundService.class)); | ||
| applicationContext.sendBroadcast(new Intent("com.dexterous.flutterlocalnotifications.FOREGROUND_SERVICE_STOPPED").setPackage(applicationContext.getPackageName())); | ||
| result.success(null); | ||
| } | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The table of contents is missing an update that allows for jumping to this section