Skip to content
This repository was archived by the owner on Jan 14, 2025. It is now read-only.

Commit 3e4930d

Browse files
authored
Merge pull request #1509 from Adapptor/precreate-channels
Add function createChannel for custom Android channel support
2 parents e914173 + 57ce995 commit 3e4930d

File tree

5 files changed

+86
-26
lines changed

5 files changed

+86
-26
lines changed

README.md

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -368,7 +368,23 @@ In the location notification json specify the full file name:
368368

369369
## Channel Management (Android)
370370

371-
This library doesn't include a full Channel Management at the moment. Channels are generated on the fly when you pass options to `PushNotification.localNotification` or `PushNotification.localNotificationSchedule`.
371+
To use custom channels, create them at startup and pass the matching `channelId` through to `PushNotification.localNotification`
372+
373+
```javascript
374+
PushNotification.createChannel(
375+
{
376+
channelId: "custom-channel-id", // (required)
377+
channelName: "Custom channel", // (required)
378+
channelDesc: "A custom channel to categorise your custom notifications", // (optional) default: undefined.
379+
soundName: "default", // (optional) See `soundName` parameter of `localNotification` function
380+
importance: 4, // (optional) default: 4. Int value of the Android notification importance
381+
vibrate: true, // (optional) default: true. Creates the default vibration patten if true.
382+
},
383+
(created: any) => console.log(`createChannel returned '${created}'`) // (optional) callback returns whether the channel was created, false means it already existed.
384+
);
385+
```
386+
387+
Channels with ids that do not exist are generated on the fly when you pass options to `PushNotification.localNotification` or `PushNotification.localNotificationSchedule`.
372388

373389
The pattern of `channel_id` is:
374390

android/src/main/java/com/dieam/reactnativepushnotification/modules/RNPushNotification.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,18 @@ public void channelExists(String channel_id, Callback callback) {
297297
}
298298
}
299299

