12
12
import android .net .Uri ;
13
13
import android .os .Build ;
14
14
import android .os .Bundle ;
15
+ import android .service .notification .StatusBarNotification ;
16
+
15
17
import androidx .annotation .VisibleForTesting ;
16
18
import androidx .core .app .NotificationCompat ;
17
19
22
24
23
25
class IterableNotificationHelper {
24
26
private static final String DEFAULT_CHANNEL_NAME = "iterable channel" ;
27
+ private static final String NO_BADGE = "_noBadge" ;
25
28
26
29
@ VisibleForTesting
27
30
static IterableNotificationHelperImpl instance = new IterableNotificationHelperImpl ();
@@ -100,7 +103,6 @@ public IterableNotificationBuilder createNotification(Context context, Bundle ex
100
103
String pushImage = null ;
101
104
//TODO: When backend supports channels, these strings needs to change (channelName, channelId, channelDescription).
102
105
String channelName = getChannelName (context );
103
- String channelId = context .getPackageName ();
104
106
String channelDescription = "" ;
105
107
106
108
if (!extras .containsKey (IterableConstants .ITERABLE_DATA_KEY )) {
@@ -113,8 +115,9 @@ public IterableNotificationBuilder createNotification(Context context, Bundle ex
113
115
return null ;
114
116
}
115
117
116
- registerChannelIfEmpty (context , channelId , channelName , channelDescription );
117
- IterableNotificationBuilder notificationBuilder = new IterableNotificationBuilder (context , context .getPackageName ());
118
+ removeUnusedChannel (context );
119
+ registerChannelIfEmpty (context , getChannelId (context ), channelName , channelDescription );
120
+ IterableNotificationBuilder notificationBuilder = new IterableNotificationBuilder (context , getChannelId (context ));
118
121
JSONObject iterableJson = null ;
119
122
title = extras .getString (IterableConstants .ITERABLE_DATA_TITLE , applicationName );
120
123
notificationBody = extras .getString (IterableConstants .ITERABLE_DATA_BODY );
@@ -261,21 +264,79 @@ private void registerChannelIfEmpty(Context context, String channelId, String ch
261
264
if (existingChannel == null || !existingChannel .getName ().equals (channelName )) {
262
265
IterableLogger .d (IterableNotificationBuilder .TAG , "Creating notification: channelId = " + channelId + " channelName = "
263
266
+ channelName + " channelDescription = " + channelDescription );
264
- mNotificationManager .createNotificationChannel (createNotificationChannel (channelId , channelName , channelDescription ));
267
+ mNotificationManager .createNotificationChannel (createNotificationChannel (channelId , channelName , channelDescription , context ));
265
268
}
266
269
}
267
270
}
268
271
269
- private NotificationChannel createNotificationChannel (String channelId , String channelName , String channelDescription ) {
272
+ /**
273
+ * Safely removes unused and old channel if the configuration for notification badge is changed.
274
+ */
275
+ private void removeUnusedChannel (Context context ) {
276
+ NotificationManager mNotificationManager = (NotificationManager )
277
+ context .getApplicationContext ().getSystemService (Context .NOTIFICATION_SERVICE );
278
+
279
+ if (android .os .Build .VERSION .SDK_INT >= android .os .Build .VERSION_CODES .O
280
+ && mNotificationManager != null ) {
281
+ String channelIdToDelete = getOldChannelId (context );
282
+ NotificationChannel unusedChannel = mNotificationManager .getNotificationChannel (channelIdToDelete );
283
+ if (unusedChannel != null ) {
284
+ for (StatusBarNotification activeNotification : mNotificationManager .getActiveNotifications ()) {
285
+ if (activeNotification .getNotification ().getChannelId () == channelIdToDelete ) {
286
+ IterableLogger .d (IterableNotificationBuilder .TAG , "Not Deleting the channel as there are active notification for old channel" );
287
+ return ;
288
+ }
289
+ }
290
+ mNotificationManager .deleteNotificationChannel (channelIdToDelete );
291
+ }
292
+ }
293
+ }
294
+
295
+ private NotificationChannel createNotificationChannel (String channelId , String channelName , String channelDescription , Context context ) {
270
296
NotificationChannel notificationChannel = null ;
271
297
if (android .os .Build .VERSION .SDK_INT >= android .os .Build .VERSION_CODES .O ) {
272
298
notificationChannel = new NotificationChannel (channelId , channelName , NotificationManager .IMPORTANCE_HIGH );
273
299
notificationChannel .setDescription (channelDescription );
274
300
notificationChannel .enableLights (true );
301
+ notificationChannel .setShowBadge (isNotificationBadgingEnabled (context ));
275
302
}
276
303
return notificationChannel ;
277
304
}
278
305
306
+ private static boolean isNotificationBadgingEnabled (Context context ) {
307
+ try {
308
+ ApplicationInfo info = context .getPackageManager ().getApplicationInfo (context .getPackageName (), PackageManager .GET_META_DATA );
309
+ if (info .metaData != null ) {
310
+ return info .metaData .getBoolean (IterableConstants .NOTIFICAION_BADGING , true );
311
+ }
312
+ } catch (PackageManager .NameNotFoundException e ) {
313
+ IterableLogger .e (IterableNotificationBuilder .TAG , e .getLocalizedMessage () + " Failed to read notification badge settings. Setting to defaults - true" );
314
+ }
315
+ return true ;
316
+ }
317
+
318
+ private String getChannelId (Context context ) {
319
+ return getChannelIdName (context , true );
320
+ }
321
+
322
+ private String getOldChannelId (Context context ) {
323
+ return getChannelIdName (context , false );
324
+ }
325
+
326
+ private String getChannelIdName (Context context , boolean isActive ) {
327
+ String channelId = context .getPackageName ();
328
+ if (isActive ) {
329
+ if (!isNotificationBadgingEnabled (context )) {
330
+ channelId = channelId + NO_BADGE ;
331
+ }
332
+ } else {
333
+ if (isNotificationBadgingEnabled (context )) {
334
+ channelId = channelId + NO_BADGE ;
335
+ }
336
+ }
337
+ return channelId ;
338
+ }
339
+
279
340
private String getChannelName (Context context ) {
280
341
String channelName = null ;
281
342
try {
0 commit comments