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

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

Closed
MarcoStb1993 opened this issue May 12, 2020 · 18 comments
Assignees

Comments

@MarcoStb1993
Copy link

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>
@Dallas62 Dallas62 self-assigned this May 12, 2020
@Dallas62
Copy link
Collaborator

Hi @MarcoStb1993
I will test this but I'm actually busy, maybe at the end of day. 😉

@Dallas62
Copy link
Collaborator

Hi @MarcoStb1993
Sorry for the delay, here a solution:

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);
  };

  checkInitialNotification() {
    PushNotification.popInitialNotification(this.onNotif);
  }

  onNotif = notif => {
    if (!notif) {
      return;
    }

    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();
  }
}

Then call checkInitialNotification() when the root component trigger componentDidMount().

Here changes:

  • In .configure turn off popInitialNotification
  • In NotificationService added a method
  checkInitialNotification() {
    PushNotification.popInitialNotification(this.onNotif);
  }
  • In the root component (App, or Routes in your case) add a call to NotificationService.getInstance().checkInitialNotification(); when componentDidMount()

Hope it's clear enough 😉

@MarcoStb1993
Copy link
Author

Thank you for your help, unfortunately the method onNotif always receives null as notification. If I start the app normally or via touching a notification.

I am calling NotificationInterface.getInstance().checkInitialNotification() in the first screen that is always opened (and where the splashscreen is hidden). popInitialNotification is also set to false.

On a side note: The app's badge always sets to multiples of 10 after receiving a notification instead of 1 (10, 20, 30 ...). This happens on iOS as well.

@Dallas62
Copy link
Collaborator

Dallas62 commented May 14, 2020

If the problem is now related to SplashScreen, take a look at:
#122 (comment)
For the badge number I will take a look.

And I forgot to mention, but there is an extra condition in case of the app start normaly:

    if (!notif) {
      return;
    }

@Dallas62
Copy link
Collaborator

For number badge, did you change the value in number when you call localNotification ?
Android stack notifications and sum all number value, which explains what you describe.

number: 10,

@MarcoStb1993
Copy link
Author

I don't know if the issue is related to the splashscreen. I tried the "hack" from the comment you linked and it did not change the notification received being null on checkInitialNotification.

I removed the splashscreen intent from the manifest and set the MainActivity as launcher and onNotif was still called with notification value null after being openend from a notification.

And the badge number "error" was due to my stupidity ... Thanks for pointing the number value out to me. It was in fact set to 10.

@Dallas62
Copy link
Collaborator

I will check this again at the end of the day, but I had the behaviour you described and making this change was enough to get the initial notification.

@MarcoStb1993
Copy link
Author

MarcoStb1993 commented May 14, 2020

Ok, thank you! I dug through the adb logcat and found some stuff that might be interesting:

