Version 3.3.0 of this plugin added FCM support (which is the successor of GCM).
Although using push messages in your Firebase app is really easy setting it up is not. Traditionally, especially for iOS.
If you didn't choose this feature during installation you can uncomment firebase-messaging
in include.gradle
You will not get the title and body if the notification was received while the application was in the background, but you will get the data payload.
Add the following services in the app/App_Resources/Android/AndroidManifest.xml
to enable advanced FCM messaging:
<manifest ... >
<application ... >
...
<service android:name="org.nativescript.plugins.firebase.MyFirebaseInstanceIDService">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
</intent-filter>
</service>
<service android:name="org.nativescript.plugins.firebase.MyFirebaseMessagingService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT"/>
</intent-filter>
</service>
</application>
</manifest>
If you didn't choose this feature during installation you can run the "post install" script again (see the main readme) to add messaging support.
Open /platforms/ios/yourproject.xcworkspace (!) and go to your project's target and head over to "Capabilities" to switch this on (if it isn't already):
Without this enabled you will receive push messages in the foreground, but NOT in the background / when the app is killed.
The previous step created a the fileplatforms/ios/YourAppName/(Resources/)YourAppName.entitlements
.
Copy that file to app/App_Resources/iOS/
(if it doesn't exist yet, otherwise merge its contents),
so it's not removed when you remove and re-add the iOS platform. The relevant content for background push in that file is:
<key>aps-environment</key>
<string>development</string>
Note that since plugin version 5.1.8 the name of the file can either be
<YourAppName>.entitlements
orapp.entitlements
.YourAppName
is the iOS foldername, see the path above.
Open app/App_Resources/iOS/Info.plist
and add this to the bottom:
<key>UIBackgroundModes</key>
<array>
<string>remote-notification</string>
</array>
Follow this guide to the letter. Once you've done it run tns run ios
and upon starting the app it should prompt you for notification support. That also works on the simulator, but actually receiving (background) notifications is only possible on a real device.
To listen to received notifications while in the foreground or when your app moves from the background to the foreground, add a handler to init
.
Any pending notifications (while your app was not in the foreground) will trigger the onMessageReceivedCallback
handler.
firebase.init({
onMessageReceivedCallback: function(message) {
console.log("Title: " + message.title);
console.log("Body: " + message.body);
// if your server passed a custom property called 'foo', then do this:
console.log("Value of 'foo': " + message.data.foo);
}
});
firebase.init({
onMessageReceivedCallback: (message: Message) => {
console.log(`Title: ${message.title}`);
console.log(`Body: ${message.body}`);
// if your server passed a custom property called 'foo', then do this:
console.log(`Value of 'foo': ${message.data.foo}`);
}
});
You don't have to provide the handler during init
- you can also do it through a dedicated function.
One scenario where you want to do this is if you don't want the "This app wants to send push notifications" popup during init, but delay it until you call this function. Second case is when you want to use Angular's Router
or RouterExtensions
navigate
method inside your handler, otherwise the view just won't update.
firebase.addOnMessageReceivedCallback(
function(message) {
// ..
}
);
If you want to send push messages to individual devices, either from your own backend or the FCM console, you need the push token.
Similarly to the message callback you can either wire this through init
or as a separate function:
firebase.init({
onPushTokenReceivedCallback: function(token) {
console.log("Firebase push token: " + token);
}
});
.. or:
firebase.addOnPushTokenReceivedCallback(
function(token) {
// ..
}
);
Based on the publish/subscribe model, FCM topic messaging allows you to send a message to multiple devices that have opted in to a particular topic. You compose topic messages as needed, and FCM handles routing and delivering the message reliably to the right devices.
Client apps can subscribe to any existing topic, or they can create a new topic. When a client app subscribes to a new topic name (one that does not already exist for your Firebase project), a new topic of that name is created in FCM and any client can subsequently subscribe to it.
firebase.subscribeToTopic("news");
and:
firebase.unsubscribeFromTopic("news");
If - for some reason - you need to manually retrieve the current push registration token of the device, you can do:
firebase.getCurrentPushToken().then((token: string) => {
// may be null if not known yet
console.log("Current push token: " + token);
});
If you want to report an issue regarding notifications not working, PLEASE try these CURL commands first.
curl -X POST --header "Authorization: key=SERVER_KEY" --Header "Content-Type: application/json" https://fcm.googleapis.com/fcm/send -d "{\"notification\":{\"title\": \"My title\", \"text\": \"My text\", \"badge\": \"1\", \"sound\": \"default\"}, \"data\":{\"foo\":\"bar\"}, \"priority\": \"High\", \"to\": \"DEVICE_TOKEN\"}"
- SERVER_KEY: see the image below (make sure to use the 'Legacy' server key).
- DEVICE_TOKEN: the one you got in
addOnPushTokenReceivedCallback
orinit
'sonPushTokenReceivedCallback
.
Note that if you don't want a badge on the app icon, remove the
badge
property or set it to 0. Note that launching the app clears the badge anyway.
curl -X POST --header "Authorization: key=AAAA9SHtZvM:APA91bGoY0H2nS8GlzzypDXSiUkNY3nrti4st4WOUs_w1A0Rttcx31U90YGv-p3U4Oql-vh-FzZzWUUPEwl47uvwhI4tB5yz4wwzrJA2fVqLEKZpDU42AQppYnU2-dsURqkyc9sKcjay2egWbfyNK2b-G2JQCqrLVA" --Header "Content-Type: application/json" https://fcm.googleapis.com/fcm/send -d "{\"notification\":{\"title\": \"My title\", \"text\": \"My text\", \"badge\": \"1\", \"sound\": \"default\"}, \"data\":{\"foo\":\"bar\"}, \"priority\": \"High\", \"to\": \"exbKSYOGbto:APA91bHqFX9EA6SxY7NkVKV3ajea9xYn9_2dPz2jS7DGuymoE3fMDhPZLVbTXxbQ5_tS6nxmjdmfAEACM4_L-egNneXInuvg8JfRjrCVICTa8vnccTBq8cAnIx6cME1FvER9WIDC3dC4\"}"
This results in a payload of:
- App in the foreground:
{"foo":"bar", "gcm.message_id":"0:1522952720644653%3194ccac3194ccac", "foreground":true, "title":"My title", "body":"My text"}
- App in the background:
{"foo":"bar", "gcm.message_id":"0:1522952737879515%3194ccac3194ccac", "title":"My title", "body":"My text", "foreground":false}
Take note of
content_available:true
here
curl -X POST --header "Authorization: key=AAAA9SHtZvM:APA91bGoY0H2nS8GlzzypDXSiUkNY3nrti4st4WOUs_w1A0Rttcx31U90YGv-p3U4Oql-vh-FzZzWUUPEwl47uvwhI4tB5yz4wwzrJA2fVqLEKZpDU42AQppYnU2-dsURqkyc9sKcjay2egWbfyNK2b-G2JQCqrLVA" --Header "Content-Type: application/json" https://fcm.googleapis.com/fcm/send -d "{\"data\":{\"foo\":\"bar\"}, \"priority\": \"High\", \"content_available\":true, \"to\": \"exbKSYOGbto:APA91bHqFX9EA6SxY7NkVKV3ajea9xYn9_2dPz2jS7DGuymoE3fMDhPZLVbTXxbQ5_tS6nxmjdmfAEACM4_L-egNneXInuvg8JfRjrCVICTa8vnccTBq8cAnIx6cME1FvER9WIDC3dC4\"}"
This results in a payload of:
- App in the foreground:
{"gcm.message_id":"0:1522952782882471%3194ccac3194ccac", "foo":"bar", "foreground":true}
- App in the background:
{"gcm.message_id":"0:1522952757954843%3194ccac3194ccac", "foo":"bar", "foreground":false}
Make sure you require
the plugin in app.ts
/ main.ts
/ main.aot.ts
before application.start()
, and do init()
after the app has started (not in app.ts
- not even in a timeout; move it out of app.ts
entirely!).
Make sure to use
require
, notimport
inapp.ts
because TSC will remove the import in case you're not using it.