Discover how to handle push notifications sent from Firebase Cloud Messaging (FCM) for Android and iOS
UPDATE: For anyone who has downloaded the demo prior to May 17th, 2017, there have been 2 changes: A UseSandbox property has been added to TPushClient, that determines whether the registration is for test apps, and activation of the service connection now happens in a separate thread, to account for threading changes in Tokyo.
A few months ago, I started writing some code that was aimed at being the basis for a job for a client (and may still end up that way), and because I also needed to handle push notifications in my own applications.
At first, it was going to use AWS (Amazon Web Services), via their Simple Notification Service (SNS) as a provider because it is a much lower cost solution than for example Kinvey, and other services, plus it supports a whole bunch of messaging services. As I dug deeper into how to connect with AWS and SNS, I saw it becoming fairly complicated, and as I was doing research about it, I stumbled across the fact that Firebase Cloud Messaging (FCM) (which used to be called Google Cloud Messaging), could handle both Android and iOS.
I started working on a solution, however it was pushed down my list of to-do’s, until I came across Jordi Corbilla’s excellent article on how to receive push notifications in Android. As I wanted to also handle receiving them on iOS, I started looking into how to achieve it. I wrote some code to do the process of registering an iOS device token and receive the FCM token back, however again it was shelved due to working on other tasks.
A post from Steven Chesser in the Embarcadero forums prompted me to take another look at it, and I finally came up with a standalone solution that works for both Android and iOS. I had always planned to make this part of the code public, so the code including a demo is at the PushClient project on Github. The demo and code was built with Delphi 10.2 Tokyo, however it should also work with XE8 and 10.1 Seattle.
Here’s a brief overview of how it works:
- TPushClient (in the DW.PushClient unit) is responsible for creating an instance of the appropriate TPushService for the platform (either Android or iOS), and the TServiceConnection, which receives the messages.
- When the device token becomes available, if the platform is iOS, an instance of TRegisterFCM is created, and a request to register the iOS device token is sent asynchronously to FCM. When the FCM token comes back, the OnChange event of the TPushClient is fired, and you know you now have a valid FCM token.
You can send the FCM token to your back end (if you have one) so that you can target specific devices, however you don’t need to do keep track of them if you’re just interested in sending a message to all devices that have your app installed.
You can use the FCM console to send test messages, however you may want to have a “back end” service that does this, especially if you want to target specific devices or groups of devices. I’ll cover this in a later article.
Please read the above mentioned article from Jordi Corbilla about how to set up Firebase Cloud Messaging for your application.
check this
http://blog.rzaripov.kz/2017/02/firebase-android-ios.html
http://blog.rzaripov.kz/2017/02/firebase-android-ios-2.html
I have tried the demo with delphi seattle, it’s run and installed at my android, but the deviceID is blank and the push message is failed sent from fcm. hope you can explain whats is wrong.. thank u
It’s more than likely you need to update the value for “package” in the Version Info of your project options, to match the package name you have in Firebase for your app. I need to update the article to reflect this, as I fell into the same trap 🙂
ups, sorry i forgot to change the package name,, :), now it’s work, but the message was received if the app running. and the deviceID is still missing.. should we have to input some code into android manifest xml to wake up the appl ?
I’m looking into both of these issues, i.e. the DeviceID, and receiving notifications when the app is not running, and plan to publish a follow-up article that addresses them.
ok thanks a lot sir.. very intresting for me to learn about fcm with delphi.. can i ask you one more question, how can i parsing the received fcm message, for example : edit1.text := gcm.notification.title; edit2.text:=gcm.notification.message;
I plan to cover that, too.
ok, i’ll wait your next great article. thanks
I have been using same method for getting DeviceToken on Android and iOS with Berlin. But, now with Tokyo I don’t get any DeviceToken on Android devices. Any idea why? When I run the code in Berlin it still works.
It crashes in line 109 of FMX.PushNotification.Android.pas where it says:
LToken := LGCM.Register(LSenderIds);
EJNIException: ‘java.io.IOException: MAIN_THREAD’
I’ll take a look into it in the next day or so.
I’ve checked in a change to the DW.PushClient unit that should work in both Tokyo and Berlin (tested here OK).
It appears the problem is due to threading changes in Tokyo.
A direct link to the changed unit is here:
https://github.com/DelphiWorlds/PushClient/blob/master/DW.PushClient.pas
Wow, that was quick! And it works, now! Thank you!
Would be good to explicitly mention somewhere that one can not use the code from GitHub right away as-is, because in line 172 of DW.PushClient.pas you have coded the Sandbox parameter to True:
FRegisterFCM.RegisterAPNToken(FBundleID, FServerKey, LDeviceToken, True)
And I was wondering why I always get a InvalidRegistrationToken from FCM when trying to push a message for the Token I correctly received during registration… 🙂
Thanks for the heads up! I’ll update the article..
Hello,
Congratulations by example, very good.
But I tested on Android and worked perfectly but in IOS does not return the Token and no error, do you have any idea what can be?
Thank you
That’s usually due to not having a certificate for APNs associated with the iOS provisioning profile. Please refer to this article on how to do obtain a certificate and profile: https://quickblox.com/developers/How_to_create_APNS_certificates
Thanks for the quick return.
I have adapted your example in my APP the part of certificates and provisioning is already right and the APN key is already registered in Firebase but for some reason can not connect to return the Token.
Image of my firebase screen: http://englishconversation.com.br/firebase.png
Do you have the correct provisioning profile selected in your Delphi project options? That’s the only other thing I can think of.
I have yes, but I’ll do a new test project from the beginning with your example. Then I put the result here.
Thank you very much for your attention.
Great and Amazing Job…. Thank you so much!!!
In android this is ok
In the ios the token appears, when sending a message does not arrive in ios, the send says ok for the 2 messages, it does not arrive in ios, I created the certificates, provider, key fcm ect …
How are you sending the message? (i.e. via Firebase console, or via HURL, as I described in the article, or by some other method) Is it received when the app is running?
And I’m sending it through the console firebird and delphi, both say success, but the message does not arrive!
Closed or open does not arrive that only happens in ios.
I have tried this project on Android, it work well and able to receive notification. However it doesn’t work on IOS, any idea or setting i should do in firebase console?
Messages sent from Firebase console will not work on iOS when the app is in the background or not running. Please use HURL (or similar) as described in the article, and ensure that a “Notification” type message is sent, not “Data”
I’ve tried running a service in delphi to stay in the background but it does not work. Example: if I put it in the form and not in a service it works normally, however I want it to run as a service because I have to process the push messages in the background! Any solution for running a service?
It’s not possible to use the methods outlined in this particular article inside of a service because of an issue with FMX units (which the built-in notifications system uses) and services. I may be possible however, using the methods outlined in this article:
http://blog.delphiworlds.com/2017/05/add-firebase-cloud-messaging-mobile-apps-part-1/
I plan to revisit it to investigate whether it would be possible.
Thank you! It will be very interesting, due to the fact that when the application dies I can not process the push notifications, so if I were running a service it would solve the problem
i am use 10.2.2, and i am download puchclientdemo, sender id ,server key change and running android device, also firebase console make app, send fcm message but android device is not receive notificcation.
hi
I’m using delphi 10.2.2. I tested the PushClient on android and it works fine. On ios, the notifications doesn’t fire… I get the token and the device id without any problem.
I’m sending request from my own application. I made tests on fcm console and i’m getting the same behavior…
Any ideas?
I’ve been attempting to investigate this issue, and I’m coming up against problems myself with iOS. Make sure that the Sandbox property (in TForm1.Create) is set to False, and that you have APNs set up correctly for your app in Firebase Console. Even after I’ve made sure of all that, attempting to send a message causes an “InvalidRegistration” response, and the token changes next time the app is run 🙁