Receiving remote message
05-14 09:45:59.408 25455 25502 V RNPushNotification: onMessageReceived: Bundle[{data=Bundle[{path=Settings, text=Remote notif, create_local=true}]}]
05-14 09:45:59.539 25455 25455 V RNPushNotification: sendNotification: Bundle[{userInteraction=false, id=1428018032, data=Bundle[{path=Settings, text=Remote notif, create_local=true}], foreground=false}]
05-14 09:45:59.549 25455 25455 D RNPushNotification: Cannot send to notification centre because there is no 'message' field in: Bundle[{userInteraction=false, id=1428018032, data=Bundle[{path=Settings, text=Remote notif, create_local=true}], foreground=false}]
Local notification posted
05-14 09:46:01.659  4664  5190 D Notification: allPendingIntents
05-14 09:46:01.661  5952  5952 D Notification.Badge: [valid] onNotificationPosted : StatusBarNotification(pkg=com.sampleapp user=UserHandle{0} id=1 tag=some_tag key=0|com.sampleapp|1|some_tag|10363: Notification(channel=rn-push-notification-channel-id-4-300 pri=1 contentView=null vibrate=null sound=null tick defaults=0x4 flags=0x10 color=0xffff0000 category=call groupKey=group actions=2 number=0 vis=PRIVATE semFlags=0x0 semPriority=0 semMissedCount=0))
05-14 09:46:01.661  5952  5952 D Notification.Badge: notificationKey : 0|com.sampleapp|1|some_tag|10363, count : 0, this.count : 1
05-14 09:46:01.661  5952  6042 D Notification.Badge: LauncherModel:onNotificationPosted() : com.sampleapp, count : [1], shouldBeFilteredOut : [false]
05-14 09:46:01.661  5952  6042 D Notification.Badge: notificationKey : 0|com.sampleapp|1|some_tag|10363, count : 1, mTotalCount : 1
05-14 09:46:01.661  4664  6935 D Notification: allPendingIntents
05-14 09:46:01.663  4664  5190 D Notification: allPendingIntents
05-14 09:46:01.663  5077  5077 D StatusBar: addNotification key=0|com.sampleapp|1|some_tag|10363 fullscreen:false
05-14 09:46:01.664  5952  6042 D Notification.Badge: updateLauncherIconBadges : 1
05-14 09:46:01.664  5952  6042 D Notification.Badge: updateLauncherIconBadges() count : -1
05-14 09:46:01.664  5952  6042 D Notification.Badge: updateLauncherIconBadges() item : [IconInfo(title=SampleApp intent=Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.sampleapp/com.zoontek.rnbootsplash.RNBootSplashActivity (has extras) } id=448 type=0 container=-102 screen=1 cellX=0 cellY=1 spanX=1 spanY=1 rank=4 hidden=0 dropPos=null user=UserHandle{0})], item.mBadgeCount: [1]
Notification removed
05-14 09:46:04.745  5952  5952 D Notification.Badge: [valid] onNotificationRemoved : StatusBarNotification(pkg=com.sampleapp user=UserHandle{0} id=1 tag=some_tag key=0|com.sampleapp|1|some_tag|10363: Notification(channel=rn-push-notification-channel-id-4-300 pri=1 contentView=null vibrate=null sound=null tick defaults=0x4 flags=0x10 color=0xffff0000 category=call groupKey=group actions=2 number=0 vis=PRIVATE semFlags=0x0 semPriority=0 semMissedCount=0))
05-14 09:46:04.745  5952  5952 D Notification.Badge: notificationKey : 0|com.sampleapp|1|some_tag|10363, count : 0, this.count : 1
05-14 09:46:04.745  5952  5952 D ViewRootImpl@3741015[LauncherActivity]: MSG_WINDOW_FOCUS_CHANGED 0
05-14 09:46:04.745  5952  6042 D Notification.Badge: LauncherModel:onNotificationRemoved() : com.sampleapp
05-14 09:46:04.745  5952  6042 D Notification.Badge: updateLauncherIconBadges : 1
05-14 09:46:04.745  5952  6042 D Notification.Badge: updateLauncherIconBadges() item : [IconInfo(title=SampleApp intent=Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.sampleapp/com.zoontek.rnbootsplash.RNBootSplashActivity (has extras) } id=448 type=0 container=-102 screen=1 cellX=0 cellY=1 spanX=1 spanY=1 rank=4 hidden=0 dropPos=null user=UserHandle{0})], item.mBadgeCount: [0]

Furthermore, I've modified the 'getInitialNotification' method in the node module RNPushNotification.java file and added some log output:

RNPushNotification.java
@ReactMethod
    public void getInitialNotification(Promise promise) {
     Log.v(LOG_TAG, "getInitialNotification: called");
        WritableMap params = Arguments.createMap();
        Activity activity = getCurrentActivity();
        if (activity != null) {
        Log.v(LOG_TAG, "getInitialNotification: activity!=null");
        Log.v(LOG_TAG, "getInitialNotification: activity: " + activity.getTitle());
            Bundle bundle = this.getBundleFromIntent(activity.getIntent());
            if (bundle != null) {
            Log.v(LOG_TAG, "getInitialNotification: bunde!=null");
                bundle.putBoolean("foreground", false);
                String bundleString = mJsDelivery.convertJSON(bundle);
                params.putString("dataJSON", bundleString);
            }
        }
        promise.resolve(params);
    }

Which resulted in this being logged:

Log on normal app start
05-14 10:33:47.475 29051 29120 V RNPushNotification: getInitialNotification: called
05-14 10:33:47.475 29051 29120 V RNPushNotification: getInitialNotification: activity!=null
05-14 10:33:47.475 29051 29120 V RNPushNotification: getInitialNotification: activity: SampleApp
Log on open local notification with app running headless
5-14 10:45:02.161 31007 31007 D SoLoader: About to load: libyoga.so
05-14 10:45:02.162 31007 31007 D SoLoader: libyoga.so not found on /data/data/com.sampleapp/lib-main
05-14 10:45:02.162 31007 31007 D SoLoader: libyoga.so found on /data/app/com.sampleapp-Stgz-IKNP7kbnWG3Rr1Cpg==/lib/arm64
05-14 10:45:02.162 31007 31007 D SoLoader: Not resolving dependencies for libyoga.so
05-14 10:45:02.164 31007 31007 D SoLoader: Loaded: libyoga.so
05-14 10:33:59.656 29149 29209 V RNPushNotification: getInitialNotification: called
05-14 10:33:59.656 29149 29149 I zygote64: Rejecting re-init on previously-failed class java.lang.Class<androidx.core.view.ViewCompat$2>: java.lang.NoClassDefFoundError: Failed resolution of: Landroid/view/View$OnUnhandledKeyEventListener;
05-14 10:33:59.656 29149 29149 I zygote64:   at void androidx.core.view.ViewCompat.setOnApplyWindowInsetsListener(android.view.View, androidx.core.view.OnApplyWindowInsetsListener) (ViewCompat.java:2421)
05-14 10:33:59.656 29149 29149 I zygote64:   at android.view.ViewGroup androidx.appcompat.app.AppCompatDelegateImpl.createSubDecor() (AppCompatDelegateImpl.java:779)
05-14 10:33:59.656 29149 29149 I zygote64:   at void androidx.appcompat.app.AppCompatDelegateImpl.ensureSubDecor() (AppCompatDelegateImpl.java:659)
05-14 10:33:59.656 29149 29149 I zygote64:   at void androidx.appcompat.app.AppCompatDelegateImpl.setContentView(android.view.View) (AppCompatDelegateImpl.java:543)
05-14 10:33:59.656 29149 29149 I zygote64:   at void androidx.appcompat.app.AppCompatActivity.setContentView(android.view.View) (AppCompatActivity.java:166)
05-14 10:33:59.656 29149 29149 I zygote64:   at void com.facebook.react.ReactActivityDelegate.loadApp(java.lang.String) (ReactActivityDelegate.java:91)
05-14 10:33:59.656 29149 29149 I zygote64:   at void com.facebook.react.ReactActivityDelegate.onCreate(android.os.Bundle) (ReactActivityDelegate.java:85)
05-14 10:33:59.656 29149 29149 I zygote64:   at void com.facebook.react.ReactActivity.onCreate(android.os.Bundle) (ReactActivity.java:45)
05-14 10:33:59.656 29149 29149 I zygote64:   at void com.sampleapp.MainActivity.onCreate(android.os.Bundle) (MainActivity.java:33)
05-14 10:33:59.656 29149 29149 I zygote64:   at void android.app.Activity.performCreate(android.os.Bundle) (Activity.java:7183)
05-14 10:33:59.656 29149 29149 I zygote64:   at void android.app.Instrumentation.callActivityOnCreate(android.app.Activity, android.os.Bundle) (Instrumentation.java:1220)
05-14 10:33:59.656 29149 29149 I zygote64:   at android.app.Activity android.app.ActivityThread.performLaunchActivity(android.app.ActivityThread$ActivityClientRecord, android.content.Intent) (ActivityThread.java:2910)
05-14 10:33:59.657 29149 29149 I zygote64:   at void android.app.ActivityThread.handleLaunchActivity(android.app.ActivityThread$ActivityClientRecord, android.content.Intent, java.lang.String) (ActivityThread.java:3032)
05-14 10:33:59.657 29149 29149 I zygote64:   at void android.app.ActivityThread.-wrap11(android.app.ActivityThread, android.app.ActivityThread$ActivityClientRecord, android.content.Intent, java.lang.String) (ActivityThread.java:-1)
05-14 10:33:59.657 29149 29149 I zygote64:   at void android.app.ActivityThread$H.handleMessage(android.os.Message) (ActivityThread.java:1696)
05-14 10:33:59.657 29149 29149 I zygote64:   at void android.os.Handler.dispatchMessage(android.os.Message) (Handler.java:105)
05-14 10:33:59.657 29149 29149 I zygote64:   at void android.os.Looper.loop() (Looper.java:164)
05-14 10:33:59.657 29149 29149 I zygote64:   at void android.app.ActivityThread.main(java.lang.String[]) (ActivityThread.java:6944)
05-14 10:33:59.657 29149 29149 I zygote64:   at java.lang.Object java.lang.reflect.Method.invoke(java.lang.Object, java.lang.Object[]) (Method.java:-2)
05-14 10:33:59.657 29149 29149 I zygote64:   at void com.android.internal.os.Zygote$MethodAndArgsCaller.run() (Zygote.java:327)
05-14 10:33:59.657 29149 29149 I zygote64:   at void com.android.internal.os.ZygoteInit.main(java.lang.String[]) (ZygoteInit.java:1374)
05-14 10:33:59.657 29149 29149 I zygote64: Caused by: java.lang.ClassNotFoundException: Didn't find class "android.view.View$OnUnhandledKeyEventListener" on path: DexPathList[[zip file "/data/app/com.sampleapp-KZ7upVvIpXkLCAdCw-hdLg==/base.apk"],nativeLibraryDirectories=[/data/app/com.sampleapp-KZ7upVvIpXkLCAdCw-hdLg==/lib/arm64, /data/app/com.sampleapp-KZ7upVvIpXkLCAdCw-hdLg==/base.apk!/lib/arm64-v8a, /system/lib64, /system/vendor/lib64]]
05-14 10:33:59.657 29149 29149 I zygote64:   at java.lang.Class dalvik.system.BaseDexClassLoader.findClass(java.lang.String) (BaseDexClassLoader.java:93)
05-14 10:33:59.657 29149 29149 I zygote64:   at java.lang.Class java.lang.ClassLoader.loadClass(java.lang.String, boolean) (ClassLoader.java:379)
05-14 10:33:59.657 29149 29149 I zygote64:   at java.lang.Class java.lang.ClassLoader.loadClass(java.lang.String) (ClassLoader.java:312)
05-14 10:33:59.657 29149 29149 I zygote64:   at void androidx.core.view.ViewCompat.setOnApplyWindowInsetsListener(android.view.View, androidx.core.view.OnApplyWindowInsetsListener) (ViewCompat.java:2421)
05-14 10:33:59.657 29149 29149 I zygote64:   at android.view.ViewGroup androidx.appcompat.app.AppCompatDelegateImpl.createSubDecor() (AppCompatDelegateImpl.java:779)
05-14 10:33:59.657 29149 29149 I zygote64:   at void androidx.appcompat.app.AppCompatDelegateImpl.ensureSubDecor() (AppCompatDelegateImpl.java:659)
05-14 10:33:59.657 29149 29149 I zygote64:   at void androidx.appcompat.app.AppCompatDelegateImpl.setContentView(android.view.View) (AppCompatDelegateImpl.java:543)
05-14 10:33:59.657 29149 29149 I zygote64:   at void androidx.appcompat.app.AppCompatActivity.setContentView(android.view.View) (AppCompatActivity.java:166)
05-14 10:33:59.657 29149 29149 I zygote64:   at void com.facebook.react.ReactActivityDelegate.loadApp(java.lang.String) (ReactActivityDelegate.java:91)
05-14 10:33:59.657 29149 29149 I zygote64:   at void com.facebook.react.ReactActivityDelegate.onCreate(android.os.Bundle) (ReactActivityDelegate.java:85)
05-14 10:33:59.657 29149 29149 I zygote64:   at void com.facebook.react.ReactActivity.onCreate(android.os.Bundle) (ReactActivity.java:45)
05-14 10:33:59.657 29149 29149 I zygote64:   at void com.sampleapp.MainActivity.onCreate(android.os.Bundle) (MainActivity.java:33)
05-14 10:33:59.657 29149 29149 I zygote64:   at void android.app.Activity.performCreate(android.os.Bundle) (Activity.java:7183)
05-14 10:33:59.657 29149 29149 I zygote64:   at void android.app.Instrumentation.callActivityOnCreate(android.app.Activity, android.os.Bundle) (Instrumentation.java:1220)
05-14 10:33:59.657 29149 29149 I zygote64:   at android.app.Activity android.app.ActivityThread.performLaunchActivity(android.app.ActivityThread$ActivityClientRecord, android.content.Intent) (ActivityThread.java:2910)
05-14 10:33:59.657 29149 29149 I zygote64:   at void android.app.ActivityThread.handleLaunchActivity(android.app.ActivityThread$ActivityClientRecord, android.content.Intent, java.lang.String) (ActivityThread.java:3032)
05-14 10:33:59.657 29149 29149 I zygote64:   at void android.app.ActivityThread.-wrap11(android.app.ActivityThread, android.app.ActivityThread$ActivityClientRecord, android.content.Intent, java.lang.String) (ActivityThread.java:-1)
05-14 10:33:59.657 29149 29149 I zygote64:   at void android.app.ActivityThread$H.handleMessage(android.os.Message) (ActivityThread.java:1696)
05-14 10:33:59.657 29149 29149 I zygote64:   at void android.os.Handler.dispatchMessage(android.os.Message) (Handler.java:105)
05-14 10:33:59.657 29149 29149 I zygote64:   at void android.os.Looper.loop() (Looper.java:164)
05-14 10:33:59.657 29149 29149 I zygote64:   at void android.app.ActivityThread.main(java.lang.String[]) (ActivityThread.java:6944)
05-14 10:33:59.657 29149 29149 I zygote64:   at java.lang.Object java.lang.reflect.Method.invoke(java.lang.Object, java.lang.Object[]) (Method.java:-2)
05-14 10:33:59.657 29149 29149 I zygote64:   at void com.android.internal.os.Zygote$MethodAndArgsCaller.run() (Zygote.java:327)
05-14 10:33:59.657 29149 29149 I zygote64:   at void com.android.internal.os.ZygoteInit.main(java.lang.String[]) (ZygoteInit.java:1374)

