Skip to content

Commit

Permalink
Merge pull request #1509 from Adapptor/precreate-channels
Browse files Browse the repository at this point in the history
Add function createChannel for custom Android channel support
  • Loading branch information
Dallas62 authored Jul 16, 2020
2 parents e914173 + 57ce995 commit 3e4930d
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 26 deletions.
18 changes: 17 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,23 @@ In the location notification json specify the full file name:

## Channel Management (Android)

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`.
To use custom channels, create them at startup and pass the matching `channelId` through to `PushNotification.localNotification`

```javascript
PushNotification.createChannel(
{
channelId: "custom-channel-id", // (required)
channelName: "Custom channel", // (required)
channelDesc: "A custom channel to categorise your custom notifications", // (optional) default: undefined.
soundName: "default", // (optional) See `soundName` parameter of `localNotification` function
importance: 4, // (optional) default: 4. Int value of the Android notification importance
vibrate: true, // (optional) default: true. Creates the default vibration patten if true.
},
(created: any) => console.log(`createChannel returned '${created}'`) // (optional) callback returns whether the channel was created, false means it already existed.
);
```

Channels with ids that do not exist are generated on the fly when you pass options to `PushNotification.localNotification` or `PushNotification.localNotificationSchedule`.

The pattern of `channel_id` is:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,18 @@ public void channelExists(String channel_id, Callback callback) {
}
}

@ReactMethod
/**
* Creates a channel if it does not already exist. Returns whether the channel was created.
*/
public void createChannel(ReadableMap channelInfo, Callback callback) {
boolean created = mRNPushNotificationHelper.createChannel(channelInfo);

if(callback != null) {
callback.invoke(created);
}
}

@ReactMethod
/**
* Check if channel is blocked with a given id
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -428,31 +428,13 @@ public void sendToNotificationCentreWithPicture(Bundle bundle, Bitmap largeIconB
Uri soundUri = null;

if (!bundle.containsKey("playSound") || bundle.getBoolean("playSound")) {
soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);

String soundName = bundle.getString("soundName");

if (soundName != null) {
if (!"default".equalsIgnoreCase(soundName)) {

// sound name can be full filename, or just the resource name.
// So the strings 'my_sound.mp3' AND 'my_sound' are accepted
// The reason is to make the iOS and android javascript interfaces compatible

int resId;
if (context.getResources().getIdentifier(soundName, "raw", context.getPackageName()) != 0) {
resId = context.getResources().getIdentifier(soundName, "raw", context.getPackageName());
} else {
soundName = soundName.substring(0, soundName.lastIndexOf('.'));
resId = context.getResources().getIdentifier(soundName, "raw", context.getPackageName());
}

soundUri = Uri.parse("android.resource://" + context.getPackageName() + "/" + resId);
}
} else {
if (soundName == null) {
soundName = "default";
}

soundUri = getSoundUri(soundName);

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { // API 26 and higher
channel_id = channel_id + "-" + soundName;
}
Expand Down Expand Up @@ -676,6 +658,27 @@ private void scheduleNextNotificationIfRepeating(Bundle bundle) {
}
}

private Uri getSoundUri(String soundName) {
if (soundName == null || "default".equalsIgnoreCase(soundName)) {
return RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
} else {

// sound name can be full filename, or just the resource name.
// So the strings 'my_sound.mp3' AND 'my_sound' are accepted
// The reason is to make the iOS and android javascript interfaces compatible

int resId;
if (context.getResources().getIdentifier(soundName, "raw", context.getPackageName()) != 0) {
resId = context.getResources().getIdentifier(soundName, "raw", context.getPackageName());
} else {
soundName = soundName.substring(0, soundName.lastIndexOf('.'));
resId = context.getResources().getIdentifier(soundName, "raw", context.getPackageName());
}

return Uri.parse("android.resource://" + context.getPackageName() + "/" + resId);
}
}

public void clearNotifications() {
Log.i(LOG_TAG, "Clearing alerts from the notification centre");

Expand Down Expand Up @@ -899,11 +902,11 @@ public void deleteChannel(String channel_id) {
manager.deleteNotificationChannel(channel_id);
}

private void checkOrCreateChannel(NotificationManager manager, String channel_id, String channel_name, String channel_description, Uri soundUri, int importance, long[] vibratePattern) {
private boolean checkOrCreateChannel(NotificationManager manager, String channel_id, String channel_name, String channel_description, Uri soundUri, int importance, long[] vibratePattern) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O)
return;
return false;
if (manager == null)
return;
return false;

NotificationChannel channel = manager.getNotificationChannel(channel_id);

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

channel.setDescription(channel_description);
channel.enableLights(true);
channel.enableVibration(true);
channel.enableVibration(vibratePattern != null);
channel.setVibrationPattern(vibratePattern);

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

manager.createNotificationChannel(channel);
return true;
}
return false;
}

public boolean createChannel(ReadableMap channelInfo) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O)
return false;

String channelId = channelInfo.getString("channelId");
String channelName = channelInfo.getString("channelName");
String channelDesc = channelInfo.hasKey("channelDesc") ? channelInfo.getString("channelDesc") : null;
String soundName = channelInfo.hasKey("soundName") ? channelInfo.getString("soundName") : "default";
int importance = channelInfo.hasKey("importance") ? channelInfo.getInt("importance") : 4;
boolean vibrate = channelInfo.hasKey("vibrate") && channelInfo.getBoolean("vibrate");
long[] vibratePattern = vibrate ? new long[] { DEFAULT_VIBRATION } : null;

NotificationManager manager = notificationManager();

Uri soundUri = getSoundUri(soundName);

return checkOrCreateChannel(manager, channelId, channelName, channelDesc, soundUri, importance, vibratePattern);
}

public boolean isApplicationInForeground(Context context) {
Expand Down
4 changes: 4 additions & 0 deletions component/index.android.js
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,10 @@ NotificationsComponent.prototype.channelExists = function(channel_id, callback)
RNPushNotification.channelExists(channel_id, callback);
}

NotificationsComponent.prototype.createChannel = function(channelInfo, callback) {
RNPushNotification.createChannel(channelInfo, callback);
}

NotificationsComponent.prototype.channelBlocked = function(channel_id, callback) {
RNPushNotification.channelBlocked(channel_id, callback);
}
Expand Down
4 changes: 4 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -513,6 +513,10 @@ Notifications.channelExists = function() {
return this.callNative('channelExists', arguments);
};

Notifications.createChannel = function() {
return this.callNative('createChannel', arguments);
};

Notifications.channelBlocked = function() {
return this.callNative('channelBlocked', arguments);
};
Expand Down

0 comments on commit 3e4930d

Please sign in to comment.