@@ -19,14 +19,12 @@ import com.pravera.flutter_foreground_task.FlutterForegroundTaskLifecycleListene
19
19
import com.pravera.flutter_foreground_task.RequestCode
20
20
import com.pravera.flutter_foreground_task.models.*
21
21
import com.pravera.flutter_foreground_task.utils.ForegroundServiceUtils
22
- import com.pravera.flutter_foreground_task.utils.PluginUtils
23
22
import kotlinx.coroutines.*
24
23
import kotlinx.coroutines.flow.MutableStateFlow
25
24
import kotlinx.coroutines.flow.asStateFlow
26
25
import kotlinx.coroutines.flow.update
27
26
import java.util.*
28
27
29
-
30
28
/* *
31
29
* A service class for implementing foreground service.
32
30
*
@@ -37,31 +35,52 @@ class ForegroundService : Service() {
37
35
companion object {
38
36
private val TAG = ForegroundService ::class .java.simpleName
39
37
40
- private const val ACTION_RECEIVE_DATA = " onReceiveData"
41
- private const val ACTION_NOTIFICATION_BUTTON_PRESSED = " onNotificationButtonPressed"
42
38
private const val ACTION_NOTIFICATION_PRESSED = " onNotificationPressed"
43
39
private const val ACTION_NOTIFICATION_DISMISSED = " onNotificationDismissed"
44
- private const val INTENT_DATA_FIELD_NAME = " data"
40
+ private const val ACTION_NOTIFICATION_BUTTON_PRESSED = " onNotificationButtonPressed"
41
+ private const val ACTION_RECEIVE_DATA = " onReceiveData"
42
+ private const val INTENT_DATA_NAME = " intentData"
45
43
46
44
private val _isRunningServiceState = MutableStateFlow (false )
47
45
val isRunningServiceState = _isRunningServiceState .asStateFlow()
48
46
49
- private var foregroundTask : ForegroundTask ? = null
47
+ private var task : ForegroundTask ? = null
50
48
private var taskLifecycleListeners = ForegroundTaskLifecycleListeners ()
51
49
52
- fun sendData (data : Any? ) {
53
- if (isRunningServiceState.value) {
54
- foregroundTask?.invokeMethod(ACTION_RECEIVE_DATA , data)
55
- }
56
- }
57
-
58
50
fun addTaskLifecycleListener (listener : FlutterForegroundTaskLifecycleListener ) {
59
51
taskLifecycleListeners.addListener(listener)
60
52
}
61
53
62
54
fun removeTaskLifecycleListener (listener : FlutterForegroundTaskLifecycleListener ) {
63
55
taskLifecycleListeners.removeListener(listener)
64
56
}
57
+
58
+ fun handleNotificationContentIntent (intent : Intent ? ) {
59
+ if (intent == null ) return
60
+
61
+ try {
62
+ // Check if the given intent is a LaunchIntent.
63
+ val isLaunchIntent = (intent.action == Intent .ACTION_MAIN ) &&
64
+ intent.categories.contains(Intent .CATEGORY_LAUNCHER )
65
+ if (! isLaunchIntent) {
66
+ // Log.d(TAG, "not LaunchIntent")
67
+ return
68
+ }
69
+
70
+ val data = intent.getStringExtra(INTENT_DATA_NAME )
71
+ if (data == ACTION_NOTIFICATION_PRESSED ) {
72
+ task?.invokeMethod(data, null )
73
+ }
74
+ } catch (e: Exception ) {
75
+ Log .e(TAG , e.message, e)
76
+ }
77
+ }
78
+
79
+ fun sendData (data : Any? ) {
80
+ if (isRunningServiceState.value) {
81
+ task?.invokeMethod(ACTION_RECEIVE_DATA , data)
82
+ }
83
+ }
65
84
}
66
85
67
86
private lateinit var foregroundServiceStatus: ForegroundServiceStatus
@@ -80,22 +99,20 @@ class ForegroundService : Service() {
80
99
// A broadcast receiver that handles intents that occur in the foreground service.
81
100
private var broadcastReceiver = object : BroadcastReceiver () {
82
101
override fun onReceive (context : Context ? , intent : Intent ? ) {
83
- try {
84
- // No intent ??
85
- if (intent == null ) {
86
- throw Exception (" Intent is null." )
87
- }
102
+ if (intent == null ) return
88
103
104
+ try {
89
105
// This intent has not sent from the current package.
90
106
val iPackageName = intent.`package`
91
107
val cPackageName = packageName
92
108
if (iPackageName != cPackageName) {
93
- throw Exception (" This intent has not sent from the current package. ($iPackageName != $cPackageName )" )
109
+ Log .d(TAG , " This intent has not sent from the current package. ($iPackageName != $cPackageName )" )
110
+ return
94
111
}
95
112
96
113
val action = intent.action ? : return
97
- val data = intent.getStringExtra(INTENT_DATA_FIELD_NAME )
98
- foregroundTask ?.invokeMethod(action, data)
114
+ val data = intent.getStringExtra(INTENT_DATA_NAME )
115
+ task ?.invokeMethod(action, data)
99
116
} catch (e: Exception ) {
100
117
Log .e(TAG , e.message, e)
101
118
}
@@ -284,43 +301,40 @@ class ForegroundService : Service() {
284
301
}
285
302
286
303
private fun createNotification (): Notification {
287
- // notification
288
- val channelId = notificationOptions.channelId
289
-
290
304
// notification icon
291
305
val icon = notificationContent.icon
292
306
val iconResId = getIconResId(icon)
293
307
val iconBackgroundColor = icon?.backgroundColorRgb?.let (::getRgbColor)
294
308
295
309
// notification intent
296
- val pendingIntent = getPendingIntent ()
297
- val deletePendingIntent = getDeletePendingIntent ()
310
+ val contentIntent = getContentIntent ()
311
+ val deleteIntent = getDeleteIntent ()
298
312
299
- // notification action
300
- var needsUpdateButtons = false
313
+ // notification actions
314
+ var needsRebuildButtons = false
301
315
val prevButtons = prevNotificationContent?.buttons
302
316
val currButtons = notificationContent.buttons
303
317
if (prevButtons != null ) {
304
318
if (prevButtons.size != currButtons.size) {
305
- needsUpdateButtons = true
319
+ needsRebuildButtons = true
306
320
} else {
307
321
for (i in currButtons.indices) {
308
322
if (prevButtons[i] != currButtons[i]) {
309
- needsUpdateButtons = true
323
+ needsRebuildButtons = true
310
324
break
311
325
}
312
326
}
313
327
}
314
328
} else {
315
- needsUpdateButtons = true
329
+ needsRebuildButtons = true
316
330
}
317
331
318
332
if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .O ) {
319
- val builder = Notification .Builder (this , channelId)
333
+ val builder = Notification .Builder (this , notificationOptions. channelId)
320
334
builder.setOngoing(true )
321
335
builder.setShowWhen(notificationOptions.showWhen)
322
336
builder.setSmallIcon(iconResId)
323
- builder.setContentIntent(pendingIntent )
337
+ builder.setContentIntent(contentIntent )
324
338
builder.setContentTitle(notificationContent.title)
325
339
builder.setContentText(notificationContent.text)
326
340
builder.style = Notification .BigTextStyle ()
@@ -333,21 +347,21 @@ class ForegroundService : Service() {
333
347
builder.setForegroundServiceBehavior(Notification .FOREGROUND_SERVICE_IMMEDIATE )
334
348
}
335
349
if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .UPSIDE_DOWN_CAKE ) {
336
- builder.setDeleteIntent(deletePendingIntent )
350
+ builder.setDeleteIntent(deleteIntent )
337
351
}
338
352
339
- val actions = buildNotificationActions(notificationContent.buttons, needsUpdateButtons )
353
+ val actions = buildNotificationActions(currButtons, needsRebuildButtons )
340
354
for (action in actions) {
341
355
builder.addAction(action)
342
356
}
343
357
344
358
return builder.build()
345
359
} else {
346
- val builder = NotificationCompat .Builder (this , channelId)
360
+ val builder = NotificationCompat .Builder (this , notificationOptions. channelId)
347
361
builder.setOngoing(true )
348
362
builder.setShowWhen(notificationOptions.showWhen)
349
363
builder.setSmallIcon(iconResId)
350
- builder.setContentIntent(pendingIntent )
364
+ builder.setContentIntent(contentIntent )
351
365
builder.setContentTitle(notificationContent.title)
352
366
builder.setContentText(notificationContent.text)
353
367
builder.setStyle(NotificationCompat .BigTextStyle ().bigText(notificationContent.text))
@@ -364,7 +378,7 @@ class ForegroundService : Service() {
364
378
}
365
379
builder.priority = notificationOptions.priority
366
380
367
- val actions = buildNotificationCompatActions(notificationContent.buttons, needsUpdateButtons )
381
+ val actions = buildNotificationCompatActions(currButtons, needsRebuildButtons )
368
382
for (action in actions) {
369
383
builder.addAction(action)
370
384
}
@@ -427,7 +441,7 @@ class ForegroundService : Service() {
427
441
private fun createForegroundTask () {
428
442
destroyForegroundTask()
429
443
430
- foregroundTask = ForegroundTask (
444
+ task = ForegroundTask (
431
445
context = this ,
432
446
serviceStatus = foregroundServiceStatus,
433
447
taskData = foregroundTaskData,
@@ -437,12 +451,12 @@ class ForegroundService : Service() {
437
451
}
438
452
439
453
private fun updateForegroundTask () {
440
- foregroundTask ?.update(taskEventAction = foregroundTaskOptions.eventAction)
454
+ task ?.update(taskEventAction = foregroundTaskOptions.eventAction)
441
455
}
442
456
443
457
private fun destroyForegroundTask () {
444
- foregroundTask ?.destroy()
445
- foregroundTask = null
458
+ task ?.destroy()
459
+ task = null
446
460
}
447
461
448
462
private fun getIconResId (icon : NotificationIcon ? ): Int {
@@ -469,27 +483,32 @@ class ForegroundService : Service() {
469
483
}
470
484
}
471
485
472
- private fun getPendingIntent (): PendingIntent {
473
- return if (Build .VERSION .SDK_INT < Build .VERSION_CODES .Q || PluginUtils .canDrawOverlays(applicationContext)) {
474
- val pIntent = Intent (ACTION_NOTIFICATION_PRESSED ).apply {
475
- setPackage(packageName)
476
- }
477
- PendingIntent .getBroadcast(
478
- this , RequestCode .NOTIFICATION_PRESSED_BROADCAST , pIntent, PendingIntent .FLAG_IMMUTABLE )
479
- } else {
480
- val pm = applicationContext.packageManager
481
- val lIntent = pm.getLaunchIntentForPackage(applicationContext.packageName)
482
- PendingIntent .getActivity(
483
- this , RequestCode .NOTIFICATION_PRESSED , lIntent, PendingIntent .FLAG_IMMUTABLE )
486
+ private fun getContentIntent (): PendingIntent {
487
+ val packageManager = applicationContext.packageManager
488
+ val packageName = applicationContext.packageName
489
+ val intent = packageManager.getLaunchIntentForPackage(packageName)?.apply {
490
+ putExtra(INTENT_DATA_NAME , ACTION_NOTIFICATION_PRESSED )
491
+ }
492
+
493
+ var flags = PendingIntent .FLAG_UPDATE_CURRENT
494
+ if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .S ) {
495
+ flags = flags or PendingIntent .FLAG_IMMUTABLE
484
496
}
497
+
498
+ return PendingIntent .getActivity(this , RequestCode .NOTIFICATION_PRESSED , intent, flags)
485
499
}
486
500
487
- private fun getDeletePendingIntent (): PendingIntent {
488
- val dIntent = Intent (ACTION_NOTIFICATION_DISMISSED ).apply {
501
+ private fun getDeleteIntent (): PendingIntent {
502
+ val intent = Intent (ACTION_NOTIFICATION_DISMISSED ).apply {
489
503
setPackage(packageName)
490
504
}
491
- return PendingIntent .getBroadcast(
492
- this , RequestCode .NOTIFICATION_DISMISSED_BROADCAST , dIntent, PendingIntent .FLAG_IMMUTABLE )
505
+
506
+ var flags = PendingIntent .FLAG_UPDATE_CURRENT
507
+ if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .S ) {
508
+ flags = flags or PendingIntent .FLAG_IMMUTABLE
509
+ }
510
+
511
+ return PendingIntent .getBroadcast(this , RequestCode .NOTIFICATION_DISMISSED , intent, flags)
493
512
}
494
513
495
514
private fun getRgbColor (rgb : String ): Int? {
@@ -513,16 +532,16 @@ class ForegroundService : Service() {
513
532
514
533
private fun buildNotificationActions (
515
534
buttons : List <NotificationButton >,
516
- needsUpdate : Boolean = false
535
+ needsRebuild : Boolean = false
517
536
): List <Notification .Action > {
518
537
val actions = mutableListOf<Notification .Action >()
519
538
for (i in buttons.indices) {
520
539
val intent = Intent (ACTION_NOTIFICATION_BUTTON_PRESSED ).apply {
521
540
setPackage(packageName)
522
- putExtra(INTENT_DATA_FIELD_NAME , buttons[i].id)
541
+ putExtra(INTENT_DATA_NAME , buttons[i].id)
523
542
}
524
543
var flags = PendingIntent .FLAG_IMMUTABLE
525
- if (needsUpdate ) {
544
+ if (needsRebuild ) {
526
545
flags = flags or PendingIntent .FLAG_CANCEL_CURRENT
527
546
}
528
547
val textColor = buttons[i].textColorRgb?.let (::getRgbColor)
@@ -542,16 +561,16 @@ class ForegroundService : Service() {
542
561
543
562
private fun buildNotificationCompatActions (
544
563
buttons : List <NotificationButton >,
545
- needsUpdate : Boolean = false
564
+ needsRebuild : Boolean = false
546
565
): List <NotificationCompat .Action > {
547
566
val actions = mutableListOf<NotificationCompat .Action >()
548
567
for (i in buttons.indices) {
549
568
val intent = Intent (ACTION_NOTIFICATION_BUTTON_PRESSED ).apply {
550
569
setPackage(packageName)
551
- putExtra(INTENT_DATA_FIELD_NAME , buttons[i].id)
570
+ putExtra(INTENT_DATA_NAME , buttons[i].id)
552
571
}
553
572
var flags = PendingIntent .FLAG_IMMUTABLE
554
- if (needsUpdate ) {
573
+ if (needsRebuild ) {
555
574
flags = flags or PendingIntent .FLAG_CANCEL_CURRENT
556
575
}
557
576
val textColor = buttons[i].textColorRgb?.let (::getRgbColor)
0 commit comments