Cordova-plugin-firebase: onNotificationOpen not fired if the app is in closed - app process is killed in the background.

Created on 24 Nov 2016  ·  46Comments  ·  Source: arnesson/cordova-plugin-firebase

Hi,

I don't know if this default behaviour or not. But when the app is in closed (the app process is killed), then the push notification is coming and tap on it, the onNotificationOpen is not fired. Is this as expected or something need to work on it?

messaging

Most helpful comment

FirebasePlugin.java

@Override
protected void pluginInitialize() {
    final Context context = this.cordova.getActivity().getApplicationContext();
    final Bundle extras = this.cordova.getActivity().getIntent().getExtras();
    this.cordova.getThreadPool().execute(new Runnable() {
        public void run() {
            Log.d(TAG, "Starting Firebase plugin");
            mFirebaseAnalytics = FirebaseAnalytics.getInstance(context);
            if(extras != null && extras.size()>1) {
                // FirebasePlugin.sendNotification(extras);
                if (FirebasePlugin.notificationStack == null) {
                    FirebasePlugin.notificationStack = new ArrayList<Bundle>();
                }
                notificationStack.add(extras);

            }
        }
    });
}

All 46 comments

me too facing same issue :(

use the cordova resume event to hook the callback up again. see the cordova docs about the android lifecycle: http://cordova.apache.org/docs/en/6.x/guide/platforms/android/index.html#lifecycle-guide

@robertarnesson Would you mind explaining your answer a little more? I'm getting the same issue on iOS. I can receive notifications while the app is running in the foreground and background, but as soon as I close/quit my app, I cannot receive notifications anymore.

I do receive notifications on both, background and foreground (Android 6.0.1)... But open notification is not firing app, tray notification clears after tap and notification data is lost. (this happens even when app is in pause). Can it be because of crosswalk? Is there any fix?

@robertarnesson @Taracque

Not sure if this helps, but I really hate it when people use words or links instead of their own code samples to try and help.

This is a basic interpretation of what I have in my index.html and this works for iOS and Android with payload being delivered to the app for manipulation.

I found that with iOS I only needed to use 'deviceready' function of cordova.js as this seemed to fire whenever a notification was received when the apps was in the foreground AND after resuming an app that was in the background be it by tapping the notification or just opening the app.

For Android I needed to use 'resume' as 'deviceready' only seemed to fire once when the app first loaded (makes sense I suppose).

function onLoad(){

    //fire this with load of the HTML page
    document.addEventListener("deviceready", onDeviceReady, false);

    }

    function onDeviceReady(){

    // this will fire when the app first runs (iOS and Android)
    // iOS will run this after tapping a notification as well but not Android

    // Create the resume as soon as the device is ready.
    document.addEventListener("resume", onResume, false); 

    // add initial cordova-plugin-firebase function calls here
    // e.g TokenRefresh, onNotificationOpen etc

    window.FirebasePlugin.onTokenRefresh(function(token){

    //Do something with the token server-side if it exists

    });

    // get any initial or resume notification (used for iOS)
    var payload = getNotification();

    }

    function getNotification(){

    // get any notification variables for use in your app
    window.FirebasePlugin.onNotificationOpen(function(notification){

    //Check if notification exists then do something with the payload vars
    var str = JSON.stringify(notification);
    console.log(str);

    });

    return str;

    }

    function onResume(){
    //Add plugin functions here after app has resumed from background
    // or after notification is tapped (needed for Android)

    //get resume notification and payload (needed for Android)

    var payload = getNotification();

    }

hi guys, I think we miss the point here. the app itself not even on the background or foreground. you try killed the app and the function not being fired, we cant use on resume because the app not suspended, the app not moving to foreground but being started. even after device ready, onNotification open is not fired.

Not sure I understand but is this correct.

1: your app is totally inactive
2: you receive native notification for the app
3 you click notification
4 the app loads
5 onNotificationOpen is not firing

Is this correct?

What OS is this for?

Can you provide some of your code?

Did you include Cordova.js in your script?

Are you 100% sure you have no js errors in the loading page?

@device68 I would like to know if onNotificationOpen is fired when the app is not launched initially, like @nikrhes said.
I've tested on both Android and iOS with onNotificationOpen being called on resume and deviceready. And only the situation I mentioned above did not work. There are also some unexpected behaviors with other situations also.
You could check out issue #137 which I opened.

@chanphillip, I'll have a look in the morning. I can't confirm iOS 10 as I'm using an older version of XCODE, but I will see what exactly is happening on Android.

My App makes significant use of both cold starting with payloads from notifications and resume, but have not noticed any issues.

@device68 all situation is working fine only when the app is inactive the function is not fired at all. I am tested, almost on every IOS and android OS I can grab my hands on. Still not working.

From what I recall during my tests today in Android this is what happens.

1 inactive app

If I receive a notification and click it, this loads the app as expected and any plugin code within onDeviceReady will capture that payload.

Any code within Resume will not capture the payload.

Any further notifications while the app is still active and has not yet been minimised, is received by functions inside onDeviceReady.

2 minimising the app first time.

The first time I minimise the app this stops onDeviceReady because the decice already ready and now waiting for resume state.

If I get a notification and tap it the app opens and plugin code inside Resume now captures the payload.

Any subsequent notifications are all received by Resume.

3 minimised app (generally speaking)

If my app is minimised at any time and I click a notification Resume captures this, BUT if I don't click it and instead open the app manually, Resume does nothing and no onNotificationOpen is fired anywhere in my code.

Note this activity is totally different in iOS 9.3

4 foreground app

If after resuming I get a notification while in the app, Resume captures the payload.

5 killing app

If I kill the app, we start from #1

6 Payloads

The two differences I have seen with the data GCM sends on Android depends on if the notification was clicked outside the app or received while it's in the foreground.

Google adds timecode, from, message ID etc if notification is tapped.

Google removes the above but adds just tap = false in all other circumstances.

Any data vars you send are present in all cases.

I'm using server side Curl API to send messages between web, Android and iOS

Ultimately everything seems logical on Android, it's actually iOS implementation that is wrong and illogical.

Everything on iOS works with onDeviceReady and onNotificationOpen is called everytime a notification is received even when you open an app manually after getting notified, clicking a message or receiving a notification while app is in foreground.

Hope this helps.

But you must use both onDeviceReady and Resume and place versions of onNotificationOpen under each if you want to capture the payload under all situations.

@device68 Thanks for your detailed explanation.
In fact I said it wrong, I was also putting onNotificationOpen into both device resume and ready, but use case 1 (clicking the notification when the app is not even launched) didn't work on my end, while the other use cases are working like what you described.

I assume you are not using ionic framework during testing. I'm using platform.ready() but it should be the same as deviceready from my understanding.

Could you double confirm that onNotificationOpen is fired even when the app is not launched (the app was killed) on your side? Also is it possible for you to test this on iOS as well? Thank you.

@chanphillip no problem glad I can aid.

Correct, I'm just using the raw phonegap plugin installed via CLI and then this plugin installed within it.

Hmm actually I did some further tests and created a video of my device with alerts in 4 places.

https://www.youtube.com/watch?v=xrWQH2wE8Fo

This does seem to confirm what you are seeing. onNotificationOpen is NOT fired at all when tapping a notification which causes a cold boot of the app. Its only after this that notifications are collecting from the function onNotificationOpen.

The listeners fire as expected but not onNotificationOpen.

For me this isn't specifically an issue for my app which probably explains why I hadn't seen it till now.

I have tested on devices running Android 4+, 6+ and 7+, all same result.

Unfortunately I don't think I can help much with iOS, I'm using Virtualbox with Yosemite and XCODE 7.1 (forced to include iOS 9.3 SDK) I did find notifications worked exclusively with onDeviceRedy and didn't even need to use Resume. This was for devices with iOS 9+ but below 10+

However the end users updated their phones to 10.2 and notifications have stopped working period. I believe that's because of my XCODE building with 9.3 SDK, I now need to buy a Mac :-(

Let me know if the video helps.

I face the same problem. App opens but it doesn't trigger the function. I tried to reproduce the behavior on your video and of course i'm waiting for ondeviceready state. But the method never triggers.

Please note: on evaluating the function via lighttable socket, it works. It ONLY works when I eval it on the IDE. But the function never triggers, such as the plugin version of method is "not called". Why evaluating the function works?

Hi there,
I'am facing the same issue, so i'am trying to understand what's going on in the code.
For the cold start usecase the doc says to use onNewIntent.
The code for the plugin looks good.

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

But this callback to be called need that the notification set an intent to start using click_action in the payload

{
  "to": "/topics/news",
  "notification": {
    "title": "Click Action Message",
    "text": "Sample message",
    "click_action": "android.intent.action.MAIN"
  }
}

I'am trying to do so but without success, not sure to want must be set in click action.
Whatever the value i set the app do not launch

        <activity android:name="MainActivity" >
            <intent-filter android:label="@string/launcher_name">
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

To work around the miss of click action perhaps it could be nice to read the extra content during the plugin init.
I try with this code and this time i got the notification.

@Override
    protected void pluginInitialize() {
        final Context context = this.cordova.getActivity().getApplicationContext();
        final Bundle extras = this.cordova.getActivity().getIntent().getExtras();
        this.cordova.getThreadPool().execute(new Runnable() {
            public void run() {
                Log.d(TAG, "Starting Firebase plugin");
                mFirebaseAnalytics = FirebaseAnalytics.getInstance(context);
                if(extras != null && extras.size()>1) {
                    FirebasePlugin.sendNotification(extras);

                }
            }
        });
    }

Anyway it looks like a dirty hack.

Ok i manage to use click_action by adding a the default categorie in the manifest.xml but onNewIntent is not called.

            <intent-filter android:label="@string/launcher_name">
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>

FirebasePlugin.java

@Override
protected void pluginInitialize() {
    final Context context = this.cordova.getActivity().getApplicationContext();
    final Bundle extras = this.cordova.getActivity().getIntent().getExtras();
    this.cordova.getThreadPool().execute(new Runnable() {
        public void run() {
            Log.d(TAG, "Starting Firebase plugin");
            mFirebaseAnalytics = FirebaseAnalytics.getInstance(context);
            if(extras != null && extras.size()>1) {
                // FirebasePlugin.sendNotification(extras);
                if (FirebasePlugin.notificationStack == null) {
                    FirebasePlugin.notificationStack = new ArrayList<Bundle>();
                }
                notificationStack.add(extras);

            }
        }
    });
}

I had the same problem as described above, mainly, notification payload wasn't delivered when the app was started via tapping a notification. @huny0522's suggestion seems to fix the problem. 👍

Interesting, I don't specifically need this, but will try as well and see if it works for me. Would be ideal if the developers of this plugin could implement this change somehow as it does seem like a big issue for most people who need notification payload after cold boot of an app.

This issue is fixed or will be fix in next release!?

Patch from @huny0522 didn't resolve the issue for me. onNotificationReceived callback ignored with Android cold start. All other scenarios behave as expected.

Reinstalling the plugin from github solved the issued for me, after trying all the suggested solutions

cordova plugin add https://github.com/arnesson/cordova-plugin-firebase.git --save

Some one have solve the

step 3 that @device68 wrote ??

minimised app (generally speaking)

If my app is minimised at any time and I click a notification Resume captures this, BUT if I don't click it and instead open the app manually, Resume does nothing and no onNotificationOpen is fired anywhere in my code.

This is my only problem now.

Similar problem here.

I had to remove this line from sent object : "click_action":"YOUR_DATA_HERE".

Now, the App lauch correctly when I touch notification recieved in background.

Hope it helps.

I also have the same issues on a ionic/cordova app, but only on a device with Android 6.0. In this device the notification is always triggered in the status bar, whether I have the app in background or foreground(!) and the callback never gets triggered when I open the notification, thus I don't get the payload.
Every other device I tested was fine (android 5, iOS 9 and10): on foreground it triggers the callback data and I react to it, and on the background receives the notification normally in status bar as described in docs.

@abhishek-kollipara the issue discussed is not how to pick up the payload in the foreground/background state, rather when the app is cold booted through the tapping of a notification and picking up the notification payload from it. this is not the issue on how the payload is formed especially when it's described in the docs of another plugin and not this one.

I've had my first success with catching the payload on a cold boot since last two days when i started hunting it down. get the ionic native plugin 'web intent'. install it as documented and use it's built-in function getIntent() on boot. if the app is booted by a notification, the notification data will be somewhere inside the returned object.

@heidji This works on IOS?

On my case:

Android:
-Cold start: Launch OnNotificationOpen
-Minimised app: Launch OnNotificationOpen
-Foreground app: Launch OnNotificationOpen

IOS:
-Cold start: NOT Launch OnNotificationOpen
-Minimised app: Launch OnNotificationOpen
-Foreground app: Launch OnNotificationOpen

Thanks for help

@Hanzofm I don't know if it works on iOS to be honest. just try to use the Web Intent plugin and log its output in the console on boot.

I have the same behavior in iOS described by @Hanzofm

I have the same behavior in iOS. The onNotificationOpen is not called on Cold start of the iOS app on clicking the notification. Using the plugin version 0.1.25.

Update:
I was using the "cordova-plugin-local-notifications" as well with firebase plugin and that caused the issue. When I removed the "cordova-plugin-local-notifications" plugin it worked fine.

I'm also having trouble getting noNotificationOpen to fire on cold starts (iOS). Is there a solution out there?

Thanks

In my case was solved removing the local-notifications plugin. There are a incompatibility with this plugin and the push notification plugins

I don't have that plugin, unfortunately :)

Is this supposed to be on?

skjermbilde 2018-04-27 kl 09 22 50

Closing for cleanup. Please test with the latest version and reopen if it is still an issue.

@heidji let's say that we solved the issue by using your method, do you have any about how to get the notification data in the following situation?

The app is completely closed. User receives push notification. User doesn't click on notification but instead removes it from the notification bar. User opens the app later and goes to the notifications page and sees nothing. Because user neither get the notification in foreground nor clicked on it to open the app. But we still need to know that this notification exist to show the user. How to do this in ionic3?

@akildemir there is no way to do so in Ionic, you will have to log notifications on your own server and retrieve them when the user opens the app like anybody would normally do.

@heidji how am I gonna log the notifs to my server to retrieve it, if I don't know that this notification exist?
Is there a way firebase also sends the notifs to my server with device or Did you mean not using firebase but using your own server for notifs?

@akildemir I mean when you CREATE a push notification you also register it's existence somewhere else, like on your own server or whatever server you are using for your project. I think firebase also provides these services.
I don't know how you create these notifications but in my project when something happens on my PHP server, for example someone sent you a message, I contact firebase to send a notification and i ALSO store this event with an "is_read = 0" flag, so if the user never clicks the notification he can retrieve it on the website or the app uses your own service to call these notifications or whatever, just standard dev stuff..

@heidji I don't have a website for my app but yea what you said is pretty logical I can store the notification in my server at the same time and retrieve it later. Thanks! and yes I can be counted as newbie in mobile dev stuff. Also can I ask something else? How can i register same notification to multiple devices trough firebase? you can think of it like group chat. When someone type something in the group chat everyone in the group gets it. I am using this format to register a notification :

let body = {
"notification":{
"title":"title", "body":"body",
},
"data":{
"param1" : "value1"
},
"to":DeviceId,
"priority":"high",
"restricted_package_name":""
}

  let options = new HttpHeaders().set('Content-Type','application/json');
  this.http.post("https://fcm.googleapis.com/fcm/send",body,{
    headers: options.set('Authorization', 'key=),
  })

here if you pass deviceId to "to" section it sends to the device. but can I pass multiple deviceId's here?

@nikrhes You can check it in meta data:
window.FirebasePlugin.onNotificationOpen().subscribe((data) => {
if (data.tap) {
// user tapping on the notification
} else {
// app is running in the foreground
}
});

I'm not sure that this was ever solved but have been looking for the answer for months through the various threads out there about it. To be clear, the issue is onNotification not firing specifically in the case of iOS where the app is completely closed/off/killed. The notification comes in, cold boot the app, but the function doesn't fire and payload is not delivered.

@heidji - your work around solution of storing the push events on the server and checking if they have been read makes sense. However, in our app there are scenarios that this won't work for (i.e. and we need the determination as to whether the notification is fired to be based on whether the user actually clicked it not whether they have read it.)

But the main thing, as so many others have stated, is that this seems to be critical behavior for which there must be a solution?

@wwwguy my solution is not a workaround. it is standard practice everybody uses, big or small.
you cannot rely on notification presses, these aren't guaranteed events. i mean when i press a facebook notification on my xiaomi phone sometimes the app never even opens.

Yes I understand. We have deployed dozens of apps for many different clients. We use the practice of tracking notifications "reads" on the server as well in several of our apps. But there are other cases to consider - i.e. notifications that are more than just simple notifications, but rather carry payloads that then direct certain functionality within the app if they are clicked on. Facebook is crap. Everyone knows this. But FB notifications are also just that, simple notifications (that just show up in an archive list inside the app). They are not functional in nature. i.e. there's not certain types of FB notifications that when you click them it needs to open the app and direct you to a specific place.

Anyway... I wasn't necessarily posting to get into a big philosophical discussion (actually was just giving a nod to @heidji for the good idea as that would take care of the issue in a lot of cases). But surely we can all agree that this:

Android Open App = WORKS
iOS Open App = WORKS
Android Background App = WORKS
iOS Background App = WORKS
Android Cold Boot From Killed App = WORKS
iOS Cold Boot From Killed App = NOT WORKING

...is not the intended design of the plugin. So it is either a bug that the developer has not addressed (perhaps due to the confusion causes on all these various threads and different people misdiagnosing what the issue is), or else something else like variables passed in the PUSH body or functionality compiled in xCode causing this behavior.

Bug fix for the plugin by the developer aside... has anyone been able to isolate a manual code fix for this?

honestly notification from cold boot on iOS works for me 100%. i used the webintent plugin only for android because onNotificationOpen didn't work for me there and webintent doesn't exist on iOS.
if u need any specifics on my setup let me know

Was this page helpful?
0 / 5 - 0 ratings

Related issues

merbin2012 picture merbin2012  ·  4Comments

rolinger picture rolinger  ·  3Comments

rolinger picture rolinger  ·  5Comments

JonSmart picture JonSmart  ·  3Comments

eilian92 picture eilian92  ·  4Comments