Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding client-side flow of Firebase messaging

I'm trying to dive deep into the client side flow of a FCM message (once the message is received on a Android device).

I understand that Android has some native Firebase system service that initially receives the Firebase message (if device not offline). How is this message delivered to the intended application (using broadcasts, intent?)? How does this native Firebase service know which application to send the message to?

It is mentioned in the docs that the FirebaseMessagingService on the device can receive the Firebase message even when stopped. How does it work in this case?

In an application, one can have a single FirebaseMessagingService but multiple FirebaseApp instances. How do these different FirebaseApp instances for an app factor into message delivery?

I'd appreciate a detailed understanding of the flow, I haven't been able to find any official docs/blogs on this.

like image 632
AbhinavChoudhury Avatar asked Mar 18 '21 21:03

AbhinavChoudhury


1 Answers

for a very general overview of the flow they added not long ago the FCM Architectural Overview maybe you already found it.

Going specifically into Android, let's start by looking into this part of the question: -> "It is mentioned in the docs that the FirebaseMessagingService on the device can receive the Firebase message even when stopped. How does it work in this case?"

With a background service that survives the Activity stop. The "native Firebase system service" is a Service declared inside the firebase SDK Manifest, which gets integrated in your app through Manifest merging.

Your APK file can contain just one AndroidManifest.xml file, but your Android Studio project may contain several—provided by the main source set, build variants, and imported libraries

As you can see the Firebase SDK Manifest registers the service. Note that the intent filter has a very low (-500) priority, 0 is the default value. So when you extend the firebase service with .MyService your service will be called, check "Edit your Manifest" step from the official guide:

A service that extends FirebaseMessagingService. This is required if you want to do any message handling beyond receiving notifications on apps in the background.

If you do not do that your service will never be called and the notification display will be managed by the firebase service.

But how does the service receive the events? The best guess is by some socket or polling mechanism as suggested here, another hint is that firebase periodically closes down the connection to "perform load balancing" as reported in their protocol, the SDK class performing this "polling" is probably TopicSyncTask.

Back to us, your service is "polling" in background, when there is an event to show it creates a notification using the system's NOTIFICATION_SERVICE:

// Register the channel with the system
val notificationManager: NotificationManager =
       getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager

-> "How is this message delivered to the intended application (using broadcasts, intent?)?"

Through an Intent with an intent filter: it is your service that creates a notification to send to the Android OS, adding an intent filter with the specific action com.google.firebase.MESSAGING_EVENT Android OS at this point will look for any Activity or Service that has an intent-filter with a the same action. If you extended the firebase service your service is called by overriding the onMessageReceived as shown in firebase guide.

Does this mean that any app can create an intent triggering your service? No because the firebase SDK Manifest sets the android:exported=false.

-> "How does this native Firebase service know which application to send the message to?"

The service is aware of your application unique package name, and uses it when creating the notification.

-> "How do these different FirebaseApp instances for an app factor into message delivery?"

Not sure if I understood correctly but such task would be addressed through the google-services.json, there is an official guide if you need to access multiple projects in your application.

To summarize the flow would be:

  1. firebase background service polling for events (started by the SDK)
  2. the service creates an intent targeting any activity/service that filters for com.google.firebase.MESSAGING_EVENT
  3. Your service onMessageReceived is called (if you did not extend firebase service, the firebase onMessageReceived will be called)
  4. Your service handles the notification (if you did not extend firebase service, it will call you app since it knows your app package name)
like image 175
dnhyde Avatar answered Nov 09 '22 01:11

dnhyde