B4A Library FirebaseNotifications - Push messages / Firebase Cloud Messaging (FCM)

Status
Not open for further replies.
Edit: FirebaseMessaging should be a Receiver. Not a service.


Clarification: The nice thing about FCM is that your app doesn't need to run in order to receive messages. The FirebaseMessaging receiver will be started by the OS when a new message arrives.
It is not a real issue, but if the user closed your app with a "force close" from the device settings then messages will not arrive, until the app is started again.
On some misbehaving devices, killing the app with a swipe will also cause messages not to arrive, until the app is started again.

Firebase Cloud Messaging service is a layer above Google Cloud Messaging service.
It makes it simple to add support for push messages.

Sending messages is done with a simple HTTP request. It is also possible to send message from the Firebase console, though it is not very useful and is actually more complicated than using the REST api.

1. The first step is to follow the Firebase integration tutorial:
https://www.b4x.com/android/forum/threads/integrating-firebase-services.67692/

Make sure to add the Notifications snippet.
You should also reference FirebaseAnalytics

2. Add a Receiver named FirebaseMessaging to your app (must be this name):
B4X:
Sub Process_Globals
    Private fm As FirebaseMessaging
End Sub

Private Sub Receiver_Receive (FirstTime As Boolean, StartingIntent As Intent)
    If FirstTime Then
        fm.Initialize("fm")
    End If
    fm.HandleIntent(StartingIntent)
End Sub

Public Sub SubscribeToTopics
    fm.SubscribeToTopic("general")
End Sub

Sub fm_MessageArrived (Message As RemoteMessage)
    Log("Message arrived")
    Log($"Message data: ${Message.GetData}"$)
    Dim n2 As Notification
    n2.Initialize2(n2.IMPORTANCE_DEFAULT)
    n2.Icon = "icon"
    n2.SetInfo(Message.GetData.Get("title"), Message.GetData.Get("body"), Main)
    n2.Notify(1)   
End Sub

Sub fm_TokenRefresh (Token As String)
    Log("TokenRefresh: " & Token)
End Sub

fm_MessageArrived will be raised whenever a message is received. In this case we show a notification. You can do whatever you need.

We call SubscribeToTopics from the starter service to make sure that the app will be subscribed when it starts:
B4X:
'Starter service
Sub Process_Globals

End Sub

Sub Service_Create
   CallSubDelayed(FirebaseMessaging, "SubscribeToTopics")
End Sub

Now we can send messages to a "topic" and all the subscribed devices will receive it.

See the code in the attached B4J tool. Note that the API_KEY should be set in the B4J code. It shouldn't be distributed in your app.

API_KEY is the server key from:

SS-2017-04-07_08.10.47.png


A simple non-ui B4J program is attached.

Note that messages sent from Firebase Console will not arrive in some cases. Use the B4J code to test it.
 

Attachments

  • B4J-SendingTool.zip
    1.1 KB · Views: 329
Last edited:

tufanv

Expert
Licensed User
Longtime User
This library requires B4A v6+.

Firebase Cloud Messaging service is a layer above Google Cloud Messaging service.
It makes it simple to add support for push messages. Although it is not clear in their documentation you don't need any additional server.

Sending messages is done with a simple HTTP request. It is also possible to send message from the Firebase console, though it is not very useful and is actually more complicated than using the REST api.

1. The first step is to follow the Firebase integration tutorial:
https://www.b4x.com/android/forum/threads/integrating-firebase-services.67692/

Make sure to add the Notifications snippet.

2. Add a Service named FirebaseMessaging to your app (must be this name):
B4X:
Sub Process_Globals
   Private fm As FirebaseMessaging
End Sub

Sub Service_Create
   fm.Initialize("fm")
End Sub

Public Sub SubscribeToTopics
   fm.SubscribeToTopic("general") 'you can subscribe to more topics
End Sub

Sub Service_Start (StartingIntent As Intent)
   If fm.HandleIntent(StartingIntent) Then Return
End Sub

Sub fm_MessageArrived (Message As RemoteMessage)
   Log("Message arrived")
   Log($"Message data: ${Message.GetData}"$)
   Dim n As Notification
   n.Initialize
   n.Icon = "icon"
   n.SetInfo(Message.GetData.Get("title"), Message.GetData.Get("body"), Main)
   n.Notify(1)
End Sub

Sub Service_Destroy

End Sub

