Before submitting an issue please take a moment to read though the following. Most issues are common and some solutions are listed here.
Known bugs and issues:
- (Android) Tapping an alert in the notification centre will sometimes not result in
onNotification
being called issue 281 - (Android) Not all local notification features are supported yet (PRs welcome)
- (iOS) The OS can penalise your app for not calling the completion handler and will stop (or delay) sending notifications to your app. This will be supported from RN-0.38 PR 227
- Use a physical device for remote push notifications. They will not work on an emulator.
- Try "grepping" logcat for
ReactNativeJS|RNPushNotification
at debug level - it will likely shed some light onto whats happening. - Your GCM
senderID
can be obtained by obtaining a file from your google console calledgoogle-services.json
. From this file use theproject_number
as your ID. Native module cannot be null
error happens when your project isn't linked correctly. Please re-read the installation instructions, specifically the bit aboutreact-native link
andMainApplication.java
.- Take a look at the google docs for more about remote push notifications.
- Bages do not work on all devices, you should see an error being logged once when the app starts if the setting a badge isn't supported.
- Use a physical device for remote push notifications. They will not work on a simulator.
- Add a log statement (
NSLog(@"push-notification received: %@", notification);
) to yourdidReceiveRemoteNotification
method inAppDelegate.m
- Look out for
APNS
log messages in the device logs.
There are a number of different types of notification, and they have subtly different behaviours. There are essentially 4 types, let's call them local notifications (1), noisy remote push notifications (2), silent remote push notifications (3) and mixed remote push notifications (4).
Local notifications are sent from your JS/RN app and appear as alerts in the notification centre, where they sit until the user removes them. They can contain text as well as sounds, vibrations, colour, images etc. Different operating systems support different features. You can send one by calling the PushNotification.localNotification
method as described in the docs. Local notifications can also be scheduled to run at a later date.
If a user taps an alert, your app will be started or brought to the foreground and onNotification
will be called.
These are highly customisable (more so than noisy remote push notifications) but this library doesn't yet support all features, for example you cannot stack notification using the "grouping" feature.
Noisy remote push notifications are sent from a server, such as the Apple Push Notification Service (APNS), or the Google Cloud Messaging Service (GCM). When the app is in the background, they appear only as alerts in the notification centre and may not interact with your application in any way when they are delivered. Like local notifications they have a visual (or audible) element.
When a user taps an alert in the notification centre that was created by a noisy remote push notification, your app will be either started or brought to the foreground. The onNotification
method will fired.
Your server will send something like this to GCM:
{
"to": "<token>",
"time_to_live": 86400,
"collapse_key": "new_message",
"delay_while_idle": false,
"notification": {
"title": "title",
"body": "this is a noisy test",
"tag": "new_message",
"icon": "new_message",
"color": "#18d821",
"sound": "default"
}
}
Your app will not be invoked when this is received.
Your server will send something like this to APNS:
{
"aps": {
"alert": {
"body": "the body text",
"title": "the title"
},
"badge": 6,
"sound": " default"
}
}
Your app will not be invoked if it is running in the background, and the notification will result in an alert in the notification centre. If you app is running in the foreground, onNotification
will be called with something like:
{
"foreground": true,
"userInteraction": false,
"message": {
"title": "the title",
"body": "the body text"
},
"data": {
"remote": true,
"notificationId": "A3DC5EEE-FF97-4695-B562-3A7E89E43199"
},
"badge": 4,
"alert": {
"title": "the title",
"body": "the body text"
},
"sound": " default"
}
Tapping the alert in the notification centre will start or bring the app to the foreground and onNotification
will be called.
Silent remote push notifications are also sent from a server. They are delivered to your app but not to the notification centre, and as such have no visual or audible content. When receiving a notification the onNotification
in your JS app will be called. The app can be running in the foreground or background, the notification will always be delivered to the app.
Using a silent remote push notifications which in turn creates a customised local notification is a common pattern for providing a rich user experience.
Your server will send something like this to GCM:
{
"to": "<token>",
"time_to_live": 86400,
"collapse_key": "new_message",
"delay_while_idle": false,
"data": {
"your-key": "your-value"
}
}
The crucial bit is presence of the data
field. Your RN/JS app will receive something like:
{
"foreground": true,
"your-key": "your-value",
"google.sent_time": 1478872536263,
"userInteraction": false,
"google.message_id": "0:999999999999",
"collapse_key": "new_message"
}
If your Android app is not running when a silent notification is received then this library will start it. It will be started in the background however, and if the OS starts your app in this way it will not start the react-native lifecycle. This means that if your notification delivery code relies on the react-native lifecycle then it will not get invoked in this situation. You need to structure your app in such a way that PushNotification.configure
gets called as a side effect of merely importing the root index.android.js
file.
Send something like this to the APNS (here are the docs):
{
"aps": {
"content-available": 1
},
"payload": "{\"your-key\":\"your-value\"}"
}
This is a pure silent push notification. It must not include a badge, sound or any alert text. These types of silent notifications are of limited use. They MUST be sent with a priority of 5 (10 is the default) and are subject to delays - basically, the OS may delay delivery if the battery is low and the phone isn't plugged in.
You can create an alternative non-pure iOS silent push notification by adding an empty string as the alert body or sound name (see this discussion). This will be delivered as a high priority message and will not be subject to OS imposed delays. Obviously this is a bit of a hack. A better approach to silent push notifications is to use react-native-voip-push-notification.
The crucial bit of an iOS silent notification is presence of the "content-available": 1
field. Your RN/JS app will receive something like:
{
"foreground": true,
"userInteraction": false,
"data": {
"remote": true,
"payload": "{\"your-key\":\"your-value\"}",
"notificationId": "8D8C24FF-B4F0-4D13-BA0E-295D0E474279"
}
}
After you have processed the notification you must call isn't finish
method (as of RN 0.38).
Mixed remote push notifications are both delivered to your app AND to the notification center.
Android doesn't directly support mixed notifications. If you try to combine the above approaches you will see a noisy notification but it will not be delivered to your app. This library does however provide a basic work-around. By adding message
field to a silent notification the library will synthesize a local notification as well as deliver a silent notification to your app. Something like this:
{
"to": "<token>",
"time_to_live": 86400,
"collapse_key": "new_message",
"delay_while_idle": false,
"data": {
"title": "title",
"message": "this is a mixed test 14:03:29.676",
"your-key": "your-value"
}
}
The resulting local notification will include the message as well as a few other (optional) fields: title, sound and colour
Just combine the above silent and noisy notifications and send to APNS:
{
"aps": {
"alert": {
"body": "body 16:03:49.889",
"title": "title"
},
"badge": 1,
"sound": "default"
},
"payload": "{\"your-key\":\"your-value\"}"
}
It will be delivered to both the notification centre and your app if the app is running in the background, but only to your app if its running in the foreground.
- http://www.fantageek.com/blog/2016/04/15/push-notification-in-practice/
- https://devcenter.verivo.com/display/doc/Handling+Push+Notifications+on+iOS
- https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/CreatingtheNotificationPayload.html#//apple_ref/doc/uid/TP40008194-CH10-SW1
- http://stackoverflow.com/questions/12071726/how-to-use-beginbackgroundtaskwithexpirationhandler-for-already-running-task-in