300+
@ReactMethod
301+
/**
302+
* Creates a channel if it does not already exist. Returns whether the channel was created.
303+
*/
304+
public void createChannel(ReadableMap channelInfo, Callback callback) {
305+
boolean created = mRNPushNotificationHelper.createChannel(channelInfo);
306+
307+
if(callback != null) {
308+
callback.invoke(created);
309+
}
310+
}
311+
300312
@ReactMethod
301313
/**
302314
* Check if channel is blocked with a given id

android/src/main/java/com/dieam/reactnativepushnotification/modules/RNPushNotificationHelper.java

Lines changed: 49 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -428,31 +428,13 @@ public void sendToNotificationCentreWithPicture(Bundle bundle, Bitmap largeIconB
428428
Uri soundUri = null;
429429

430430
if (!bundle.containsKey("playSound") || bundle.getBoolean("playSound")) {
431-
soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
432-
433431
String soundName = bundle.getString("soundName");
434-
435-
if (soundName != null) {
436-
if (!"default".equalsIgnoreCase(soundName)) {
437-
438-
// sound name can be full filename, or just the resource name.
439-
// So the strings 'my_sound.mp3' AND 'my_sound' are accepted
440-
// The reason is to make the iOS and android javascript interfaces compatible
441-
442-
int resId;
443-
if (context.getResources().getIdentifier(soundName, "raw", context.getPackageName()) != 0) {
444-
resId = context.getResources().getIdentifier(soundName, "raw", context.getPackageName());
445-
} else {
446-
soundName = soundName.substring(0, soundName.lastIndexOf('.'));
447-
resId = context.getResources().getIdentifier(soundName, "raw", context.getPackageName());
448-
}
449-
450-
soundUri = Uri.parse("android.resource://" + context.getPackageName() + "/" + resId);
451-
}
452-
} else {
432+
if (soundName == null) {
453433
soundName = "default";
454434
}
455435

436+
soundUri = getSoundUri(soundName);
437+
456438
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { // API 26 and higher
457439
channel_id = channel_id + "-" + soundName;
458440
}
@@ -676,6 +658,27 @@ private void scheduleNextNotificationIfRepeating(Bundle bundle) {
676658
}
677659
}
678660

661+
private Uri getSoundUri(String soundName) {
662+
if (soundName == null || "default".equalsIgnoreCase(soundName)) {
663+
return RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
664+
} else {
665+
666+
// sound name can be full filename, or just the resource name.
667+
// So the strings 'my_sound.mp3' AND 'my_sound' are accepted
668+
// The reason is to make the iOS and android javascript interfaces compatible
669+
670+
int resId;
671+
if (context.getResources().getIdentifier(soundName, "raw", context.getPackageName()) != 0) {
672+
resId = context.getResources().getIdentifier(soundName, "raw", context.getPackageName());
673+
} else {
674+
soundName = soundName.substring(0, soundName.lastIndexOf('.'));
675+
resId = context.getResources().getIdentifier(soundName, "raw", context.getPackageName());
676+
}
677+
678+
return Uri.parse("android.resource://" + context.getPackageName() + "/" + resId);
679+
}
680+
}
681+
679682
public void clearNotifications() {
680683
Log.i(LOG_TAG, "Clearing alerts from the notification centre");
681684

@@ -899,11 +902,11 @@ public void deleteChannel(String channel_id) {
899902
manager.deleteNotificationChannel(channel_id);
900903
}
901904

902-
private void checkOrCreateChannel(NotificationManager manager, String channel_id, String channel_name, String channel_description, Uri soundUri, int importance, long[] vibratePattern) {
905+
private boolean checkOrCreateChannel(NotificationManager manager, String channel_id, String channel_name, String channel_description, Uri soundUri, int importance, long[] vibratePattern) {
903906
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O)
904-
return;
907+
return false;
905908
if (manager == null)
906-
return;
909+
return false;
907910

908911
NotificationChannel channel = manager.getNotificationChannel(channel_id);
909912

@@ -920,7 +923,7 @@ private void checkOrCreateChannel(NotificationManager manager, String channel_id
920923

921924
channel.setDescription(channel_description);
922925
channel.enableLights(true);
923-
channel.enableVibration(true);
926+
channel.enableVibration(vibratePattern != null);
924927
channel.setVibrationPattern(vibratePattern);
925928

926929
if (soundUri != null) {
@@ -935,7 +938,28 @@ private void checkOrCreateChannel(NotificationManager manager, String channel_id
935938
}
936939

937940
manager.createNotificationChannel(channel);
941+
return true;
938942
}
943+
return false;
944+
}
945+
946+
public boolean createChannel(ReadableMap channelInfo) {
947+
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O)
948+
return false;
949+
950+
String channelId = channelInfo.getString("channelId");
951+
String channelName = channelInfo.getString("channelName");
952+
String channelDesc = channelInfo.hasKey("channelDesc") ? channelInfo.getString("channelDesc") : null;
953+
String soundName = channelInfo.hasKey("soundName") ? channelInfo.getString("soundName") : "default";
954+
int importance = channelInfo.hasKey("importance") ? channelInfo.getInt("importance") : 4;
955+
boolean vibrate = channelInfo.hasKey("vibrate") && channelInfo.getBoolean("vibrate");
956+
long[] vibratePattern = vibrate ? new long[] { DEFAULT_VIBRATION } : null;
957+
958+
NotificationManager manager = notificationManager();
959+
960+
Uri soundUri = getSoundUri(soundName);
961+
962+
return checkOrCreateChannel(manager, channelId, channelName, channelDesc, soundUri, importance, vibratePattern);
939963
}
940964

941965
public boolean isApplicationInForeground(Context context) {

component/index.android.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,10 @@ NotificationsComponent.prototype.channelExists = function(channel_id, callback)
154154
RNPushNotification.channelExists(channel_id, callback);
155155
}
156156

157+
NotificationsComponent.prototype.createChannel = function(channelInfo, callback) {
158+
RNPushNotification.createChannel(channelInfo, callback);
159+
}
160+
157161
NotificationsComponent.prototype.channelBlocked = function(channel_id, callback) {
158162
RNPushNotification.channelBlocked(channel_id, callback);
159163
}

index.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,10 @@ Notifications.channelExists = function() {
513513
return this.callNative('channelExists', arguments);
514514
};
515515

516+
Notifications.createChannel = function() {
517+
return this.callNative('createChannel', arguments);
518+
};
519+
516520
Notifications.channelBlocked = function() {
517521
return this.callNative('channelBlocked', arguments);
518522
};

0 commit comments

Comments
 (0)