react-native-push-notification icon indicating copy to clipboard operation
react-native-push-notification copied to clipboard

onNotification not called when the app is first opened from notification tap

Open cristianoccazinsp opened this issue 3 years ago • 15 comments

Bug

Environment info

react-native info output:

ystem:
    OS: macOS 10.15.7
    CPU: (4) x64 Intel(R) Core(TM) i5-6267U CPU @ 2.90GHz
    Memory: 35.33 MB / 8.00 GB
    Shell: 5.7.1 - /bin/zsh
  Binaries:
    Node: 12.20.1 - /usr/local/bin/node
    Yarn: 1.22.5 - /usr/local/bin/yarn
    npm: 6.14.10 - /usr/local/bin/npm
    Watchman: 4.9.0 - /usr/local/bin/watchman
  Managers:
    CocoaPods: 1.10.1 - /usr/local/bin/pod
  SDKs:
    iOS SDK:
      Platforms: iOS 14.4, DriverKit 20.2, macOS 11.1, tvOS 14.3, watchOS 7.2
    Android SDK:
      API Levels: 29, 30
      Build Tools: 28.0.3, 29.0.2, 29.0.3
      Android NDK: Not Found
  IDEs:
    Android Studio: 4.1 AI-201.8743.12.41.7199119
    Xcode: 12.4/12D4e - /usr/bin/xcodebuild
  Languages:
    Java: 1.8.0_121 - /usr/bin/javac
    Python: 2.7.15 - /Library/Frameworks/Python.framework/Versions/2.7/bin/python
  npmPackages:
    @react-native-community/cli: Not Found
    react: 16.14.0 => 16.14.0 
    react-native: 0.62.2 => 0.62.2 
    react-native-macos: Not Found
  npmGlobalPackages:
    *react-native*: Not Found

Library version: 7.2.3

Steps To Reproduce

onNotification: function (notification) {
    // do something
}

The above code only runs when the notification is tapped and if the app was previously opened. However, if the app was not opened, it never runs.

I'm trying to handle the case when the user taps on the notification and the app wasn't opened / was killed, in order to react to it accordingly.

I see from RN logs that an initialProps object is added when the app opens from the notification on iOS, could this be used to add extra info?

Thanks!

cristianoccazinsp avatar Apr 16 '21 16:04 cristianoccazinsp

Hi @cristianoccazinsp Please search in issue history or check the exemple project before. The code provided doesn't help to reproduce. Regards,

Dallas62 avatar Apr 16 '21 16:04 Dallas62

I'm pretty much using the example code, but onNotification doesn't fire if the app was closed (terminated), but then re-opened from the notification tap event:

PushNotification.configure({
  // (optional) Called when Token is generated (iOS and Android)
  // NOT using push notifications from the server right now, this step is not done.
  onRegister: function (token) {},

  // (required) Called when a remote or local notification is opened or received
  onNotification: function (notification) {
    console.warn("TEST - THIS DOESN'T FIRE: ", notification)
    // required on iOS only
    if (Platform.OS == 'ios') {
      notification.finish(PushNotificationIOS.FetchResult.NewData);
    }
  },

  // ANDROID ONLY: GCM or FCM Sender ID (product_number) (optional - not required for local notifications, but is need to receive remote push notifications)
  //senderID: "YOUR GCM (OR FCM) SENDER ID",

  // IOS ONLY (optional): default: all - Permissions to register.
  permissions: {
    alert: true,
    badge: true,
    sound: true,
  },

  // Should the initial notification be popped automatically
  // default: true
  popInitialNotification: true,

  /**
   * (optional) default: true
   * - Specified if permissions (ios) and token (android and ios) will requested or not,
   * - if not, you must call PushNotificationsHandler.requestPermissions() later
   * - if you are not using remote notification or do not have Firebase installed, use this:
   *     requestPermissions: Platform.OS === 'ios'
   */
  requestPermissions: Platform.OS === 'ios',
});


