9
9
import android .content .pm .ApplicationInfo ;
10
10
import android .content .pm .PackageManager ;
11
11
import android .content .res .Resources ;
12
+ import android .media .AudioAttributes ;
12
13
import android .net .Uri ;
13
14
import android .os .Build ;
14
15
import android .os .Bundle ;
16
+ import android .provider .Settings ;
15
17
import android .service .notification .StatusBarNotification ;
16
18
19
+ import androidx .annotation .Nullable ;
17
20
import androidx .annotation .VisibleForTesting ;
18
21
import androidx .core .app .NotificationCompat ;
19
22
23
26
import java .util .Map ;
24
27
25
28
class IterableNotificationHelper {
26
- private static final String DEFAULT_CHANNEL_NAME = "iterable channel" ;
27
29
private static final String NO_BADGE = "_noBadge" ;
28
30
29
31
@ VisibleForTesting
@@ -101,8 +103,8 @@ public IterableNotificationBuilder createNotification(Context context, Bundle ex
101
103
String soundName = null ;
102
104
String messageId = null ;
103
105
String pushImage = null ;
106
+ Uri soundUri = null ;
104
107
//TODO: When backend supports channels, these strings needs to change (channelName, channelId, channelDescription).
105
- String channelName = getChannelName (context );
106
108
String channelDescription = "" ;
107
109
108
110
if (!extras .containsKey (IterableConstants .ITERABLE_DATA_KEY )) {
@@ -115,13 +117,36 @@ public IterableNotificationBuilder createNotification(Context context, Bundle ex
115
117
return null ;
116
118
}
117
119
118
- removeUnusedChannel (context );
119
- registerChannelIfEmpty (context , getChannelId (context ), channelName , channelDescription );
120
- IterableNotificationBuilder notificationBuilder = new IterableNotificationBuilder (context , getChannelId (context ));
121
120
JSONObject iterableJson = null ;
122
121
title = extras .getString (IterableConstants .ITERABLE_DATA_TITLE , applicationName );
123
122
notificationBody = extras .getString (IterableConstants .ITERABLE_DATA_BODY );
124
123
soundName = extras .getString (IterableConstants .ITERABLE_DATA_SOUND );
124
+ String soundUrl = null ;
125
+
126
+ //Check if soundName is a remote sound file
127
+ if (soundName != null ) {
128
+
129
+ // If soundname contains remote link, store it as a soundUrl and continue to trim soundName to for channel Id and name
130
+ if (soundName .contains ("https" )) {
131
+ soundUrl = soundName ;
132
+ soundName = soundName .substring (soundName .lastIndexOf ('/' ) + 1 );
133
+ }
134
+
135
+ // Remove extension of sound file
136
+ soundName = soundName .replaceFirst ("[.][^.]+$" , "" );
137
+ }
138
+
139
+ soundUri = getSoundUri (context , soundName , soundUrl );
140
+
141
+ String channelName = (soundUri == Settings .System .DEFAULT_NOTIFICATION_URI )
142
+ ? IterableConstants .NOTIFICATION_CHANNEL_NAME
143
+ : getChannelName (soundName );
144
+
145
+ String channelId = (soundUri == Settings .System .DEFAULT_NOTIFICATION_URI )
146
+ ? context .getPackageName ()
147
+ : getCurrentChannelId (context , soundName );
148
+
149
+ IterableNotificationBuilder notificationBuilder = new IterableNotificationBuilder (context , channelId );
125
150
126
151
String iterableData = extras .getString (IterableConstants .ITERABLE_DATA_KEY );
127
152
@@ -155,23 +180,6 @@ public IterableNotificationBuilder createNotification(Context context, Bundle ex
155
180
notificationBuilder .setImageUrl (pushImage );
156
181
notificationBuilder .setExpandedContent (notificationBody );
157
182
158
- if (soundName != null ) {
159
- //Removes the file type from the name
160
- String [] soundFile = soundName .split ("\\ ." );
161
- soundName = soundFile [0 ];
162
-
163
- if (!soundName .equalsIgnoreCase (IterableConstants .DEFAULT_SOUND )) {
164
- int soundID = context .getResources ().getIdentifier (soundName , IterableConstants .SOUND_FOLDER_IDENTIFIER , context .getPackageName ());
165
- Uri soundUri = Uri .parse (IterableConstants .ANDROID_RESOURCE_PATH + context .getPackageName () + "/" + soundID );
166
- notificationBuilder .setSound (soundUri );
167
- } else {
168
- notifPermissions .defaults |= Notification .DEFAULT_SOUND ;
169
- }
170
-
171
- } else {
172
- notifPermissions .defaults |= Notification .DEFAULT_SOUND ;
173
- }
174
-
175
183
// The notification doesn't cancel properly if requestCode is negative
176
184
notificationBuilder .requestCode = Math .abs ((int ) System .currentTimeMillis ());
177
185
IterableLogger .d (IterableNotificationBuilder .TAG , "Request code = " + notificationBuilder .requestCode );
@@ -223,6 +231,9 @@ public IterableNotificationBuilder createNotification(Context context, Bundle ex
223
231
224
232
notificationBuilder .setDefaults (notifPermissions .defaults );
225
233
234
+ removeUnusedChannel (context , soundName );
235
+ registerChannelIfEmpty (context , channelId , channelName , channelDescription , soundUri );
236
+
226
237
return notificationBuilder ;
227
238
}
228
239
@@ -255,7 +266,7 @@ public void postNotificationOnDevice(Context context, IterableNotificationBuilde
255
266
* @param channelName Sets the channel name that is shown to the user.
256
267
* @param channelDescription Sets the channel description that is shown to the user.
257
268
*/
258
- private void registerChannelIfEmpty (Context context , String channelId , String channelName , String channelDescription ) {
269
+ private void registerChannelIfEmpty (Context context , String channelId , String channelName , String channelDescription , Uri soundUri ) {
259
270
NotificationManager mNotificationManager = (NotificationManager )
260
271
context .getApplicationContext ().getSystemService (Context .NOTIFICATION_SERVICE );
261
272
if (android .os .Build .VERSION .SDK_INT >= android .os .Build .VERSION_CODES .O
@@ -264,21 +275,21 @@ private void registerChannelIfEmpty(Context context, String channelId, String ch
264
275
if (existingChannel == null || !existingChannel .getName ().equals (channelName )) {
265
276
IterableLogger .d (IterableNotificationBuilder .TAG , "Creating notification: channelId = " + channelId + " channelName = "
266
277
+ channelName + " channelDescription = " + channelDescription );
267
- mNotificationManager .createNotificationChannel (createNotificationChannel (channelId , channelName , channelDescription , context ));
278
+ mNotificationManager .createNotificationChannel (createNotificationChannel (channelId , channelName , channelDescription , context , soundUri ));
268
279
}
269
280
}
270
281
}
271
282
272
283
/**
273
284
* Safely removes unused and old channel if the configuration for notification badge is changed.
274
285
*/
275
- private void removeUnusedChannel (Context context ) {
286
+ private void removeUnusedChannel (Context context , String soundName ) {
276
287
NotificationManager mNotificationManager = (NotificationManager )
277
288
context .getApplicationContext ().getSystemService (Context .NOTIFICATION_SERVICE );
278
289
279
290
if (android .os .Build .VERSION .SDK_INT >= android .os .Build .VERSION_CODES .O
280
291
&& mNotificationManager != null ) {
281
- String channelIdToDelete = getOldChannelId (context );
292
+ String channelIdToDelete = getOldChannelId (context , soundName );
282
293
NotificationChannel unusedChannel = mNotificationManager .getNotificationChannel (channelIdToDelete );
283
294
if (unusedChannel != null ) {
284
295
for (StatusBarNotification activeNotification : mNotificationManager .getActiveNotifications ()) {
@@ -292,14 +303,18 @@ private void removeUnusedChannel(Context context) {
292
303
}
293
304
}
294
305
295
- private NotificationChannel createNotificationChannel (String channelId , String channelName , String channelDescription , Context context ) {
306
+ private NotificationChannel createNotificationChannel (String channelId , String channelName , String channelDescription , Context context , Uri soundUri ) {
296
307
NotificationChannel notificationChannel = null ;
308
+ AudioAttributes audioAttributes = getAudioAttributes ();
309
+
297
310
if (android .os .Build .VERSION .SDK_INT >= android .os .Build .VERSION_CODES .O ) {
298
311
notificationChannel = new NotificationChannel (channelId , channelName , NotificationManager .IMPORTANCE_HIGH );
299
312
notificationChannel .setDescription (channelDescription );
300
313
notificationChannel .enableLights (true );
301
314
notificationChannel .setShowBadge (isNotificationBadgingEnabled (context ));
315
+ notificationChannel .setSound (soundUri , audioAttributes );
302
316
}
317
+
303
318
return notificationChannel ;
304
319
}
305
320
@@ -315,16 +330,21 @@ private static boolean isNotificationBadgingEnabled(Context context) {
315
330
return true ;
316
331
}
317
332
318
- private String getChannelId (Context context ) {
319
- return getChannelIdName (context , true );
333
+ private String getCurrentChannelId (Context context , String soundName ) {
334
+ return getChannelIdName (context , true , soundName );
320
335
}
321
336
322
- private String getOldChannelId (Context context ) {
323
- return getChannelIdName (context , false );
337
+ private String getOldChannelId (Context context , String soundName ) {
338
+ return getChannelIdName (context , false , soundName );
324
339
}
325
340
326
- private String getChannelIdName (Context context , boolean isActive ) {
341
+ private String getChannelIdName (Context context , boolean isActive , String soundName ) {
327
342
String channelId = context .getPackageName ();
343
+
344
+ if (soundName != null ) {
345
+ channelId = soundName ;
346
+ }
347
+
328
348
if (isActive ) {
329
349
if (!isNotificationBadgingEnabled (context )) {
330
350
channelId = channelId + NO_BADGE ;
@@ -337,33 +357,14 @@ private String getChannelIdName(Context context, boolean isActive) {
337
357
return channelId ;
338
358
}
339
359
340
- private String getChannelName (Context context ) {
341
- String channelName = null ;
342
- try {
343
- ApplicationInfo info = context .getPackageManager ().getApplicationInfo (context .getPackageName (), PackageManager .GET_META_DATA );
344
- if (info .metaData != null ) {
345
- Object channelNameMetaData = info .metaData .get (IterableConstants .NOTIFICATION_CHANNEL_NAME );
346
- if (channelNameMetaData instanceof String ) {
347
- // Literal string value
348
- channelName = (String ) channelNameMetaData ;
349
- } else if (channelNameMetaData instanceof Integer ) {
350
- // Try to read from a string resource
351
- int stringId = (Integer ) channelNameMetaData ;
352
- if (stringId != 0 ) {
353
- channelName = context .getString (stringId );
354
- }
355
- }
356
- IterableLogger .d (IterableNotificationBuilder .TAG , "channel name: " + channelName );
357
- }
358
- } catch (Exception e ) {
359
- IterableLogger .e (IterableNotificationBuilder .TAG , "Error while retrieving channel name" , e );
360
- }
360
+ private String getChannelName (String soundName ) {
361
+ String channelName = IterableConstants .NOTIFICATION_CHANNEL_NAME ;
361
362
362
- if (channelName != null ) {
363
- return channelName ;
364
- } else {
365
- return DEFAULT_CHANNEL_NAME ;
363
+ if (soundName != null ) {
364
+ channelName = soundName ;
366
365
}
366
+
367
+ return channelName ;
367
368
}
368
369
369
370
/**
@@ -434,4 +435,33 @@ boolean isEmptyBody(Bundle extras) {
434
435
}
435
436
}
436
437
438
+ @ Nullable
439
+ private static AudioAttributes getAudioAttributes () {
440
+ AudioAttributes audioAttributes = null ;
441
+ if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .LOLLIPOP ) {
442
+ audioAttributes = new AudioAttributes .Builder ()
443
+ .setUsage (AudioAttributes .USAGE_NOTIFICATION )
444
+ .setContentType (AudioAttributes .CONTENT_TYPE_SONIFICATION )
445
+ .build ();
446
+ }
447
+ return audioAttributes ;
448
+ }
449
+
450
+ private static Uri getSoundUri (Context context , String soundName , String soundUrl ) {
451
+ int soundId = 0 ;
452
+
453
+ if (soundUrl != null ) {
454
+ return Uri .parse (soundUrl );
455
+ }
456
+
457
+ if (soundName != null ) {
458
+ soundId = context .getResources ().getIdentifier (soundName , IterableConstants .SOUND_FOLDER_IDENTIFIER , context .getPackageName ());
459
+ }
460
+
461
+ if (soundId == 0 ) {
462
+ return Settings .System .DEFAULT_NOTIFICATION_URI ;
463
+ }
464
+
465
+ return Uri .parse (IterableConstants .ANDROID_RESOURCE_PATH + context .getPackageName () + "/" + soundId );
466
+ }
437
467
}
0 commit comments