fm_MessageArrived will be raised whenever a message is received. In this case we show a notification. You can do whatever you need.

We call SubscribeToTopics from the starter service to make sure that the app will be subscribed when it starts:
B4X:
'Starter service
Sub Process_Globals

End Sub

Sub Service_Create
   CallSubDelayed(FirebaseMessaging, "SubscribeToTopics")
End Sub

Now we can send messages to a "topic" and all the subscribed devices will receive it.

This is done with this request:
B4X:
Private Sub SendMessage(Topic As String, Title As String, Body As String)
   Dim Job As HttpJob
   Job.Initialize("fcm", Me)
   Dim m As Map = CreateMap("to": $"/topics/${Topic}"$)
   Dim data As Map = CreateMap("title": Title, "body": Body)
   m.Put("data": data)
   Dim jg As JSONGenerator
   jg.Initialize(m)
   Job.PostString("https://fcm.googleapis.com/fcm/send", jg.ToString)
   Job.GetRequest.SetContentType("application/json;charset=UTF-8")
   Job.GetRequest.SetHeader("Authorization", "key=" & API_KEY)
End Sub


Sub JobDone(job As HttpJob)
   Log(job)
   If job.Success Then
     Log(job.GetString)
   End If
   job.Release
End Sub
API_KEY is the server key from:

SS-2016-06-09_12.48.20.png


A simple non-ui B4J program is attached.

We can send the notification dişrectly from firebase console. Why did Erel said that it is complicated ? does it have some weaknesses or what ?
 

aidymp

Well-Known Member
Licensed User
Longtime User
When I send a message from the firebase console it get null, null but from the b4j app it works fine? why is that?

Thanks

Aidy
 

tiziana.tinnirello

Member
Licensed User
Longtime User
How to subscribe more topics ?

executing code above has no effect.

fm.SubscribeToTopic("general") 'you can subscribe to more topics
fm.SubscribeToTopic("another") 'you can subscribe to more topics
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
We can send the notification dişrectly from firebase console. Why did Erel said that it is complicated ?
It is simple to send from Firebase console however there are several edge cases that you need to handle (go over their documentation and you will see) in order to always receive the messages.
I don't find it useful as it is very simple to send messages with the REST API.

How to subscribe more topics ?
executing code above has no effect.
Your code is correct. It should work.
 

aidymp

Well-Known Member
Licensed User
Longtime User
How to subscribe more topics ?

executing code above has no effect.

fm.SubscribeToTopic("general") 'you can subscribe to more topics
fm.SubscribeToTopic("another") 'you can subscribe to more topics

That does work for me! one point i noticed, is if your using an emulator it must have google play services installed or all the code has no effect, although adsense still works! (This may be pretty obvious but took me an hour to realise :)
 

DonManfred

Expert
Licensed User
Longtime User
is there a way to know the delivery datetime with message ID ?
not with google-code.

Write the time into a database when the message arrives and give the value back to a server app which will hold the value then...
 

dragonguy

Active Member
Licensed User
Longtime User
What the different about gcm and fcm? I have many app implement with gcm, is it worth change to fcm?
 

Leni Berry

Active Member
Licensed User
Longtime User
i hv an error around this code below :

Job.GetRequest.SetContentType("application/json;charset=UTF-8")
Job.GetRequest.SetHeader("Authorization", "key=" & API_KEY)

Note:
i already use httputil2 library by B4A v6
 

Attachments

  • error httpjob.png
    error httpjob.png
    57 KB · Views: 316
Last edited:

KMatle

Expert
Licensed User
Longtime User
As far as i know no. Or, let me say, i did not found any info about restrictions.

Only the info that it is totally free (and forever).

About a month I tested one of my Apps using GCM. I must have sent thousands of messages in 8 hours or so :cool: As long as you don't spam Google's servers, everything is ok...

Even if you don't need a server here I strictly recoomend to have some logic between it (like login, check who sends messages, handling devices etc.). If someone catches your api-key (stored inside the app) then you're done :). So send it to your server, check it, route it to the device (with the corresponding php).
 

ricardotm1968

Member
Licensed User
Longtime User
Hi Erel,
i'm starting to develop a new app, i use appcompat library (ver 2.0) , when i try to chenge my GCM to FCM, in the compile send me this error ,

Error.png


if i inactivate the library everthig is fine, is not posible to use both library at the same time?

thanks in advance
 
Status
Not open for further replies.
Top