// somewhere else in the code
PushNotification.localNotification({
    /* Android Only Properties */
    id: id,
    channelId: 'channel',
    autoCancel: true,
    vibrate: vibrate,
    vibration: 300,
    priority: 'high',
    visibility: 'public',
    ongoing: false,

    /* iOS only properties */
    userInfo: {id: id}, // required for ios local notification

    /* iOS and Android properties */
    title: title,
    message: message, // (required)
  });

cristianoccazinsp avatar Apr 16 '21 16:04 cristianoccazinsp

You can check: https://github.com/zo0r/react-native-push-notification/issues/1453 There is many reference to the ios repository. It's probably an issue on the AppDelegate.

Dallas62 avatar Apr 16 '21 17:04 Dallas62

This is for both Android and iOS, and only for local notifications (not using remote).

Calling PushNotification.popInitialNotification does seem to return the tapped notification though.

cristianoccazinsp avatar Apr 16 '21 17:04 cristianoccazinsp

Hi @cristianoccazinsp I'm not able to reproduce the issue with exemple project, without a reproducible exemple I can't help more. Be sure that .configure() is not inside a component. Regards

Dallas62 avatar Apr 16 '21 17:04 Dallas62

Just to be sure: if you completely kill the app (swipe it out) while the notification is still visible, then tap the notification, the app opens, onNotification is called for you? Both on Android and iOS.

Also, on iOS, PushNotification.popInitialNotification seems to only return the notification ID, but all other flags are null or with default values (e.g., message is undefined, userInteraction is false even if tapped, etc.).

cristianoccazinsp avatar Apr 16 '21 18:04 cristianoccazinsp

I dig into the link provided, I found this: https://github.com/zo0r/react-native-push-notification/issues/1501 https://github.com/zo0r/react-native-push-notification/issues/1501#issuecomment-764203739 https://github.com/react-native-push-notification-ios/push-notification-ios/issues/24#issuecomment-548398814

You can try in Release mode, this should work.

Dallas62 avatar Apr 16 '21 19:04 Dallas62

Release mode may solve it for iOS, but what about Android? So far the only work around that worked for me was to use PushNotification.popInitialNotification on a mount event.

cristianoccazinsp avatar Apr 16 '21 19:04 cristianoccazinsp

For Android, The main reason is an Activity such as a splash screen which intercept the intent. https://github.com/crazycodeboy/react-native-splash-screen/issues/289#issuecomment-421537284 Or in https://github.com/zo0r/react-native-push-notification#android-manual-installation The following part:

If your app has an @Override on onNewIntent in MainActivity.java ensure that function includes a super call on onNewIntent (if your MainActivity.java does not have an @Override for onNewIntent skip this):

    @Override
    public void onNewIntent(Intent intent) {
        ...
        super.onNewIntent(intent);
        ...
    }

Dallas62 avatar Apr 16 '21 20:04 Dallas62

Main activity is clean, and no custom splash screen (we are just using a background image)

public class MainActivity extends ReactActivity {

    /**
     * Returns the name of the main component registered from JavaScript.
     * This is used to schedule rendering of the component.
     */
    @Override
    protected String getMainComponentName() {
        return "zinspector3";
    }

    /**
    For react-native-gesture-handler (used)
     */
    @Override
    protected ReactActivityDelegate createReactActivityDelegate() {
        return new ReactActivityDelegate(this, getMainComponentName()) {
            @Override
            protected ReactRootView createRootView() {
                return new RNGestureHandlerEnabledRootView(MainActivity.this);
            }
        };
    }
}

cristianoccazinsp avatar Apr 16 '21 20:04 cristianoccazinsp

Landed on the same issue, for remote notifications, the onNotification is not called on tapping the notification. However, it gets called when the notification arrives. Is there any other method that is triggered on clicking the notification from the tray?

OS: Android

The implementation is pretty much the same as mentioned above. I went through many other issues that were reported but could not find a solution for this. Any help is appreciated.

Thanks in advance.

suryateja77 avatar May 18 '21 14:05 suryateja77

Landed on the same issue, for remote notifications, the onNotification is not called on tapping the notification. However, it gets called when the notification arrives. Is there any other method that is triggered on clicking the notification from the tray?

OS: Android

The implementation is pretty much the same as mentioned above. I went through many other issues that were reported but could not find a solution for this. Any help is appreciated.

Thanks in advance.

I'm having the exact same problem but my AndroidManifest has this shape:

    <activity android:name=".SplashActivity" 
      android:theme="@style/SplashTheme" 
      android:launchMode="singleTask" 
      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|uiMode" 
      android:windowSoftInputMode="adjustResize" 
      android:launchMode="singleTask" 
      android:exported="true">  
    <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:scheme="trique"/>
    </intent-filter>
    </activity>

And this is my index.js:

/* eslint-disable curly */
/* eslint-disable prettier/prettier */
/**
 * @format
 */

import { AppRegistry, AppState, Platform } from 'react-native';
import App from 'commons/src/App';
import { name as appNameJson } from './app.json';
import PushNotification from 'react-native-push-notification';
import triquestore from 'commons/src/store';
import { providers } from 'commons/src/services/Auth.service';
import { saveNotification } from 'commons/src/store/notifications';

const appName = Platform.OS === 'ios' ? appNameJson : 'com.trique.app';

const handleOnNotification = (notification) => {
    if (notification) {
        console.log('NOTIFICATION_RECIEVED', JSON.stringify(notification));
        if (!notification.ignoreInForeground && !notification.data.actionIdentifier) {
            console.log('PUSH_NOTIFICATION_ACCEPTED');
            triquestore.dispatch(saveNotification(notification));
            console.log('PUSH_NOTIFICATION_STORED');
            const payload = JSON.parse(notification.data.payload);
            if (Platform.OS === 'android') {
                PushNotification.localNotification({
                    ...notification,
                    channelId: 'com.trique.app',
                    title: payload.notification.title,
                    message: payload.notification.body,
                    ignoreInForeground: true,
                });
                console.log('LOCAL_NOTIFICATION_GENERATED_ANDROID');
            } else if (AppState.currentState === 'background') {
                PushNotification.localNotification({
                    ...notification,
                    title: payload.notification.title,
                    message: payload.notification.body,
                });
                console.log('LOCAL_NOTIFICATION_GENERATED_IOS');
            }
        } else {
            console.log('LOCAL_NOTIFICATION_CLICKED', JSON.stringify(notification));
        }
    }
};

PushNotification.configure({
    onRegister: function (token) {
        providers.GOOGLE.fcmToken = token.token;
    },
    onNotification: handleOnNotification,
    onRegistrationError: function (err) {
        console.error(err.message, err);
    },
    //popInitialNotification: true,
    requestPermissions: true,
});

PushNotification.createChannel(
    {
        channelId: (Platform.OS === 'android') ? 'com.trique.app' : 'com.diofy.trique',
        channelName: 'Trique',
    },
    (created) => {
        if (created) console.log(`createChannel returned '${created}'`);
    },
);

PushNotification.popInitialNotification(handleOnNotification);

AppRegistry.registerComponent(appName, () => App);

Everything works as expected with the app in foreground and background, the notification is even stored in redux, getting the desired output.. But when i tap the localNotification in closed state i do not get any interaction. Not even NOTIFICATION_RECIEVED, pointing at it begin lost or something before onNotification, example:

[Fri May 28 2021 01:23:49.445]  LOG      NOTIFICATION_RECIEVED {"foreground":false,"userInteraction":false,"id":"737196777","data":{"payload":"{\"relatedId\":3,\"content\":\"\",\"name\":\"FerTrique\",\"people\":[{\"id\":3,\"name\":\"Alejandro Albertengo\",\"avatar\":{\"uri\":\"https://firebasestorage.googleapis.com/v0/b/triqueapp.appspot.com/o/3%2Fprofile.png?alt=media&token=87883367-cde2-4b9a-9004-0aca3e35cbd6\"}}],\"type\":8,\"notification\":{\"title\":\"Te han comenzado a seguir\",\"body\":\"Alejandro Albertengo ha comenzado a seguirte\"}}"}}
[Fri May 28 2021 01:23:49.446]  LOG      PUSH_NOTIFICATION_ACCEPTED
[Fri May 28 2021 01:23:49.446]  LOG      PUSH_NOTIFICATION_STORED
[Fri May 28 2021 01:23:49.447]  LOG      LOCAL_NOTIFICATION_GENERATED_ANDROID
[Fri May 28 2021 01:23:49.447]  LOG      Loaded react-native-ffmpeg-android-arm64-v8a.
[Fri May 28 2021 01:24:11.503]  LOG      Running "com.trique.app" with {"rootTag":1}