Hopefully, this might be helpful.

Edit: I found this regarding splash screens in RNF's issues. which shows the same problem in RNF with getInitialNotification (that I presume to work similarly). But I am using React Native Bootsplash which apparently already implements these additions .

@Dallas62
Copy link
Collaborator

There is a difference in the AndroidManifest I used and your AndroidManifest:
https://github.com/zo0r/react-native-push-notification/blob/master/example/android/app/src/main/AndroidManifest.xml#L23
Don't know if this is the problem, but easy to test.

@MarcoStb1993
Copy link
Author

I've added this tag both my activities but it still did not work.

But, by chance I found out, that the initial notification is fetched when not in Debug mode. As soon as I activate the Debug mode, I receive null for the initial notification. When it is deactivated, everything works as expected.

Do you have any idea why that can be?

@Dallas62
Copy link
Collaborator

I don’t know what it can be, debug can replay the same initial notification (null if no notification) but its due to Hot Reload.
If you can provide a small repository with the bug I can investigate (no need to provide a firebase configuration, I will configure it)

@MarcoStb1993
Copy link
Author

I tried to build a small repository for testing just using your example project and adding RN Bootsplash, but using just this combination works as expected.

I guess its some misconfiguration in my project using submodules and tons of dependencies ...

I will close this issue now since I can proceed (without debug mode). Thanks again for your help!

