--

Tuesday, 29 November 2016

Push notification using Firebase Cloud Messaging (FCM)


         Bye, Bye GCM. Yes some features of GCM is already depreciated and now in coming days GCM are going to fully deprecated. A warm welcome to FCM, is a cloud-based messaging service having all features of GCM with some additional features also.

         Google recommending this,  "Firebase is known for being cross platform, so FCM now makes a natural fit in the Firebase suite of features designed for Android, iOS, and mobile web". FCM is completely free and there are no limitations.


 Vital Features 

1. Send notification messages or data messages

          Displayed to your user. Or send data messages and determine completely what happens in your application code. See Message Types

      1.1 Notification Message:

         Notification messages are handled by firebase SDK itself. Typically the notification message contains title, message, icon etc., In order to send the notification message, you need to use notification key in the JSON data. An example of the notification message is given below.

{
    "to": "e1w6hEbZn-8:APA91bEUIb2JewYCIiApsMu5JfI5Ak...",
    "notification": {
        "body": "Cool offers. Get them before expiring!",
        "title": "Flat 80% discount",
        "icon": "appicon"
    }
}

      1.2 Data Message:

           Data messages have to be handled by the android app. You can add this kind of messages if you want to send some additional data along with the notification. But sending these messages through firebase console is not possible. You need to have a server-side logic to send the notification using Firebase API. You need to use data key when sending this message.
An example of data message json is given below.
{
   "to" : "e1w6hEbZn-8:APA91bEUIb2JewYCIiApsMu5JfI5Ak...",
   "data" : {
     "name" : "LG LED TV S15",
     "product_id" : "123",
     "final_price" : "2500"
   }
 }

       1.3 Messages with both notification and data payload:

          A message can also contain both notification and data payload. When these kinds of messages are sent, it will be handled in two scenarios depending upon app state (background / foreground). For these messages, we can use both notification and data keys.
When in the background – Apps receive the notification payload in the notification tray and only handle the data payload when the user taps on the notification.
When in the foreground – App receives a message object with both payloads available.
An example of notification & data payload message will be
{
    "to" : "e1w6hEbZn-8:APA91bEUIb2JewYCIiApsMu5JfI5Ak...",
    "notification": {
        "body": "Cool offers. Get them before expiring!",
        "title": "Flat 80% discount",
        "icon": "appicon"
    },
    "data" : {
     "name" : "LG LED TV S15",
     "product_id" : "123",
     "final_price" : "2500"
   }
}

Receiving messages from multiple senders

 Case Study : The client app is an article aggregator with multiple contributors, and each of them should be able to send a message when they publish a new article. This message might contain a URL so that the client app can download the article.

Solution :
The sender ID is uniquely generated by the sender. The client app produces multiple tokens with different sender ID while registration. The registration token is shared with the corresponding app servers (to complete the FCM registration client/server handshake), and finally they'll be able to send messages to the client app using their own authentication keys up to 100 multiple senders.


2. Versatile message targeting 

          Distribute messages to your client app in any of three ways — to single devices, to groups of devices, or to devices subscribed to topics.

Targeted audienceDescriptionMessage JSON format
Sending to Single UserWhen a single user targeted, the firebase registration id is used to identify the device. The reg id has to be mentioned in 'to' field JSON.{
"to": "e1w6hEbZn-8:APA91bEUIb2Je.......",
"data": {
"message": "To Single user Message!",
}
}
Sending to Multiple UserBy adding multiple registration id in 'to'  field.{
"to": "e1wZn-8:APA9....&&d4ffsdsdfdf....&&ffasd.. ",
"data": {
"message": "Multiple user Message!",
}
}
Topic MessagingTopic messaging is useful when segment of users targeted for messaging. For this all the users has to subscribe to firebase topic.
The request format of topic messaging is given below. In the to filed you need to mention the topic name.
{
"to": "/topics/news",
"data": {
"message": "Cloud Messaging Topic Message!",
}
}

3. Send messages from client apps

          Send acknowledgments, chats, and other messages from devices back to your server over FCM’s reliable and battery-efficient connection channel.

FCM Android Implementation

Step 1:

