1212import android .net .Uri ;
1313import android .os .Build ;
1414import android .os .Bundle ;
15+ import android .service .notification .StatusBarNotification ;
16+
1517import androidx .annotation .VisibleForTesting ;
1618import androidx .core .app .NotificationCompat ;
1719
2224
2325class IterableNotificationHelper {
2426 private static final String DEFAULT_CHANNEL_NAME = "iterable channel" ;
27+ private static final String NO_BADGE = "_noBadge" ;
2528
2629 @ VisibleForTesting
2730 static IterableNotificationHelperImpl instance = new IterableNotificationHelperImpl ();
@@ -100,7 +103,6 @@ public IterableNotificationBuilder createNotification(Context context, Bundle ex
100103 String pushImage = null ;
101104 //TODO: When backend supports channels, these strings needs to change (channelName, channelId, channelDescription).
102105 String channelName = getChannelName (context );
103- String channelId = context .getPackageName ();
104106 String channelDescription = "" ;
105107
106108 if (!extras .containsKey (IterableConstants .ITERABLE_DATA_KEY )) {
@@ -113,8 +115,9 @@ public IterableNotificationBuilder createNotification(Context context, Bundle ex
113115 return null ;
114116 }
115117
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 ));
118121 JSONObject iterableJson = null ;
119122 title = extras .getString (IterableConstants .ITERABLE_DATA_TITLE , applicationName );
120123 notificationBody = extras .getString (IterableConstants .ITERABLE_DATA_BODY );
@@ -261,21 +264,79 @@ private void registerChannelIfEmpty(Context context, String channelId, String ch
261264 if (existingChannel == null || !existingChannel .getName ().equals (channelName )) {
262265 IterableLogger .d (IterableNotificationBuilder .TAG , "Creating notification: channelId = " + channelId + " channelName = "
263266 + channelName + " channelDescription = " + channelDescription );
264- mNotificationManager .createNotificationChannel (createNotificationChannel (channelId , channelName , channelDescription ));
267+ mNotificationManager .createNotificationChannel (createNotificationChannel (channelId , channelName , channelDescription , context ));
265268 }
266269 }
267270 }
268271
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 ) {
270296 NotificationChannel notificationChannel = null ;
271297 if (android .os .Build .VERSION .SDK_INT >= android .os .Build .VERSION_CODES .O ) {
272298 notificationChannel = new NotificationChannel (channelId , channelName , NotificationManager .IMPORTANCE_HIGH );
273299 notificationChannel .setDescription (channelDescription );
274300 notificationChannel .enableLights (true );
301+ notificationChannel .setShowBadge (isNotificationBadgingEnabled (context ));
275302 }
276303 return notificationChannel ;
277304 }
278305
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+
279340 private String getChannelName (Context context ) {
280341 String channelName = null ;
281342 try {
0 commit comments