Skip to content

Commit b689f2c

Browse files
committed
change: Change method for customizing notification icon
1 parent 0a92a5d commit b689f2c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+180
-297
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,7 @@ void initState() {
342342
* `serviceId`: The unique ID that identifies the service.
343343
* `notificationTitle`: The title to display in the notification.
344344
* `notificationText`: The text to display in the notification.
345-
* `notificationIcon`: The icon to display in the notification. (only work Android)
345+
* `notificationIcon`: The icon to display in the notification. Go to [this page](./documentation/customize_notification_icon.md) to customize.
346346
* `notificationButtons`: The buttons to display in the notification. (can add 0~3 buttons)
347347
* `callback`: A top-level function that calls the setTaskHandler function.
348348

android/src/main/kotlin/com/pravera/flutter_foreground_task/PreferencesKey.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ object PreferencesKey {
3535
// notification content
3636
const val NOTIFICATION_CONTENT_TITLE = "notificationContentTitle"
3737
const val NOTIFICATION_CONTENT_TEXT = "notificationContentText"
38-
const val NOTIFICATION_CONTENT_ICON = "iconData"
38+
const val NOTIFICATION_CONTENT_ICON = "icon"
3939
const val NOTIFICATION_CONTENT_BUTTONS = "buttons"
4040

4141
// task options

android/src/main/kotlin/com/pravera/flutter_foreground_task/models/NotificationContent.kt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@ import org.json.JSONArray
66
import org.json.JSONObject
77

88
data class NotificationContent(
9-
val title: String,
10-
val text: String,
11-
val icon: NotificationIconData?,
12-
val buttons: List<NotificationButton>
9+
val title: String,
10+
val text: String,
11+
val icon: NotificationIcon?,
12+
val buttons: List<NotificationButton>
1313
) {
1414
companion object {
1515
fun getData(context: Context): NotificationContent {
@@ -20,9 +20,9 @@ data class NotificationContent(
2020
val text = prefs.getString(PrefsKey.NOTIFICATION_CONTENT_TEXT, null) ?: ""
2121

2222
val iconJsonString = prefs.getString(PrefsKey.NOTIFICATION_CONTENT_ICON, null)
23-
var icon: NotificationIconData? = null
23+
var icon: NotificationIcon? = null
2424
if (iconJsonString != null) {
25-
icon = NotificationIconData.fromJsonString(iconJsonString)
25+
icon = NotificationIcon.fromJsonString(iconJsonString)
2626
}
2727

2828
val buttonsJsonString = prefs.getString(PrefsKey.NOTIFICATION_CONTENT_BUTTONS, null)
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package com.pravera.flutter_foreground_task.models
2+
3+
import org.json.JSONObject
4+
5+
data class NotificationIcon(
6+
val metaDataName: String,
7+
val backgroundColorRgb: String?
8+
) {
9+
companion object {
10+
private const val META_DATA_NAME_KEY = "metaDataName"
11+
private const val BACKGROUND_COLOR_RGB_KEY = "backgroundColorRgb"
12+
13+
fun fromJsonString(jsonString: String): NotificationIcon {
14+
val jsonObj = JSONObject(jsonString)
15+
16+
val metaDataName: String = if (jsonObj.isNull(META_DATA_NAME_KEY)) {
17+
""
18+
} else {
19+
jsonObj.getString(META_DATA_NAME_KEY)
20+
}
21+
22+
val backgroundColorRgb: String? = if (jsonObj.isNull(BACKGROUND_COLOR_RGB_KEY)) {
23+
null
24+
} else {
25+
jsonObj.getString(BACKGROUND_COLOR_RGB_KEY)
26+
}
27+
28+
return NotificationIcon(
29+
metaDataName = metaDataName,
30+
backgroundColorRgb = backgroundColorRgb
31+
)
32+
}
33+
}
34+
}

android/src/main/kotlin/com/pravera/flutter_foreground_task/models/NotificationIconData.kt

Lines changed: 0 additions & 52 deletions
This file was deleted.

android/src/main/kotlin/com/pravera/flutter_foreground_task/service/ForegroundService.kt

Lines changed: 23 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import android.content.pm.ServiceInfo
88
import android.graphics.Color
99
import android.net.wifi.WifiManager
1010
import android.os.*
11-
import android.os.Build
1211
import android.text.Spannable
1312
import android.text.SpannableString
1413
import android.text.style.ForegroundColorSpan
@@ -27,6 +26,7 @@ import kotlinx.coroutines.flow.asStateFlow
2726
import kotlinx.coroutines.flow.update
2827
import java.util.*
2928

29+
3030
/**
3131
* A service class for implementing foreground service.
3232
*
@@ -288,9 +288,9 @@ class ForegroundService : Service() {
288288
val channelId = notificationOptions.channelId
289289

290290
// notification icon
291-
val iconData = notificationContent.icon
292-
val iconBackgroundColor = iconData?.backgroundColorRgb?.let(::getRgbColor)
293-
val iconResId = if (iconData != null) getIconResId(iconData) else getIconResId()
291+
val icon = notificationContent.icon
292+
val iconResId = getIconResId(icon)
293+
val iconBackgroundColor = icon?.backgroundColorRgb?.let(::getRgbColor)
294294

295295
// notification intent
296296
val pendingIntent = getPendingIntent()
@@ -445,37 +445,28 @@ class ForegroundService : Service() {
445445
foregroundTask = null
446446
}
447447

448-
private fun getIconResId(): Int {
449-
return try {
450-
val pm = applicationContext.packageManager
451-
val appInfo =
452-
pm.getApplicationInfo(applicationContext.packageName, PackageManager.GET_META_DATA)
453-
appInfo.icon
454-
} catch (e: Exception) {
455-
Log.e(TAG, "getIconResId", e)
456-
0
457-
}
458-
}
448+
private fun getIconResId(icon: NotificationIcon?): Int {
449+
try {
450+
val packageManager = applicationContext.packageManager
451+
val packageName = applicationContext.packageName
452+
val appInfo = packageManager.getApplicationInfo(packageName, PackageManager.GET_META_DATA)
459453

460-
private fun getIconResId(iconData: NotificationIconData): Int {
461-
val resType = iconData.resType
462-
val resPrefix = iconData.resPrefix
463-
val name = iconData.name
464-
if (resType.isEmpty() || resPrefix.isEmpty() || name.isEmpty()) {
465-
return 0
466-
}
454+
// application icon
455+
if (icon == null) {
456+
return appInfo.icon
457+
}
467458

468-
val resName = if (resPrefix.contains("ic")) {
469-
String.format("ic_%s", name)
470-
} else {
471-
String.format("img_%s", name)
472-
}
459+
// custom icon
460+
val metaData = appInfo.metaData
461+
if (metaData != null) {
462+
return metaData.getInt(icon.metaDataName)
463+
}
473464

474-
return applicationContext.resources.getIdentifier(
475-
resName,
476-
resType,
477-
applicationContext.packageName
478-
)
465+
return 0
466+
} catch (e: Exception) {
467+
Log.e(TAG, "getIconResId($icon)", e)
468+
return 0
469+
}
479470
}
480471

481472
private fun getPendingIntent(): PendingIntent {
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
Go to [`page`][1] and generate the notification icon.
2+
You can also use the [`image generator`][2] provided by Android Studio.
3+
4+
Move the downloaded icon image file to the `android/app/src/res/drawable` folder.
5+
6+
If successful, it will appear as shown in the image below:
7+
8+
<img width="300" alt="image" src="https://github.com/user-attachments/assets/1ebe4750-def1-4387-a0ed-aeb8d4f483a4">
9+
10+
Next, you need to add meta-data in the `AndroidManifest.xml` file so that the plugin can reference the icon resource.
11+
12+
```xml
13+
<application>
14+
<!-- Warning: Do not change service name. -->
15+
<service
16+
android:name="com.pravera.flutter_foreground_task.service.ForegroundService"
17+
android:foregroundServiceType="dataSync"
18+
android:exported="false" />
19+
20+
<!-- this -->
21+
<meta-data
22+
android:name="com.your_package.service.HEART_ICON"
23+
android:resource="@drawable/ic_heart" />
24+
</application>
25+
```
26+
27+
The name of the meta-data can be customized, but it is recommended to set it to a unique name combined with your package name.
28+
29+
Finally, you can create a NotificationIcon object to change the notification icon when starting or updating the service.
30+
31+
```dart
32+
void start() {
33+
FlutterForegroundTask.startService(
34+
notificationTitle: 'notificationTitle',
35+
notificationText: 'notificationText',
36+
notificationIcon: const NotificationIcon(
37+
metaDataName: 'com.your_package.service.HEART_ICON',
38+
backgroundColor: Colors.orange,
39+
),
40+
);
41+
}
42+
43+
void update() {
44+
FlutterForegroundTask.updateService(
45+
notificationIcon: const NotificationIcon(
46+
metaDataName: 'com.your_package.service.HEART_ICON',
47+
backgroundColor: Colors.purple,
48+
),
49+
);
50+
}
51+
```
52+
53+
[1]: https://romannurik.github.io/AndroidAssetStudio/icons-notification.html#source.type=clipart&source.clipart=ac_unit&source.space.trim=1&source.space.pad=0.15&name=ic_notification
54+
[2]: https://developer.android.com/studio/write/create-app-icons#create-notification

documentation/models_documentation.md

Lines changed: 6 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -49,33 +49,14 @@ A class that defines the action of onRepeatEvent in `TaskHandler`.
4949
| `once()` | Call onRepeatEvent only once. |
5050
| `repeat(interval)` | Call onRepeatEvent at milliseconds `interval`. |
5151

52-
### :chicken: NotificationIconData
52+
### :chicken: NotificationIcon
5353

54-
Data for setting the notification icon.
54+
A data class for dynamically changing the notification icon.
5555

56-
| Property | Description |
57-
|-------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
58-
| `resType` | The resource type of the notification icon. If the resource is in the drawable folder, set it to `ResourceType.drawable`, if the resource is in the mipmap folder, set it to `ResourceType.mipmap`. |
59-
| `resPrefix` | The resource prefix of the notification icon. If the notification icon name is `ic_simple_notification`, set it to `ResourcePrefix.ic` and set `name` to `simple_notification`. |
60-
| `name` | Notification icon name without prefix. |
61-
62-
### :chicken: ResourceType
63-
64-
The resource type of the notification icon.
65-
66-
| Value | Description |
67-
|------------|---------------------------------------------------------------------------------------------------------|
68-
| `drawable` | A resources in the drawable folder. The drawable folder is where all kinds of images are stored. |
69-
| `mipmap` | A resources in the mipmap folder. The mipmap folder is usually where the launcher icon image is stored. |
70-
71-
### :chicken: ResourcePrefix
72-
73-
The resource prefix of the notification icon.
74-
75-
| Value | Description |
76-
|-------|-------------------------------------|
77-
| `ic` | A resources with the `ic_` prefix. |
78-
| `img` | A resources with the `img_` prefix. |
56+
| Property | Description |
57+
|-------------------|------------------------------------------------------------------------------------------------|
58+
| `metaDataName` | The name of the meta-data in the manifest that contains the drawable icon resource identifier. |
59+
| `backgroundColor` | The background color for the notification icon. |
7960

8061
### :chicken: NotificationButton
8162

example/android/app/src/main/AndroidManifest.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,14 @@
4646
android:foregroundServiceType="dataSync|remoteMessaging"
4747
android:exported="false" />
4848

49+
<!-- Custom notification icon. -->
50+
<meta-data
51+
android:name="com.your_package.service.HOME_ICON"
52+
android:resource="@drawable/ic_home" />
53+
<meta-data
54+
android:name="com.your_package.service.HEART_ICON"
55+
android:resource="@drawable/ic_heart" />
56+
4957
<!-- Don't delete the meta-data below.
5058
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
5159
<meta-data
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading

0 commit comments

Comments
 (0)