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

Commit c9aae3c

Browse files
committed
Refactor to preprare version 4.0.0.
1 parent d1dd76c commit c9aae3c

File tree

16 files changed

+464
-113
lines changed

16 files changed

+464
-113
lines changed

CHANGELOG.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,22 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
77

88
## [Unreleased]
99

10+
### Breaking changes
11+
12+
- Now local scheduled notifications trigger `onNotification`.
13+
- `RNPushNotificationRegistrationService` has been remove, old reference in AndroidManifest must be removed.
14+
- `Notifications.registerNotificationActions()` has been removed and is not required for `actions`.
15+
- `DeviceEventEmitter.addListener('notificationActionReceived', callback)` is replaced by `onAction`.
16+
1017
### Features
1118

19+
- (Android) `actions` accept an array of strings.
20+
- (Android) `invokeApp` allow you to handle actions in background without invoking the application.
21+
- (Android) `onAction` has been added to `.configure()` to handle action in background.
22+
- (Android) `PushNotification.invokeApp(notification)` allow you to invoke the application when in background (notification for initial notification).
23+
- (Android) `PushNotification.getChannels(callback)` allow you to get the list of channels.
24+
- (Android) `PushNotification.channelExists(channel_id, callback)` allow you to check of a channel exists.
25+
- (Android) `PushNotification.deleteChannel(channel_id)` allow you to delete a channel.
1226
- (Android) Add `largeIconUrl` to load a largeIcon based on Url. Based on [#1444](https://github.com/zo0r/react-native-push-notification/pull/1444)
1327
- (Android) Add `bigPictureUrl` to load a picture based on Url. Based on [#1444](https://github.com/zo0r/react-native-push-notification/pull/1444)
1428
- (Android) Add `shortcutId` for better badges management.
@@ -20,6 +34,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
2034
### Fixed
2135

2236
- (Android) Some options were ignored on scheduled/repeating notifications (allowWhileIdle, ignoreInForeground).
37+
- (Android/iOS) popInitialInotification might be ignored in `.configure()`
2338

2439
## [3.5.2] - 2020-05-25
2540

README.md

Lines changed: 57 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,9 @@ In your `android/app/src/main/AndroidManifest.xml`
8686
<!-- Change the value to true to enable pop-up for in foreground (remote-only, for local use ignoreInForeground) -->
8787
<meta-data android:name="com.dieam.reactnativepushnotification.notification_foreground"
8888
android:value="false"/>
89+
<!-- Change the value to false if you don't want the creation of the default channel -->
90+
<meta-data android:name="com.dieam.reactnativepushnotification.channel_create_default"
91+
android:value="true"/>
8992
<!-- Change the resource name to your App's accent color - or any other color you want -->
9093
<meta-data android:name="com.dieam.reactnativepushnotification.notification_color"
9194
android:resource="@color/white"/> <!-- or @android:color/{name} to use a standard color -->
@@ -224,6 +227,14 @@ PushNotification.configure({
224227
notification.finish(PushNotificationIOS.FetchResult.NoData);
225228
},
226229

230+
// (optional) Called when Registered Action is pressed and invokeApp is false, if true onNotification will be called (Android)
231+
onAction: function (notification) {
232+
console.log("ACTION:", notification.action);
233+
console.log("NOTIFICATION:", notification);
234+
235+
// process the action
236+
},
237+
227238
// IOS ONLY (optional): default: all - Permissions to register.
228239
permissions: {
229240
alert: true,
@@ -302,6 +313,7 @@ PushNotification.localNotification({
302313
channelId: "your-custom-channel-id", // (optional) custom channelId, if the channel doesn't exist, it will be created with options passed above (importance, vibration, sound). Once the channel is created, the channel will not be update. Make sure your channelId is different if you change these options. If you have created a custom channel, it will apply options of the channel.
303314

304315
actions: '["Yes", "No"]', // (Android only) See the doc for notification actions to know more
316+
invokeApp: true, // (optional) This enable click on actions to bring back the application to foreground or stay in background, default: true
305317

306318
/* iOS only properties */
307319
alertAction: "view", // (optional) default: view
@@ -349,13 +361,21 @@ This library doesn't include a full Channel Management at the moment. Channels a
349361
The pattern of `channel_id` is:
350362

351363
```
352-
rn-push-notification-channel-id(-soundname, default if playSound "-default")-(importance: default "4")-(vibration, default "300")
364+
rn-push-notification-channel-id-(importance: default "4")(-soundname, default if playSound "-default")-(vibration, default "300")
353365
```
354366

355-
By default, 2 channels are created:
367+
By default, 1 channel is created:
368+
369+
- rn-push-notification-channel-id-4-default-300 (used for remote notification if none already exist).
370+
371+
you can avoid the default creation by using this:
372+
373+
```xml
374+
<meta-data android:name="com.dieam.reactnativepushnotification.channel_create_default"
375+
android:value="false"/>
376+
```
356377

357-
- rn-push-notification-channel-id-default-4-300 (used for remote notification if none already exist).
358-
- rn-push-notification-channel-id-4-300 (previously used for remote notification but without sounds).
378+
**NOTE: Without channel, remote notifications don't work**
359379

360380
In the notifications options, you can provide a custom channel id with `channelId: "your-custom-channel-id"`, if the channel doesn't exist, it will be created with options passed above (importance, vibration, sound). Once the channel is created, the channel will not be update. Make sure your `channelId` is different if you change these options. If you have created a custom channel in another way, it will apply options of the channel.
361381

@@ -387,6 +407,37 @@ If you want to use a different default channel for remote notification, refer to
387407
android:value="@string/default_notification_channel_id" />
388408
```
389409

410+
### List channels
411+
412+
You can list available channels with:
413+
414+
```js
415+
PushNotification.getChannels(function(channel_ids) {
416+
console.log(channel_ids); // ['channel_id_1']
417+
});
418+
419+
```
420+
421+
### Channel exists
422+
423+
You can check if a channel exists with:
424+
425+
```js
426+
PushNotification.channelExists(function(exists) {
427+
console.log(exists); // true/false
428+
});
429+
430+
```
431+
432+
### List channels
433+
434+
You can list available channels with:
435+
436+
```js
437+
PushNotification.deleteChannel(channel_id);
438+
439+
```
440+
390441
## Cancelling notifications
391442

392443
### 1) cancelLocalNotifications
@@ -539,38 +590,11 @@ Property `repeatType` could be one of `month`, `week`, `day`, `hour`, `minute`,
539590

540591
(Android only) [Refer](https://github.com/zo0r/react-native-push-notification/issues/151) to this issue to see an example of a notification action.
541592

542-
Two things are required to setup notification actions.
543-
544-
### 1) Specify notification actions for a notification
545-
546593
This is done by specifying an `actions` parameters while configuring the local notification. This is an array of strings where each string is a notification action that will be presented with the notification.
547594

548-
For e.g. `actions: '["Accept", "Reject"]' // Must be in string format`
549-
550-
The array itself is specified in string format to circumvent some problems because of the way JSON arrays are handled by react-native android bridge.
551-
552-
### 2) Specify handlers for the notification actions
595+
For e.g. `actions: ['Accept', 'Reject']`
553596

554-
For each action specified in the `actions` field, we need to add a handler that is called when the user clicks on the action. This can be done in the `componentWillMount` of your main app file or in a separate file which is imported in your main app file. Notification actions handlers can be configured as below:
555-
556-
```
557-
import PushNotificationAndroid from 'react-native-push-notification'
558-
559-
(function() {
560-
// Register all the valid actions for notifications here and add the action handler for each action
561-
PushNotificationAndroid.registerNotificationActions(['Accept','Reject','Yes','No']);
562-
DeviceEventEmitter.addListener('notificationActionReceived', function(action){
563-
console.log ('Notification action received: ' + action);
564-
const info = JSON.parse(action.dataJSON);
565-
if (info.action == 'Accept') {
566-
// Do work pertaining to Accept action here
567-
} else if (info.action == 'Reject') {
568-
// Do work pertaining to Reject action here
569-
}
570-
// Add all the required actions handlers
571-
});
572-
})();
573-
```
597+
When you handle actions in background (`invokeApp: false`), you can open the application and pass the initial notification by using use `PushNotification.invokeApp(notification)`.
574598

575599
For iOS, you can use this [package](https://github.com/holmesal/react-native-ios-notification-actions) to add notification actions.
576600

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

Lines changed: 97 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import com.facebook.react.bridge.ReactContextBaseJavaModule;
2323
import com.facebook.react.bridge.ReactMethod;
2424
import com.facebook.react.bridge.ReadableArray;
25+
import com.facebook.react.bridge.WritableArray;
2526
import com.facebook.react.bridge.ReadableMap;
2627
import com.facebook.react.bridge.WritableMap;
2728

@@ -58,6 +59,8 @@ public RNPushNotification(ReactApplicationContext reactContext) {
5859
mJsDelivery = new RNPushNotificationJsDelivery(reactContext);
5960

6061
mRNPushNotificationHelper.checkOrCreateDefaultChannel();
62+
63+
registerNotificationsReceiveNotificationActions();
6164
}
6265

6366
@Override
@@ -92,30 +95,81 @@ public void onNewIntent(Intent intent) {
9295
}
9396
}
9497

95-
private void registerNotificationsReceiveNotificationActions(ReadableArray actions) {
98+
private void registerNotificationsReceiveNotificationActions() {
9699
IntentFilter intentFilter = new IntentFilter();
97-
// Add filter for each actions.
98-
for (int i = 0; i < actions.size(); i++) {
99-
String action = actions.getString(i);
100-
intentFilter.addAction(getReactApplicationContext().getPackageName() + "." + action);
100+
101+
for(int i = 0; i < 10; i++) {
102+
intentFilter.addAction(getReactApplicationContext().getPackageName() + ".ACTION_" + i);
101103
}
102104

105+
final RNPushNotification self = this;
106+
103107
getReactApplicationContext().registerReceiver(new BroadcastReceiver() {
104108
@Override
105109
public void onReceive(Context context, Intent intent) {
106110
Bundle bundle = intent.getBundleExtra("notification");
107111

108-
// Notify the action.
109-
mJsDelivery.notifyNotificationAction(bundle);
110-
111112
// Dismiss the notification popup.
112113
NotificationManager manager = (NotificationManager) context.getSystemService(context.NOTIFICATION_SERVICE);
113114
int notificationID = Integer.parseInt(bundle.getString("id"));
114-
manager.cancel(notificationID);
115+
116+
boolean autoCancel = bundle.getBoolean("autoCancel", true);
117+
118+
if(autoCancel) {
119+
if (bundle.containsKey("tag")) {
120+
String tag = bundle.getString("tag");
121+
manager.cancel(tag, notificationID);
122+
} else {
123+
manager.cancel(notificationID);
124+
}
125+
}
126+
127+
boolean invokeApp = bundle.getBoolean("invokeApp", true);
128+
129+
// Notify the action.
130+
if(invokeApp) {
131+
self.invokeApp(bundle);
132+
} else {
133+
mJsDelivery.notifyNotificationAction(bundle);
134+
}
115135
}
116136
}, intentFilter);
117137
}
118138

139+
private void invokeApp(Bundle bundle) {
140+
ReactContext reactContext = getReactApplicationContext();
141+
String packageName = reactContext.getPackageName();
142+
Intent launchIntent = reactContext.getPackageManager().getLaunchIntentForPackage(packageName);
143+
String className = launchIntent.getComponent().getClassName();
144+
145+
try {
146+
Class<?> activityClass = Class.forName(className);
147+
Intent activityIntent = new Intent(reactContext, activityClass);
148+
149+
if(bundle != null) {
150+
activityIntent.putExtra("notification", bundle);
151+
}
152+
153+
activityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
154+
155+
reactContext.startActivity(activityIntent);
156+
} catch(Exception e) {
157+
Log.e(LOG_TAG, "Class not found", e);
158+
return;
159+
}
160+
}
161+
162+
@ReactMethod
163+
public void invokeApp(ReadableMap data) {
164+
Bundle bundle = null;
165+
166+
if (data != null) {
167+
bundle = Arguments.toBundle(data);
168+
}
169+
170+
invokeApp(bundle);
171+
}
172+
119173
@ReactMethod
120174
public void checkPermissions(Promise promise) {
121175
ReactContext reactContext = getReactApplicationContext();
@@ -227,13 +281,8 @@ public void cancelLocalNotifications(ReadableMap userInfo) {
227281
/**
228282
* Clear notification from the notification centre.
229283
*/
230-
public void clearLocalNotification(int notificationID) {
231-
mRNPushNotificationHelper.clearNotification(notificationID);
232-
}
233-
234-
@ReactMethod
235-
public void registerNotificationActions(ReadableArray actions) {
236-
registerNotificationsReceiveNotificationActions(actions);
284+
public void clearLocalNotification(String tag, int notificationID) {
285+
mRNPushNotificationHelper.clearNotification(tag, notificationID);
237286
}
238287

239288
@ReactMethod
@@ -279,4 +328,36 @@ public void run() {
279328
}
280329
}).start();
281330
}
331+
332+
@ReactMethod
333+
/**
334+
* List all channels id
335+
*/
336+
public void getChannels(Callback callback) {
337+
WritableArray array = Arguments.fromList(mRNPushNotificationHelper.listChannels());
338+
339+
if(callback != null) {
340+
callback.invoke(array);
341+
}
342+
}
343+
344+
@ReactMethod
345+
/**
346+
* Check if channel exists with a given id
347+
*/
348+
public void channelExists(String channel_id, Callback callback) {
349+
boolean exists = mRNPushNotificationHelper.channelExists(channel_id);
350+
351+
if(callback != null) {
352+
callback.invoke(exists);
353+
}
354+
}
355+
356+
@ReactMethod
357+
/**
358+
* Delete channel with a given id
359+
*/
360+
public void deleteChannel(String channel_id) {
361+
mRNPushNotificationHelper.deleteChannel(channel_id);
362+
}
282363
}

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ public class RNPushNotificationAttributes {
3838
private static final String VIBRATE = "vibrate";
3939
private static final String VIBRATION = "vibration";
4040
private static final String ACTIONS = "actions";
41+
private static final String INVOKE_APP = "invokeApp";
4142
private static final String TAG = "tag";
4243
private static final String REPEAT_TYPE = "repeatType";
4344
private static final String REPEAT_TIME = "repeatTime";
@@ -70,6 +71,7 @@ public class RNPushNotificationAttributes {
7071
private final boolean vibrate;
7172
private final double vibration;
7273
private final String actions;
74+
private final boolean invokeApp;
7375
private final String tag;
7476
private final String repeatType;
7577
private final double repeatTime;
@@ -103,6 +105,7 @@ public RNPushNotificationAttributes(Bundle bundle) {
103105
vibrate = bundle.getBoolean(VIBRATE);
104106
vibration = bundle.getDouble(VIBRATION);
105107
actions = bundle.getString(ACTIONS);
108+
invokeApp = bundle.getBoolean(INVOKE_APP);
106109
tag = bundle.getString(TAG);
107110
repeatType = bundle.getString(REPEAT_TYPE);
108111
repeatTime = bundle.getDouble(REPEAT_TIME);
@@ -138,6 +141,7 @@ private RNPushNotificationAttributes(JSONObject jsonObject) {
138141
vibrate = jsonObject.has(VIBRATE) ? jsonObject.getBoolean(VIBRATE) : true;
139142
vibration = jsonObject.has(VIBRATION) ? jsonObject.getDouble(VIBRATION) : 1000;
140143
actions = jsonObject.has(ACTIONS) ? jsonObject.getString(ACTIONS) : null;
144+
invokeApp = jsonObject.has(INVOKE_APP) ? jsonObject.getBoolean(INVOKE_APP) : true;
141145
tag = jsonObject.has(TAG) ? jsonObject.getString(TAG) : null;
142146
repeatType = jsonObject.has(REPEAT_TYPE) ? jsonObject.getString(REPEAT_TYPE) : null;
143147
repeatTime = jsonObject.has(REPEAT_TIME) ? jsonObject.getDouble(REPEAT_TIME) : 0.0;
@@ -230,6 +234,7 @@ public Bundle toBundle() {
230234
bundle.putBoolean(VIBRATE, vibrate);
231235
bundle.putDouble(VIBRATION, vibration);
232236
bundle.putString(ACTIONS, actions);
237+
bundle.putBoolean(INVOKE_APP, invokeApp);
233238
bundle.putString(TAG, tag);
234239
bundle.putString(REPEAT_TYPE, repeatType);
235240
bundle.putDouble(REPEAT_TIME, repeatTime);
@@ -267,6 +272,7 @@ public JSONObject toJson() {
267272
jsonObject.put(VIBRATE, vibrate);
268273
jsonObject.put(VIBRATION, vibration);
269274
jsonObject.put(ACTIONS, actions);
275+
jsonObject.put(INVOKE_APP, invokeApp);
270276
jsonObject.put(TAG, tag);
271277
jsonObject.put(REPEAT_TYPE, repeatType);
272278
jsonObject.put(REPEAT_TIME, repeatTime);
@@ -310,6 +316,7 @@ public String toString() {
310316
", vibrate=" + vibrate +
311317
", vibration=" + vibration +
312318
", actions='" + actions + '\'' +
319+
", invokeApp=" + invokeApp +
313320
", tag='" + tag + '\'' +
314321
", repeatType='" + repeatType + '\'' +
315322
", repeatTime=" + repeatTime +

0 commit comments

Comments
 (0)