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

Background mode notifications not receiving data in latest Firebase Cloud Messaging APIs and SDKs #266

Closed
viking2917 opened this issue Mar 6, 2024 · 10 comments

Comments

@viking2917
Copy link

Bug Report

As noted in (#257), Firebase Cloud Messaging is obsoleting the old way of sending notifications and as of June 2024 will require an upgrade to v1 (https://firebase.google.com/docs/cloud-messaging/migrate-v1)

The documentation for this plugin states that in order for the on('notification') handler to be triggered, one must omit the "data" section of the message payload and instead use the "notifications" field. This is the only way to handle custom data to be passed to an application when it is in background mode and receives a notification.

My app works correctly when used with the legacy endpoint for FCM (https://fcm.googleapis.com/fcm/send), and receives custom data used to process the notification. When using the new FCM endpoint and associated new auth methodology (e.g. https://fcm.googleapis.com/v1/projects/myproject-b5ae1/messages:send), the app notifications correctly receive the custom data when the app gets a notification in foreground, but NOT when the app is in background.

Google's documentation says the message payload should look more or less as follows:

{
  "message": {
    "topic": "news", OR ("token": < A Device Token >,)
    "notification": {
      "title": "Breaking News",
      "body": "New news story available."
    },
    "data": {
      "story_id": "story_12345"
    }
  }
}

Whereas this documentation (https://github.com/havesource/cordova-plugin-push/blob/master/docs/PAYLOAD.md#notification-vs-data-payloads)_ says that to trigger the on('notification') from a background notification one should effectively do this:

{
   "message": {
    "topic": "news", (OR "token": < A Device Token >,)
    "data": {
      "title": "Test Notification",
      "body": "This offer expires at 11:30 or whatever",
      "notId": 10,
      "surveyID": "ewtawgreg-gragrag-rgarhthgbad"
  }
}

thereby omitting the "data" field of the message.

In the old FCM, this works. In the new FCM, not only does the on('notification') not get triggered, but the notification displayed to the user has no title or body (because the "notifications" were not specified.)

Therefore it seems impossible to receive custom data from a background notification.

Has anyone successfully done this?

Expected Behaviour

Background notifications should invoke the on('notification') handler

Actual Behaviour

Background notifications, when used with the latest FCM V1 HTTP APi, do not raise the on('notification') handler

Reproduce Scenario (including but not limited to)

Steps to Reproduce

Platform and Version (eg. Android 5.0 or iOS 9.2.1)

(Android) Device Vendor (e.g. Samsung, HTC, Sony...)

cordova info Printout

Cordova Packages:

cli: 11.1.0
    common: 4.1.0
    create: 4.1.0
    lib: 11.1.0
        common: 4.1.0
        fetch: 3.1.0
        serve: 4.0.1

Project Installed Platforms:

android: 10.1.2
browser: 5.0.4
ios: 6.3.0

Project Installed Plugins:

@havesource/cordova-plugin-push: 4.0.0-dev.0
branch-cordova-sdk: 5.1.0
cordova-clipboard: 1.3.0
cordova-plugin-add-swift-support: 2.0.2
cordova-plugin-androidx-adapter: 1.1.3
cordova-plugin-androidx: 3.0.0
cordova-plugin-app-version: 0.1.12
cordova-plugin-camera-preview: 0.11.1
cordova-plugin-camera: 6.0.1-dev
cordova-plugin-chooser: 1.3.1
cordova-plugin-contacts: 3.0.1
cordova-plugin-device: 2.0.3
cordova-plugin-email-composer: 0.8.15
cordova-plugin-fbsdk: 4.0.2
cordova-plugin-file: 7.0.0
cordova-plugin-inappbrowser: 4.1.0
cordova-plugin-ionic-keyboard: 2.2.0
cordova-plugin-ionic-webview: 5.0.0
cordova-plugin-jitsi-meet-sdk: 4.0.9
cordova-plugin-network-information: 3.0.0
cordova-plugin-purchase: 13.10.0
cordova-plugin-sign-in-with-apple: 0.0.1
cordova-plugin-splashscreen: 6.0.2
cordova-plugin-x-socialsharing: 6.0.4
cordova-sms-plugin: 1.0.3
cordova-support-android-plugin: 1.0.1
es6-promise-plugin: 4.2.2
phonegap-plugin-barcodescanner: 8.1.1-dev

Environment:

OS: macOS 14.3 (23D56) (darwin 23.3.0) x64
Node: v14.15.4
npm: 6.14.10

android Environment:

android:

ERROR: Command failed with exit code 1: avdmanager list target
Exception in thread "main" java.lang.NoClassDefFoundError: javax/xml/bind/annotation/XmlSchema
at com.android.repository.api.SchemaModule$SchemaModuleVersion.(SchemaModule.java:156)
at com.android.repository.api.SchemaModule.(SchemaModule.java:75)
at com.android.sdklib.repository.AndroidSdkHandler.(AndroidSdkHandler.java:81)
at com.android.sdklib.tool.AvdManagerCli.run(AvdManagerCli.java:213)
at com.android.sdklib.tool.AvdManagerCli.main(AvdManagerCli.java:200)
Caused by: java.lang.ClassNotFoundException: javax.xml.bind.annotation.XmlSchema
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:581)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
... 5 more

ios Environment:

xcodebuild:

Xcode 15.1
Build version 15C65

Project Setting Files:

config.xml:
So you can post pictures to your Readings chat windows So you can post pictures to your Readings chat windows So you can post pictures to your Readings chat windows So you can save and post pictures to your Readings chat windows When you invite people to Readings, we'll upload their contact information to our servers so we can send them Reading Invitations on your behalf. fb instagram twitter
<branch-config>
         <OMITTED>
</branch-config>
<engine name="browser" spec="5.0.4" />
package.json:

--- Start of Cordova JSON Snippet ---
{
"plugins": {
"cordova-plugin-email-composer": {},
"cordova-clipboard": {},
"cordova-plugin-camera-preview": {
"ANDROID_SUPPORT_LIBRARY_VERSION": "26+"
},
"cordova-plugin-sign-in-with-apple": {},
"cordova-plugin-inappbrowser": {},
"cordova-plugin-app-version": {},
"cordova-plugin-device": {},
"cordova-plugin-androidx-adapter": {},
"cordova-plugin-chooser": {},
"cordova-plugin-androidx": {},
"cordova-plugin-jitsi-meet-sdk": {},
"cordova-plugin-network-information": {},
"cordova-plugin-ionic-keyboard": {},
"cordova-plugin-file": {
"ANDROIDX_WEBKIT_VERSION": "1.4.0"
},
"cordova-plugin-x-socialsharing": {},
"cordova-sms-plugin": {},
"cordova-plugin-contacts": {},
"branch-cordova-sdk": {},
"cordova-plugin-fbsdk": {
"APP_ID": "",
"APP_NAME": "",
"FACEBOOK_ADVERTISER_ID_COLLECTION": "false",
"CLIENT_TOKEN": "",
"FACEBOOK_URL_SCHEME_SUFFIX": " ",
"OTHER_APP_SCHEMES": " ",
"FACEBOOK_AUTO_LOG_APP_EVENTS": "true",
"FACEBOOK_HYBRID_APP_EVENTS": "false",
"FACEBOOK_ANDROID_SDK_VERSION": "14.1.1",
"FACEBOOK_IOS_SDK_VERSION": "14.1.0",
"FACEBOOK_BROWSER_SDK_VERSION": "v14.0"
},
"cordova-plugin-camera": {
"ANDROIDX_CORE_VERSION": "1.6.+"
},
"@havesource/cordova-plugin-push": {
"ANDROIDX_CORE_VERSION": "1.6.+",
"FCM_VERSION": "23.+",
"IOS_FIREBASE_MESSAGING_VERSION": "~> 8.1.1"
},
"cordova-plugin-purchase": {},
"cordova-plugin-ionic-webview": {},
"cordova-plugin-splashscreen": {},
"phonegap-plugin-barcodescanner": {
"ANDROID_SUPPORT_V4_VERSION": "27.+"
}
},
"platforms": [
"browser",
"android"
]
}
--- End of Cordova JSON Snippet ---

Sample Push Data Payload

Sample Code that illustrates the problem

Logs taken while reproducing problem

@ksch10bob
Copy link

@viking2917

We ran into the same issue:
The Documentation
https://github.com/havesource/cordova-plugin-push/blob/master/docs/PAYLOAD.md#notification-vs-data-payloads
pointed us to the right direction:

If we want the on notification handler to be called by clicking on the push notification when app is in backround we have to use the mixed payload with a special key-value pair "click_action": "com.adobe.phonegap.push.background.MESSAGING_EVENT"

{
"notification": {
"title": "Test Notification",
"body": "This offer expires at 11:30 or whatever",
"notId": 10,
"click_action": "com.adobe.phonegap.push.background.MESSAGING_EVENT"
},
"data": {
"surveyID": "ewtawgreg-gragrag-rgarhthgbad"
}
}

Did you try this?
It worked for us

@viking2917
Copy link
Author

Thanks @ksch10bob. That does not work for me. When I add notId and click_action to my payload, I get an error like this:

"error": {
    "code": 400,
    "message": "Invalid JSON payload received. Unknown name "notId" at 'message.notification': Cannot find field.\nInvalid JSON payload received. Unknown name "click_action" at 'message.notification': Cannot find field.",
    ...
}

To confirm, are you using the NEW FIREBASE messaging service? i.e. you are sending to

https://fcm.googleapis.com/v1/projects/<your project>/messages:send

and not:

https://fcm.googleapis.com/fcm/send

The new API has a different payload structure, and so far as I can tell does not allow the parameters the documentation for this plugin suggests adding.

If you are using the new service, are you sending to a "topic" or a "token"? (the new payload requires a "message" field with that specified, e.g.

 "message": {
    "topic": "news", 
   ...

OR

 "message": {
   "token": <A Device Token>,
...

Thanks for your help and any further details.

@ksch10bob
Copy link

ksch10bob commented Mar 19, 2024

@viking2917
We do not call the FCM endpoints directly.
We use AWS SNS and a "platform" for FCM (thats basically a container for the authentication.key) You can create a FCM platform with the new servicekey.json or the old apikey.
The documentation of AWS SNS states, that they use the new FCM service, when you create the platform with the servicekey.json.
For every platform Container we create so called "endpoints" with a devicetoken. So an endpoint represents a devicetoken.
We then publish messages to these endpoints.
But AWS SNS builds the real payload itself, we do not know how it looks like.

The FCM payload we give to AWS SNS has this structure
NO notId in the notification Object

{
    "notification": {
        "title": "Test Notification",
        "body": "This offer expires at 11:30 or whatever",
        "click_action": "com.adobe.phonegap.push.background.MESSAGING_EVENT"
     },
    "data": {
        "customData": "foobar"
    }
}

We think AWS SNS handles the wrapping of this payload into the new message Object that contains notification and data as keys.

Sorry for not being specific enough about our exakt payload and Infrastructure.
Maybe AWS SNS put the click_action into the data Object
Did you try to add the key value pair "click_action": "com.adobe.phonegap.push.background.MESSAGING_EVENT" to the data Object?

@viking2917
Copy link
Author

@ksch10bob. Thanks for your help!

I have the click_action on the data object. When the app is in background, the app opens when the alert is tapped, but the on() notification function does not fire, so no chance to handle the custom data. If I put the click_action on the data{} field, or for that matter on the top level message{} object, the post to FCM service returns an invalid field error. So I think it has to go on the data{} field and that is what I am trying.

Its good to know it works via SNS. Maybe I will try to set that up and then wireshark the payload or something. Just need to find the right magic dance :)

Will post here if/when I figure it out :)

@ksch10bob
Copy link

@viking2917
i just found this:
https://firebase.google.com/docs/cloud-messaging/concept-options#example-notification-message-with-platform-specific-delivery-options

{
  "message":{
     "token":"bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
     "notification":{
       "title":"Match update",
       "body":"Arsenal goal in added time, score is now 3-0"
     },
     "android":{
       "notification"{
         "click_action":"com.adobe.phonegap.push.background.MESSAGING_EVENT"
       }
     }
   }
 }

The click_action key has to be wrapped with the platform specific android key and the notification key

Hope that helps

@viking2917
Copy link
Author

tried that too already :)

@viking2917
Copy link
Author

viking2917 commented Mar 20, 2024

@ksch10bob found it.

You are correct, one does need the android section in the payload.

 "android":{
       "notification"{
         "click_action":"com.adobe.phonegap.push.background.MESSAGING_EVENT"
       }
 }

I had done that, but I also just discovered that somehow, not sure how, the following lines had been deleted from my AndroidManifest.xml, so the app would not start in background:

 <activity android:name="com.adobe.phonegap.push.BackgroundHandlerActivity" android:exported="true" android:permission="${applicationId}.permission.BackgroundHandlerActivity">
    <intent-filter>
        <action android:name="com.adobe.phonegap.push.background.MESSAGING_EVENT"/>
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity>

(I found this by running 'adb logcat' while the background notification was happening and watching for errors, in case helpful to anyone.)

For anyone else with this issue, my full payload looks like:

{
    message: {
	token: <devicetoken>m
	notification: {
	    title: "title",
	    body: "body"
	},
	android: {
	    notification: {
		click_action:  "com.adobe.phonegap.push.background.MESSAGING_EVENT"
	    }
	},
	data: {
            'content-available' => "1",
	    'customdata': 'foo',
	    notId: <an integer>,
	    etc
	}
    }
}

(I am passing notId, as per documentation, although in my experiments it does not seem to be required)

Thank you @ksch10bob !!!

@sithwarrior
Copy link

sithwarrior commented Apr 8, 2024

@viking2917 We do not call the FCM endpoints directly. We use AWS SNS and a "platform" for FCM (thats basically a container for the authentication.key) You can create a FCM platform with the new servicekey.json or the old apikey. The documentation of AWS SNS states, that they use the new FCM service, when you create the platform with the servicekey.json. For every platform Container we create so called "endpoints" with a devicetoken. So an endpoint represents a devicetoken. We then publish messages to these endpoints. But AWS SNS builds the real payload itself, we do not know how it looks like.

The FCM payload we give to AWS SNS has this structure NO notId in the notification Object

{
    "notification": {
        "title": "Test Notification",
        "body": "This offer expires at 11:30 or whatever",
        "click_action": "com.adobe.phonegap.push.background.MESSAGING_EVENT"
     },
    "data": {
        "customData": "foobar"
    }
}

We think AWS SNS handles the wrapping of this payload into the new message Object that contains notification and data as keys.

Sorry for not being specific enough about our exakt payload and Infrastructure. Maybe AWS SNS put the click_action into the data Object Did you try to add the key value pair "click_action": "com.adobe.phonegap.push.background.MESSAGING_EVENT" to the data Object?

Hi @ksch10bob Sorry to highlight this closed issue, but we are using SNS also, and I was wondering how your experience was, switching from the old apikey, to the new json method of auth. Was it painless?

@viking2917
Copy link
Author

@sithwarrior

@ksch10bob may have more SNS-specific info. My server side is in PHP and I found this StackOverflow answer worked pretty much as-is for me, in converting to the new API: https://stackoverflow.com/a/75482555. May be helpful.

@ksch10bob
Copy link

Hi @sithwarrior
we did not have any problems at all.

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

3 participants