@Dallas62
Copy link
Collaborator

Hi @MarcoStb1993
A pull request fix this issue without a workaround:
#1446
This will be release soon.

@Ajmal0197
Copy link

Ajmal0197 commented Sep 5, 2020

The issue is due to splash activity
Edit the manifest like this and it gonna work:

      <activity
        android:name=".SplashActivity"
        android:theme="@style/SplashTheme"
        android:label="@string/app_name">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
  <activity
    android:name=".MainActivity"
    android:label="@string/app_name"
    android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
    android:windowSoftInputMode="adjustResize" >
      <intent-filter>
      <action android:name="android.intent.action.MAIN" />
      <category android:name="android.intent.category.INFO" />
      </intent-filter>
    </activity>

@maullerz
Copy link

maullerz commented Mar 16, 2021

happens to me also, completely removing <activity android:name=".SplashActivity" ...</activity> fixes the problem.

FYI
there is still popular article on Medium (first result on google search)
https://medium.com/@appstud/add-a-splash-screen-to-a-react-native-app-810492e773f9

there is instructions to add separate activity for Splash like this

      <activity
        android:name=".SplashActivity"
        android:theme="@style/SplashTheme"
        android:label="@string/app_name">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

but the README of https://github.com/crazycodeboy/react-native-splash-screen
doesnt have any info about such activity.

@Draigs
Copy link

Draigs commented Jun 8, 2021

@MarcoStb1993 Have you been able to resolve your issues? Asking as I'm experiencing the same symptoms in one of my projects.

@MarcoStb1993
Copy link
Author

@Draigs Unfortunately, I can't really tell. It seemed to work for some tests back then, but was never really used in a productive app until recently when it did not work. Currently I am working on another project, but soon I'll try to fix it. But I reckon since a lot of new releases happened since then, it will be quite different.

@Draigs
Copy link

Draigs commented Jun 9, 2021

@MarcoStb1993 thanks for getting back. Finally found my problem. Was a misconfiguration of the manifest. As I'd implemented SSO, I had to change the intent-filter:

<intent-filter>
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
    <data
      android:host="@string/AUTH_DOMAIN"
      android:pathPrefix="/android/${applicationId}/callback"
      android:scheme="${applicationId}" />
</intent-filter>

If I changed this, to what's written in the documentation of this repo, the notification were working but obviously it broke the SSO flow. Finally I fixed it by adding an additional intent-filter and left the existing one(s) unchanged:

<intent-filter>
    <action android:name="android.intent.action.MAIN" />
    <category android:name="android.intent.category.INFO" />
</intent-filter>

Maybe this helps someone having similar issues.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants