Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add function createChannel for custom Android channel support #1509

Merged
merged 3 commits into from
Jul 16, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,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