Pra3t0r5 avatar May 28 '21 03:05 Pra3t0r5

Bug

Environment info

react-native info output:

ystem:
    OS: macOS 10.15.7
    CPU: (4) x64 Intel(R) Core(TM) i5-6267U CPU @ 2.90GHz
    Memory: 35.33 MB / 8.00 GB
    Shell: 5.7.1 - /bin/zsh
  Binaries:
    Node: 12.20.1 - /usr/local/bin/node
    Yarn: 1.22.5 - /usr/local/bin/yarn
    npm: 6.14.10 - /usr/local/bin/npm
    Watchman: 4.9.0 - /usr/local/bin/watchman
  Managers:
    CocoaPods: 1.10.1 - /usr/local/bin/pod
  SDKs:
    iOS SDK:
      Platforms: iOS 14.4, DriverKit 20.2, macOS 11.1, tvOS 14.3, watchOS 7.2
    Android SDK:
      API Levels: 29, 30
      Build Tools: 28.0.3, 29.0.2, 29.0.3
      Android NDK: Not Found
  IDEs:
    Android Studio: 4.1 AI-201.8743.12.41.7199119
    Xcode: 12.4/12D4e - /usr/bin/xcodebuild
  Languages:
    Java: 1.8.0_121 - /usr/bin/javac
    Python: 2.7.15 - /Library/Frameworks/Python.framework/Versions/2.7/bin/python
  npmPackages:
    @react-native-community/cli: Not Found
    react: 16.14.0 => 16.14.0 
    react-native: 0.62.2 => 0.62.2 
    react-native-macos: Not Found
  npmGlobalPackages:
    *react-native*: Not Found

Library version: 7.2.3

Steps To Reproduce

onNotification: function (notification) {
    // do something
}

The above code only runs when the notification is tapped and if the app was previously opened. However, if the app was not opened, it never runs.

I'm trying to handle the case when the user taps on the notification and the app wasn't opened / was killed, in order to react to it accordingly.

I see from RN logs that an initialProps object is added when the app opens from the notification on iOS, could this be used to add extra info?

Thanks!

I'm facing this exact issue. Were you guys able to fix it?

parth-koshta avatar Jul 07 '21 15:07 parth-koshta

We were using react-native-bootsplash and it was working just fine. Then we removed it and onNotification was no longer called. We tried a few things and eventually we realized (with a little bit of help from this SO answer) that were missing the following in the .MainActivity:

<intent-filter>
    <action android:name="android.intent.action.MAIN" />
    <category android:name="android.intent.category.INFO" />
</intent-filter>
so in total that now looks like this:
<activity
  android:name=".MainActivity"
  android:label="@string/app_name"
  android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
  android:windowSoftInputMode="adjustResize"
  android:exported="true"
  android:launchMode="singleTask">
  <intent-filter>
    <action android:name="android.intent.action.MAIN" />
    <category android:name="android.intent.category.INFO" />
  </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:scheme="nora"/>
  </intent-filter>
</activity>
<activity
  android:name=".SplashScreenActivity"
  android:theme="@style/BootTheme"
  android:launchMode="singleTask">
  <intent-filter>
    <action android:name="android.intent.action.MAIN" />
    <category android:name="android.intent.category.LAUNCHER" />
  </intent-filter>
</activity>

miallo avatar Feb 01 '22 16:02 miallo

I faced the same problem and for me the solution was to turn off the debug mode on the real device and after that the onNotification method started working.

FrontendTerminator avatar Oct 03 '22 09:10 FrontendTerminator