Create a project in Firebase (http://console.firebase.google.com/). Providing Android Studio application`s package name in Firebase project which connects with App.

Step 2:

Download Config file i.e.  google-services.json file from project settings. Add this file to Android App`s \app folder of the project.

Step 3:

Now open the build.gradle located in project’s home directory and add firebase dependency.
dependencies {
    classpath 'com.android.tools.build:gradle:2.2.0'
    classpath 'com.google.gms:google-services:3.0.0'
    // NOTE: Do not place your application dependencies here; they belong
    // in the individual module build.gradle files
}

 Step 4:

Open app/build.gradle and add firebase messaging dependency. At the very bottom of the file, add apply plugin: ‘com.google.gms.google-services’

 dependencies {
    compile 'com.android.support:appcompat-v7:23.4.0'
    compile 'com.google.firebase:firebase-messaging:10.0.0'

}

apply plugin: 'com.google.gms.google-services'

Step 5:

A service that extends FirebaseInstanceIdService to handle the creation, rotation, and updating of registration tokens. This is required for sending to specific devices or for creating device groups.
 <service

    android:name=".AKCFirebaseInstanceIDService">
    <intent-filter>
        <action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
    </intent-filter>
</service>
Must be added in the manifest.

Step 6:

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


As shown in the screenshot, showing push notification if app is running in background

To receive notifications in foregrounded apps, to receive data payload, to send upstream messages, and so on, you must extend this service.
<service
    android:name=".AKCFirebaseMessagingService">
    <intent-filter>
        <action android:name="com.google.firebase.MESSAGING_EVENT"/>
    </intent-filter>
</service>
 Must be added in the manifest.

Step 7: 

The onTokenRefresh callback fires from AKCFirebaseInstanceIDService.java whenever a new token is generated, so calling getToken in its context ensures that you are accessing a current, available registration token.

@Override
public void onTokenRefresh() {
    super.onTokenRefresh();
    String refreshedToken = FirebaseInstanceId.getInstance().getToken();

    // Saving reg id to shared preferences
    saveRegIdPreference(refreshedToken);
            // Notify UI that registration has completed, so the progress indicator can be hidden.
            try {
        Intent registrationComplete = new Intent();
        registrationComplete.putExtra("token", refreshedToken);
        registrationComplete.setAction(Configuration.REGISTRATION_COMPLETE);
        sendBroadcast(registrationComplete);
    }catch (Exception ex){
        Log.e(TAG,"FCM Exception:"+ex.getLocalizedMessage());
    } }
Broadcast manager broadcasts the reg id to all the activities those are listening.   
 

Step 8: 


The Broadcast receiver responds to the sendBroadcast from onTokenRefresh(). Once FCM is successfully registered. We are ready to `AKC` topic subscription to receive app wide notifications.

 public class AKCFCMReceiver extends BroadcastReceiver{
    private static final String TAG = "FCMAKCReceiver";

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d(TAG,"FCMReceiver onReceive");
        // checking for type intent filter
        if (intent.getAction().equals(Configuration.REGISTRATION_COMPLETE)) {
          
            FirebaseMessaging.getInstance().subscribeToTopic(Configuration.TOPIC_AKC);
            Log.d(TAG,"FCMReceiver : FCM is registered.");
        } else if (intent.getAction().equals(Configuration.PUSH_NOTIFICATION)) {
            // new push notification is received
            String message = intent.getStringExtra("message");
            Log.d(TAG,"FCMReceiver message :"+message);
            Toast.makeText(context, "Push notification: " + message, Toast.LENGTH_LONG).show();
        }
    }
}

 As shown in the screenshot, displaying toast if app is running in foreground.

Step 9:

Subscribing to Topic

When you want to subscribe to any topic, subscribeToTopic() function can be used. 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.

FirebaseMessaging.getInstance().subscribeToTopic('AKC');

Unsubscribing from Topic

Similarly the client can unsubscribe from a topic by calling unsubscribeFromTopic() method.
FirebaseMessaging.getInstance().unsubscribeFromTopic('AKC');
 

Sending Notification Test messages from Firebase console

    
      Firebase gives hand to test push notification from Console itself. By Tapping 'Notification' option at the left side, Compose message window opens. 



Once send a message, it shows Status, Delivery date, Platform, Open rate, and estimated number of devices the messages reached.



I have added FCM functionalities with Authetication project. You can download the full source code from GitHub,

Kindly send your queries in the comment section.

Happy Coding !!!
Cheers...

1 comment: