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

onNotification not called when opening local notification in headless state (android) #1434

@MarcoStb1993

Description

@MarcoStb1993

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

  1. Following this package's installation instruction
  2. Setting up FCM
  3. Implemented a singleton notification interface that is called outside of the react scope (see index.js)
  4. Started app in debug mode on physical android device (SM-A520F) with Android 8.0.0
  5. Quit the app after it successfully started first
  6. 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
}
  1. Open local PN

Describe what you expected to happen:

  1. App background task spins up and onNotification is called with respective log output ("remote notif received")
  2. Local PN is shown
  3. 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>

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions