Skip to content

onNotificationOpened not working on Android (background/foreground) #1272

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

Closed
nopmengkoung opened this issue Jul 4, 2018 · 43 comments
Closed
Assignees

Comments

@nopmengkoung
Copy link

Issue

When my app is closed and I tapped on notification getInitialNotification is working fine on both platforms, but on android when I tapped on notification and my app is in background/foreground onNotificationOpened didn't triggered. When my app in foreground I display a local notification.

const notify = new firebase.notifications.Notification()
      .setNotificationId(notification._notificationId)
      .setTitle(notification._title)
      .setBody('Tap here to view more detail')
      .setData({...notification._data})
      .android.setChannelId('notif-channel')
      .android.setSmallIcon('ic_launcher')

    firebase.notifications().displayNotification(notify)

Environment

  1. Application Target Platform: Both
  1. Development Operating System: macOS High Sierra
  1. Build Tools:
  1. React Native version: 0.54
  1. React Native Firebase Version: 4.0.4
  1. Firebase Module: notifications
  1. Are you using typescript? no

Loving react-native-firebase? Please consider supporting their open collective:

👉 https://opencollective.com/react-native-firebase/donate

@borapop
Copy link

borapop commented Jul 5, 2018

Same issue

@Nicholas1490
Copy link

Hi,

I am having the same issue.
The onNotificationOpened listener doesn't trigger when the app is in the background and I received the notification.

It triggers if the app is in the foreground.
getInitialNotification also triggers when the app is dead.

@yangnana11
Copy link

Hello,

It trigged for me though. But it doesn't get the notification data correctly, I've got undefined if it got when it goes background

       this.notificationOpenedListener = firebase.notifications().onNotificationOpened((notificationOpen: NotificationOpen) => {
            // Get the action triggered by the notification being opened
            const action = notificationOpen.action;
            // Get information about the notification that was opened
            const notification: Notification = notificationOpen.notification;
            alert(notification.body);
            firebase.notifications().removeDeliveredNotification(notification.notificationId);
        });

@vomchik
Copy link

vomchik commented Jul 9, 2018

the same problem :(

@vomchik
Copy link

vomchik commented Jul 9, 2018

my problem was in this .MainActivity class

Before:

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

After:

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

i forgot about this super.onNewIntent(intent);

@Nicholas1490
Copy link

@vomchik didn't work for me :(

I was really hoping this was the solution.
I remember using that snippet of code from another notification plugin and I took it out.

@dengue8830
Copy link

dengue8830 commented Jul 10, 2018

in my case, i was missing the notification's data setup when building the notification on foreground notification event firebase.notifications().onNotification

new firebase.notifications.Notification()
      .setNotificationId(fcmNotification.data.notificacionId)
      .setTitle(fcmNotification.title)
      .setBody(fcmNotification.body)
      .setData(fcmNotification.data) // <- this little bastard

so, when tapping the notification data was undefined on firebase.notifications().onNotificationOpened even when the json that comes in firebase.notifications().onNotification had data field filled

@nopmengkoung
Copy link
Author

On my side this issue is solved by doing nothing. When I tested on debug mode its not working but after I running release its working. That's weird for me too.

@Salakar
Copy link
Contributor

Salakar commented Jul 21, 2018

Duplicate of #988 and others.

Please check there and the many other duplicates of this issue for a resolution, specifically see this comment #988 (comment) for a complete reference example.

Some common causes on Android are:

  • you've not set up a notification channel
  • missing a notification sound / add a default sound
  • not added the services/intents to AndroidManifest as defined here

Loving react-native-firebase and the support we provide? Please consider supporting us with any of the below:

@Salakar Salakar closed this as completed Jul 21, 2018
@willdady
Copy link

@Salakar This is not a duplicate of #988. That issue is referring to notifications not appearing in the foreground when triggered by the app itself. This issue is about the onNotificationOpened event not firing after tapping the notification.

I'm sending messages via the Cloud Messaging console and they appear fine in the simulator however when pressing the notification the onNotificationOpened event never fires. I've tried with and without explicitly creating a channel a as described here.

Also the getInitialNotification is always null when the app is cold-launched from pressing a notification.

@gabrielbull
Copy link
Contributor

@Salakar Please re-open, we are all experiencing this issue.

@Salakar Salakar reopened this Jul 23, 2018
@Salakar Salakar added Workflow: Needs Review Pending feedback or review from a maintainer. help: general General help wanted labels Jul 23, 2018
@Salakar
Copy link
Contributor

Salakar commented Jul 23, 2018

@willdady sorry I actually meant this was a duplicate of #1230 - can I close this in favour of the other one?


Hey @gabrielbull been a while! Small world... 😄


@yangnana11 this is correct, see the below section from the docs:
image
Source: https://rnfirebase.io/docs/v4.3.x/notifications/receiving-notifications#4)-Listen-for-a-Notification-being-opened

If you need them then you can additionally send them as part of your data in your notification as well.

@Salakar
Copy link
Contributor

Salakar commented Aug 4, 2018

Closing in favour of #1230 - definitely a duplicate this time 🙈 see my latest comment there as well.

Thanks

@Salakar Salakar closed this as completed Aug 4, 2018
@Salakar Salakar added resolution: duplicate and removed Workflow: Needs Review Pending feedback or review from a maintainer. labels Aug 4, 2018
@Salakar Salakar self-assigned this Aug 4, 2018
@Salakar Salakar added question and removed help: general General help wanted labels Aug 4, 2018
@laukaichung
Copy link

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

This solution doesn't work.

@ZardozSpeaks
Copy link

My solution to this problem is pretty implementation specific, but you never know what might help.

My issue was that I had a splash activity which was the actual launcher activity. To get the callbacks to fire in App.js I had to:

  1. Add "singleTop" to the activity tag for SplashActivity.java in AndroidManifest.xml
  2. Use "this.getIntent();" within the onCreate method of SplashActivity.java to intercept the intent from the firebase notification open event
  3. Use .getExtras() to take the bundle from the intercepted intent and attach it to a new intent forwarded to .MainActivity

As soon as .MainActivity had access to the intent all of the callbacks began firing on the correct events.

@dakt
Copy link

dakt commented Sep 6, 2018

@msrivas
Can you provide code please? I'm also stuck with same "onNotificationOpened" issue.

@juanpaie
Copy link

Solved the issue only on background using @ZardozSpeaks approach.

Under my SplashActivity.java, I added the following:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Intent fcmIntent = this.getIntent();
        Bundle bundle = fcmIntent.getExtras();

        Intent intent = new Intent(this, MainActivity.class);
        intent.putExtras(fcmIntent);
        startActivity(intent);
        finish();
    }

I'm still trying to find the solution for foreground notifications.

@awdhootlele
Copy link

awdhootlele commented Oct 9, 2018

Solved the issue only on background using @ZardozSpeaks approach.

Under my SplashActivity.java, I added the following:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Intent fcmIntent = this.getIntent();
        Bundle bundle = fcmIntent.getExtras();

        Intent intent = new Intent(this, MainActivity.class);
        intent.putExtras(fcmIntent);
        startActivity(intent);
        finish();
    }

I'm still trying to find the solution for foreground notifications.

I tried this and my onNotificationOpened() callback is firing now, but I get undefined as a body inside the notification.
Also, as @ZardozSpeaks said, I also tried to pass the Bundle (using currentIntent.getExtras()) instead of the actual Intent, still getting undefined inside my notification.

In my main activity I have :
@OverRide
public void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
}

