-
-
Notifications
You must be signed in to change notification settings - Fork 2k
onNotification not called when opening local notification in headless state (android) #1434
Description
Bug
I want to handle remote push notifications (PN) from FCM in my app by sending silent remote PNs that trigger a local PN (as advised in this package's troubleshooting guide). This works for all states but one: When the app is in quit state and receives a remote PN, the background task is launched, onNotification
called and a local PN is created (PushNotification.configure
is called as well). When this local PN is opened, the onNotification
method is not called. If the app is in background state and receives a remote PN, the local PN is created and onNotification
called as expected when it is opened.
Environment info
react-native info
output:
System:
OS: Windows 10 10.0.17763
CPU: (8) x64 Intel(R) Core(TM) i7-7820HQ CPU @ 2.90GHz
Memory: 20.04 GB / 31.85 GB
Binaries:
Node: 8.12.0 - C:\Program Files\nodejs\node.EXE
Yarn: Not Found
npm: 6.13.0 - C:\Program Files\nodejs\npm.CMD
Watchman: Not Found
SDKs:
Android SDK:
API Levels: 23, 25, 26, 27, 28
Build Tools: 26.0.3, 27.0.3, 28.0.2, 28.0.3
System Images: android-26 | Google APIs Intel x86 Atom_64, android-28 | Google APIs Intel x86 Atom, android-28 | Google APIs Intel x86 Atom_64
Android NDK: Not Found
IDEs:
Android Studio: Version 3.6.0.0 AI-192.7142.36.36.6392135
Languages:
Java: Not Found
Python: Not Found
npmPackages:
@react-native-community/cli: Not Found
react: 16.9.0 => 16.9.0
react-native: 0.62.0 => 0.62.0
npmGlobalPackages:
*react-native*: Not Found
Library version: 3.4.0
Steps To Reproduce
- Following this package's installation instruction
- Setting up FCM
- Implemented a singleton notification interface that is called outside of the react scope (see index.js)
- Started app in debug mode on physical android device (SM-A520F) with Android 8.0.0
- Quit the app after it successfully started first
- Sent FCM message via Postman:
{
"to": "eGZXrIp-Suu4HTicVNzbjB:APA91bF5Y68YR-BvYtIpX_p1drT8Io5wTV1Mh_2Y6OGSgX_XzbP0rDQWIxj2YuRUBX6JiZvrshMHQ5t9FLxOp42fQfCUzRq9lKbsm4av0ECVlkeq0aQWlhV-kRDLwgIU03iXQbpl8uii",
"data": {
"path": "Settings", //data content
"create_local": true, //If a local PN should be created
"text": "Remote notif" //Text to display in local PN
}
"priority": "high",
"content_available": true //required for iOS silent PN
}
- Open local PN
Describe what you expected to happen:
- App background task spins up and
onNotification
is called with respective log output ("remote notif received") - Local PN is shown
- When local PN is opened,
onNotification
is called with log output "opened app with notif" (which unfortunately is not happening)
Log output for remote PN received in app background state and opening local PN:
log
[Tue May 12 2020 09:07:24.431] LOG configure
[Tue May 12 2020 09:07:24.432] LOG Running "SampleApp" with {"rootTag":21}
[Tue May 12 2020 09:07:24.433] LOG {"os": "android", "token": "eGZXrIp-Suu4HTicVNzbjB:APA91bF5Y68YR-BvYtIpX_p1drT8Io5wTV1Mh_2Y6OGSgX_XzbP0rDQWIxj2YuRUBX6JiZvrshMHQ5t9FLxOp42fQfCUzRq9lKbsm4av0ECVlkeq0aQWlhV-kRDLwgIU03iXQbpl8uii"}
[Tue May 12 2020 09:07:56.880] LOG onNotif
[Tue May 12 2020 09:07:56.950] LOG remote notif received {"data": {"create_local": "true", "path": "Settings", "text": "Remote notif"}, "finish": [Function finish], "foreground": false, "id": "1896499685", "userInteraction": false}
[Tue May 12 2020 09:07:58.817] LOG onNotif
[Tue May 12 2020 09:07:58.820] LOG opened app with notif {"actions": "[\"Yes\", \"No\"]", "alertAction": "view", "autoCancel": true, "bigText": "My big text that will be shown when notification is expanded", "category": "", "color": "red", "finish": [Function finish], "foreground": false, "group": "group", "id": "1", "largeIcon": "ic_launcher", "message": "My Notification Message", "number": "10", "ongoing": false, "playSound": false, "smallIcon": "ic_notification", "soundName": "default", "subText": "This is a subText", "tag": "some_tag", "ticker": "My Notification Ticker", "title": "Local Notification", "userInfo": {}, "userInteraction": true, "vibrate": true, "vibration": 300}
Log output for remote PN received in app quit state on spinning up background task and opening local PN:
log
[Tue May 12 2020 09:08:55.442] LOG configure
[Tue May 12 2020 09:08:55.443] LOG onNotif
[Tue May 12 2020 09:08:55.443] LOG remote notif received {"data": {"create_local": "true", "path": "Settings", "text": "Remote notif"}, "finish": [Function finish], "foreground": false, "id": "-538668049", "userInteraction": false}
[Tue May 12 2020 09:08:55.444] LOG {"os": "android", "token": "eGZXrIp-Suu4HTicVNzbjB:APA91bF5Y68YR-BvYtIpX_p1drT8Io5wTV1Mh_2Y6OGSgX_XzbP0rDQWIxj2YuRUBX6JiZvrshMHQ5t9FLxOp42fQfCUzRq9lKbsm4av0ECVlkeq0aQWlhV-kRDLwgIU03iXQbpl8uii"}
[Tue May 12 2020 09:09:00.701] LOG Running "SampleApp" with {"rootTag":1}
Reproducible sample code
index.js
import 'react-native-gesture-handler';
import {AppRegistry} from 'react-native';
import Routes from './src/config/routes';
import {name as appName} from './app.json';
import NotificationService from './src/libs/NotificationInterface';
NotificationService.getInstance();
AppRegistry.registerComponent(appName, () => Routes);
NotificationInterface.js
import PushNotification from 'react-native-push-notification';
import {AppState} from 'react-native';
import PushNotificationIOS from '@react-native-community/push-notification-ios';
export default class NotificationService {
constructor() {
this.configure(this.onRegister, this.onNotif);
this.lastId = 0;
}
static instance = null;
static getInstance() {
if (this.instance == null) this.instance = new NotificationService();
return this.instance;
}
onRegister = async token => {
console.log(token);
};
onNotif = notif => {
console.log('onNotif');
if (
notif.hasOwnProperty('data') &&
notif.data.hasOwnProperty('create_local') &&
notif.data.create_local
) {
console.log('remote notif received', notif);
if (!notif.foreground) {
this.localNotif(notif.data.text);
}
} else {
console.log('opened app with notif', notif);
if (Platform.OS === 'ios') {
PushNotificationIOS.setApplicationIconBadgeNumber(0);
}
}
if (Platform.OS === 'ios') {
notif.finish(PushNotificationIOS.FetchResult.NoData);
}
};
configure(onRegister, onNotification) {
console.log('configure');
PushNotification.configure({
onRegister: onRegister,
onNotification: onNotification,
permissions: {
alert: true,
badge: true,
sound: true,
},
popInitialNotification: true,
requestPermissions: true,
});
}
localNotif() {
this.lastId++;
PushNotification.localNotification({
/* Android Only Properties */
id: '' + this.lastId, // (optional) Valid unique 32 bit integer specified as string. default: Autogenerated Unique ID
ticker: 'My Notification Ticker', // (optional)
autoCancel: true, // (optional) default: true
largeIcon: 'ic_launcher', // (optional) default: "ic_launcher"
smallIcon: 'ic_notification', // (optional) default: "ic_notification" with fallback for "ic_launcher"
bigText: 'My big text that will be shown when notification is expanded', // (optional) default: "message" prop
subText: 'This is a subText', // (optional) default: none
color: 'red', // (optional) default: system default
vibrate: true, // (optional) default: true
vibration: 300, // vibration length in milliseconds, ignored if vibrate=false, default: 1000
tag: 'some_tag', // (optional) add tag to message
group: 'group', // (optional) add group to message
ongoing: false, // (optional) set whether this is an "ongoing" notification
/* iOS only properties */
alertAction: 'view', // (optional) default: view
category: '', // (optional) default: empty string
userInfo: {}, // (optional) default: {} (using null throws a JSON value '<null>' error)
/* iOS and Android properties */
title: 'Local Notification', // (optional)
message: 'My Notification Message', // (required)
playSound: false, // (optional) default: true
soundName: 'default', // (optional) Sound to play when the notification is shown. Value of 'default' plays the default sound. It can be set to a custom sound such as 'android.resource://com.xyz/raw/my_sound'. It will look for the 'my_sound' audio file in 'res/raw' directory and play it. default: 'default' (default sound is played)
number: 10, // (optional) Valid 32 bit integer specified as string. default: none (Cannot be zero)
actions: '["Yes", "No"]', // (Android only) See the doc for notification actions to know more
});
}
scheduleNotif() {
this.lastId++;
PushNotification.localNotificationSchedule({
date: new Date(Date.now() + 3000), // in 3 secs
/* Android Only Properties */
id: '' + this.lastId, // (optional) Valid unique 32 bit integer specified as string. default: Autogenerated Unique ID
ticker: 'My Notification Ticker', // (optional)
autoCancel: true, // (optional) default: true
largeIcon: 'ic_launcher', // (optional) default: "ic_launcher"
smallIcon: 'ic_notification', // (optional) default: "ic_notification" with fallback for "ic_launcher"
bigText: 'My big text that will be shown when notification is expanded', // (optional) default: "message" prop
subText: 'This is a subText', // (optional) default: none
color: 'blue', // (optional) default: system default
vibrate: true, // (optional) default: true
vibration: 300, // vibration length in milliseconds, ignored if vibrate=false, default: 1000
tag: 'some_tag', // (optional) add tag to message
group: 'group', // (optional) add group to message
ongoing: false, // (optional) set whether this is an "ongoing" notification
/* iOS only properties */
alertAction: 'view', // (optional) default: view
category: '', // (optional) default: empty string
userInfo: {}, // (optional) default: {} (using null throws a JSON value '<null>' error)
/* iOS and Android properties */
title: 'Scheduled Notification', // (optional)
message: 'My Notification Message', // (required)
playSound: true, // (optional) default: true
soundName: 'default', // (optional) Sound to play when the notification is shown. Value of 'default' plays the default sound. It can be set to a custom sound such as 'android.resource://com.xyz/raw/my_sound'. It will look for the 'my_sound' audio file in 'res/raw' directory and play it. default: 'default' (default sound is played)
});
}
checkPermission(cbk) {
return PushNotification.checkPermissions(cbk);
}
requestPermissions() {
return PushNotification.requestPermissions();
}
cancelNotif() {
PushNotification.cancelLocalNotifications({id: '' + this.lastId});
}
cancelAll() {
PushNotification.cancelAllLocalNotifications();
}
}
AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.sampleapp">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.VIBRATE" />
<application
android:name=".MainApplication"
android:label="@string/app_name"
android:icon="@mipmap/ic_launcher"
android:roundIcon="@mipmap/ic_launcher_round"
android:allowBackup="false"
android:theme="@style/AppTheme">
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
android:windowSoftInputMode="adjustResize"
android:exported="true"
android:launchMode="singleInstance">
</activity>
<activity
android:name="com.zoontek.rnbootsplash.RNBootSplashActivity"
android:theme="@style/BootTheme"> <!-- apply the theme you created at step 3. -->
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<action android:name="android.intent.action.DOWNLOAD_COMPLETE"/>
</intent-filter>
</activity>
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
<receiver android:name="com.dieam.reactnativepushnotification.modules.RNPushNotificationPublisher" />
<receiver android:name="com.dieam.reactnativepushnotification.modules.RNPushNotificationBootEventReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<service
android:name="com.dieam.reactnativepushnotification.modules.RNPushNotificationListenerService"
android:exported="false" >
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
<meta-data android:name="com.dieam.reactnativepushnotification.notification_channel_name"
android:value="sampleapp"/>
<meta-data android:name="com.dieam.reactnativepushnotification.notification_channel_description"
android:value="Sample App test channel"/>
<meta-data android:name="com.dieam.reactnativepushnotification.notification_foreground"
android:value="false"/>
<meta-data android:name="com.dieam.reactnativepushnotification.notification_color"
android:resource="@android:color/white"/>
</application>
</manifest>