And in androidManifest.xml, I have set android:launchMode="singleTask" for both Main activity and Splash activity. Still no luck :(

@ofri84
Copy link

ofri84 commented Oct 23, 2018

in our app we use MainActivity which extends SplashActivity (from react-native-navigation) which extends AppCompatActivity.
the rnfirebase implements ActivityEventListener.
so:

  1. onNewIntent in MainActivity doesn't get called and even if it did, calling super.onNewIntent won't help us.
  2. since app is in the background onCreate in MainActivity/SplashActivity doesn't get called either.

I added: notification.android.setClickAction('...');
to the local notification so it created another intent which restart the app (after it came back to foreground) and then on getInitialNotification() get called with the local notification.
I know its not a good solution but for now it helps us...

@rizasifmap
Copy link

Any updates on this? I am stuck here. Tried all solutions above.

@daviswhitehead
Copy link

I solved this with the following files

NotificationListeners.js

import firebase from 'react-native-firebase';
import { ts } from './FirebaseHelpers';
// https://rnfirebase.io/docs/v5.x.x/notifications/introduction

export const notificationDisplayedListener = () =>
  // app in foreground
  firebase.notifications().onNotificationDisplayed(notification => {
    console.log('onNotificationDisplayed');
    console.log(notification);
  });

export const notificationListener = () =>
  // app in foreground
  firebase.notifications().onNotification(notification => {
    console.log('notificationListener');
    console.log(notification);

    const localNotification = new firebase.notifications.Notification({
      sound: 'default',
      show_in_foreground: true,
      show_in_background: true,
    })
      .setNotificationId(notification.notificationId)
      .setTitle(notification.title)
      .setSubtitle(notification.subtitle)
      .setBody(notification.body)
      .setData(notification.data)
      .android.setChannelId('General')
      .android.setSmallIcon('@mipmap/ic_notification')
      .android.setColor('#F2C94C')
      .android.setPriority(firebase.notifications.Android.Priority.High);

    firebase.notifications().displayNotification(localNotification);
    console.log('displayed');
    firebase.notifications().removeDeliveredNotification(localNotification.notificationId);
  });

export const notificationOpenedListener = () =>
  // app in background
  firebase.notifications().onNotificationOpened(notificationOpen => {
    console.log('notificationOpenedListener');
    console.log(notificationOpen);
    const { action, notification } = notificationOpen;
    firebase.notifications().removeDeliveredNotification(notification.notificationId);
    console.log('OPEN:', notification);
  });

export const notificationTokenListener = userId =>
  // listens for changes to the user's notification token and updates database upon change
  firebase.messaging().onTokenRefresh(notificationToken => {
    console.log('notificationTokenListener');
    console.log(notificationToken);

    return firebase
      .firestore()
      .collection('users')
      .doc(userId)
      .update({ pushToken: notificationToken, updatedAt: ts })
      .then(ref => {
        console.log('savePushToken success');
      })
      .catch(e => {
        console.error(e);
      });
  });

SplashActivity.java

package com.daviswhitehead.shayr.android;

import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;

public class SplashActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Intent intent = new Intent(this, MainActivity.class);
        
        // Pass along FCM messages/notifications etc.
        Bundle extras = getIntent().getExtras();
        if (extras != null) {
            intent.putExtras(extras);
        }

        startActivity(intent);
        finish();
    }
}

AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.daviswhitehead.shayr.android"
    xmlns:tools="http://schemas.android.com/tools" >

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
    <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"
        tools:replace="android:label">

        <activity
            android:name=".SplashActivity"
            android:theme="@style/SplashTheme"
            android:label="@string/APP_NAME"
            android:launchMode="singleTask" >
            <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"
            android:exported="true"
            android:launchMode="singleTask" >
        </activity>
      
        <meta-data android:name="com.facebook.sdk.ApplicationId" android:value="@string/facebook_app_id"/>
      
        <activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />

        <!-- NOTIFICATION DEFAULTS -->
        <meta-data
            android:name="com.google.firebase.messaging.default_notification_channel_id"
            android:value="@string/default_notification_channel_id"/>

        <!-- Set custom default icon. This is used when no icon is set for incoming notification messages.
            See README(https://goo.gl/l4GJaQ) for more. -->
        <meta-data
            android:name="com.google.firebase.messaging.default_notification_icon"
            android:resource="@mipmap/ic_notification" />
            <!-- android:resource="@drawable/ic_notification" /> -->
        <!-- Set color used with incoming notification messages. This is used when no color is set for the incoming
            notification message. See README(https://goo.gl/6BKBk7) for more. -->
        <meta-data
            android:name="com.google.firebase.messaging.default_notification_color"
            android:resource="@color/yellow" />
        
        <!-- SHARE ACTIVITY -->
        <activity
            android:noHistory="true"
            android:name=".share.ShareActivity"
            android:configChanges="orientation"
            android:label="@string/TITLE_ACTIVITY_SHARE"
            android:screenOrientation="portrait"
            android:theme="@style/Theme.Share.Transparent" >
            <intent-filter>
                <action android:name="android.intent.action.SEND" />
                <category android:name="android.intent.category.DEFAULT" />
                //  for sharing links include
                <data android:mimeType="text/plain" />
                //  for sharing photos include
                <data android:mimeType="image/*" />
            </intent-filter>
        </activity>
      
        <!-- FABRIC -->
        <meta-data
            android:name="io.fabric.ApiKey"
            android:value="c12e5c4bb8cd8ca855a8ada44fa3fde413006659" />
        
        <!-- REACT-NATIVE-FIREBASE NOTIFICATIONS -->
        <service android:name="io.invertase.firebase.messaging.RNFirebaseMessagingService">
            <intent-filter>
                <action android:name="com.google.firebase.MESSAGING_EVENT" />
            </intent-filter>
        </service>
        
        <service android:name="io.invertase.firebase.messaging.RNFirebaseInstanceIdService">
            <intent-filter>
                <action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
            </intent-filter>
        </service>

        <!-- SCHEDULED NOTIFICATIONS -->
        <receiver android:name="io.invertase.firebase.notifications.RNFirebaseNotificationReceiver"/>
        <receiver android:enabled="true" android:exported="true"  android:name="io.invertase.firebase.notifications.RNFirebaseNotificationsRebootReceiver">
            <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED"/>
            <action android:name="android.intent.action.QUICKBOOT_POWERON"/>
            <action android:name="com.htc.intent.action.QUICKBOOT_POWERON"/>
            <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </receiver>
    </application>
</manifest>

@jayzyaj
Copy link

jayzyaj commented Apr 10, 2019

For those who were getting undefined on the data object when I console.log(notificationOpen.notification) on the returned promise of the onNotificationOpened it returns an object with a _data property instead of data.

Instead of this code block below:

 /*
    * If your app is in background, you can listen for when a notification is clicked / tapped / opened as follows:
    * */
    this.notificationOpenedListener = firebase.notifications().onNotificationOpened(notificationOpen => {
      const { data } = notificationOpen.notification;
      const { title, body } = data;
      console.log('Tapped the notifications when app is on background or foreground:', notificationOpen.notification);
      this.showAlert(title, body);
    });

I used this:

/*
    * If your app is in background, you can listen for when a notification is clicked / tapped / opened as follows:
    * */
    this.notificationOpenedListener = firebase.notifications().onNotificationOpened(notificationOpen => {
      const { _data } = notificationOpen.notification;
      const { title, body } = _data;
      console.log('Tapped the notifications when app is on background or foreground:', notificationOpen.notification);
      this.showAlert(title, body);
    });

Now everything works like a charm. I am using a newer firebase version btw

This is my package.json below:
"react-native": "0.59.2",
"react-native-firebase": "^5.2.3",

This is my project level build.gradle dependencies below:

    // Firebase dependencies
    implementation "com.google.android.gms:play-services-base:16.0.1"
    implementation "com.google.firebase:firebase-core:16.0.6"
    implementation "com.google.firebase:firebase-messaging:17.3.4"

@LuongTruong
Copy link

Hi guys, I am in the same situation, getInitialNotification and onNotificationOpened get call but both title and body are undefined

React native version: 0.57.0
react-native-firebase: 5.1.1
Running on AVD 8.1

I try everything above but no hope. Do you know any combination to make it work or I need to upgrade the version of react-native and react-native-firebase?

Thank you in advance!

@mikehardy
Copy link
Collaborator

I can't offer guidance on the specific issue but as regards upgrading I can think of a massive number of issues resolved between what you're running and current versions. You'll like the 'rn-diff-purge' project to take the fear out of react-native upgrades so you can get to 0.59.4 (actually 0.59.5 is releasing today I think), which will let you use react-native-firebase 5.3.1 and all the firebase SDK updates as well. Worth it I think

@LuongTruong
Copy link

thank you @mikehardy , I update the project to newest and it still undefined. However, I am able to receive the data from push notification. That is good for me

@pierregoutheraud
Copy link

I also ran into this problem (onNotificationOpened would not be triggered) and finally made it work.
I followed #1272 (comment), you also need to change your launchMode from singleTop to singleTask (don't ask me why).

@LuongTruong
Copy link

Hi @pierregoutheraud , I set the launchMode to singleTask but the title and body still remain undefined. However, the data is able to be received. Thank you 😄

@pierregoutheraud
Copy link

@truongluong1314520 The documentation says: "On Android, unfortunately there is no way to access the title and body of an opened remote notification. You can use the data part of the remote notification to supply this information if it's required."

@LuongTruong
Copy link

Thank you @pierregoutheraud

@danielzzz
Copy link

danielzzz commented Jul 29, 2019

in my case getInitialNotification was called but onNotificationOpened was not.

#1272 (comment)
did not work for me (there was just a blank screen and the app would not start)

but I as getInitialNotification was called always whenever the app came to foreground I used this (combined with checking if I have already processed this notifictation) to workaround this problem.

I added getInitialNotification when initializing the App (to catch a cold start) and then boud it to appstate.change to call the callback when the app came back from background to foreground.

_handleAppStateChange = (nextAppState) => {
    console.log("APP STATE");
    console.log(this.state.appState);
    console.log(nextAppState);
    if (this.state.appState.match(/inactive|background/) && nextAppState === 'active') {
      console.log('App has come to the foreground!')
      RNFirebase.notifications().getInitialNotification()
        .then(processNotification);
    }

    //update stored state
    this.setState({
      appState: nextAppState
    });
  }

componentDidMount() {
    AppState.addEventListener('change', this._handleAppStateChange);
    console.log('hiding the splash');
    SplashScreen.hide();
  }

  componentWillUnmount() {
    AppState.removeEventListener('change', this._handleAppStateChange);
  }

@elizaMathaai
Copy link

Have been struggling with background notitifcation no picking up in android... Got it to work finally. changed the launcher to singleTask. Thanks

@r4mdat
Copy link

r4mdat commented Oct 30, 2019

Using react-native-bootsplash which already forwards the FCM Intent. Just had to set <activity android:name=".MainActivity" _android:launchMode="singleTask"_ ... /> and onNotificationOpened works as expected.

@mikehardy
Copy link
Collaborator

Interesting @r4mdat if I were to re-do my splash screen (which I may in the future) I would use react-native-bootsplash over react-native-splash-screen - it seems to be handling the Intent correctly https://github.com/zoontek/react-native-bootsplash/blob/master/android/src/main/java/com/zoontek/rnbootsplash/RNBootSplashActivity.java#L27 which is why it doesn't have the problems splash-screen had when chaining Activities

@muhammad-ihsan
Copy link

I came here looking for the solution of why firebase.notifications().onNotificationOpened not triggered on background, and not using any additional package like react-native-bootsplash or react-native-splash-screen. I got stuck a month for this issue :(

@Dylan0916
Copy link

onNotificationOpened can be triggered, but _title and _body are undefined. 😕

"react-native": "0.60.6"
"react-native-firebase": "5.5.6"

@roger-ngx
Copy link

android document said "The other modes — singleTask and singleInstance — are not appropriate for most applications, since they result in an interaction model that is likely to be unfamiliar to users and is very different from most other applications." - I wonder what is "unfamiliar" behavior ?

@mikehardy
Copy link
Collaborator

React-native programming model for Android is that there is only one activity and really it should always be on top and all by itself. That makes sense since really it's javascript showing "screens" inside the activity.

In normal Android apps each screen is an Activity. And you might have the same screen showing different pieces of data, so two Activities on the stack with other Activities on top etc - so the normal Android app has a different Activity stack model and singleTask wouldn't fit it.

@jbdevelop
Copy link

Solved the issue only on background using @ZardozSpeaks approach.

Under my SplashActivity.java, I added the following:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Intent fcmIntent = this.getIntent();
        Bundle bundle = fcmIntent.getExtras();

        Intent intent = new Intent(this, MainActivity.class);
        intent.putExtras(fcmIntent);
        startActivity(intent);
        finish();
    }

I'm still trying to find the solution for foreground notifications.

Amazing! It works for me. Thank you! I also changed launchMode activity .MainActivity from singleTop to singleTask.

@mikehardy
Copy link
Collaborator

react-native-boot-splash is the thing to use. It passes Intent data correctly and is well maintained

@thaitd96
Copy link

@daviswhitehead thank you, it worked for me!!!

@TwistedMinda
Copy link

Issue seem to be persisting and not related to react-native-splash-screen : wix/react-native-notifications#958

@autimio
Copy link

autimio commented Jul 5, 2024

Using react-native-notifications worked for me.

import { Notifications } from 'react-native-notifications';
Notifications.getInitialNotification().then(async remoteMessage => {}).catch(err => { console.error(err, 'err') })

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

No branches or pull requests