Firebase Cloud Messaging

von Steve Liedtke

Push-Notifications

Mit einer Push-Nofication übermittelt der App-Betreiber Informationen an den App-Nutzer

Technische Sicht

  • Eine Verbindung wird zu dem Push-Dienst(Anbieter) aufrecht gehalten
  • Darüber sendet der Dienst die Nachrichten an den Client/die App

Vorteile

  • Zeitnahe Informationsübermittlung von Server an Client
  • App muss nicht aktiv (im Vordergrund) sein
  • Batterieschonung
  • Nachricht für abgeschaltetes Gerät wird nach Start geliefert
  • Entlastung des Applikationsservers (weniger Requests durch Polling)

Push-Notification Dienste

  • Apple Push Notification Service (APNS)
  • Amazon Simple Notification Service (SNS)
  • Windows Push Notification Service (WNS)
  • Firebase Cloud Messaging (FCM)

Firebase Cloud Messaging

Eckpunkte

  • Auslieferung an
  • Android
  • iOS
  • Web (JavaScript-Bibliothek)
  • aber auch C++ und Unity
  • Leichtgewichtige Nachrichten (max 4KB Payload)
  • Kostenloser Dienst von Google

GCM mit neuem Namen

Nachrichten an einzelne Geräte

Nachrichten an Gerätegruppen

Nachrichten zu Themen

Push an Server

Verbindungsprotokoll HTTP

  • Senden von Applikationsserver über FCM-Dienst (HTTP-Request) an Client
  • Formate: JSON und Plain Text

Verbindungsprotokoll XMPP

  • Zwischen Applikationsserver und FCM-Dienst sowie Client und FCM-Dienst wird dauerhaft eine TCP-Verbindung aufrecht erhalten
  • Somit können Push-Nachrichten vom Client über FCM-Dienst an Applikationsserver gesendet werden

Unterschied zu GCM

  • Funktionalität komplett gleich
  • Statt Google Cloud Konsole nun in Firebase Konsole
  • Optimierung der Client-Bibliotheken
  • Admin-SDK für Node.js

Migration von GCM zu FCM

  • Auf dem Applikationsserver:
    • Gering, da sich nur der Endpoint geändert hat und ein paar Namings
  • Auf Android:
    • Sorgt die Client-Bibliothek für einige Vereinfachungen, z.B. entfällt Permission im Manifest
  • Auf iOS:
    • Auch einige Vereinfachungen

Nachricht an einzelnes Gerät schicken

Client fordert Registration-Token an

public class MyFirebaseInstanceIDService extends FirebaseInstanceIdService {
						
    @Override
    public void onTokenRefresh() {
        // Get updated InstanceID token.
        String refreshedToken = FirebaseInstanceId.getInstance().getToken();
        
        sendRegistrationToServer(refreshedToken);
    }
}

Applikationsserver sendet Nachricht

POST https://fcm.googleapis.com/fcm/send
Content-Type:application/json
Authorization:key=AIzaSyZ-1u...0GBYzPu7Udno5aA

{ 
    "to" : "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
    "data": {
        "status": "OPEN",
        "time": "15:10"
    }
}

Senden von Daten

  • In der Nachricht kann im Bereich "data" Daten übermittelt werden
  • Diese Übertragung kann für "stille" Benachrichtigungen genutzt werden, z.B. um die App aufzufordern neuen Content nachzuladen
public class MyFirebaseMessagingService extends FirebaseMessagingService {

    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        // Check if message contains a data payload.
        if (remoteMessage.getData().size() > 0) {
            Log.d(TAG, "Message data payload: " + remoteMessage.getData());
        }
    }

Senden von Benachrichtigungen

  • Zeigt Nachrichten als Benachrichtigungen an
  • Im Bereich "notification" können Titel, Text, Icon, Sounds, etc. an den Client übergeben werden
POST https://fcm.googleapis.com/fcm/send
Content-Type:application/json
Authorization:key=AIzaSyZ-1u...0GBYzPu7Udno5aA

{
    "to" : "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
    "notification" : {
        "body" : "FCM is live",
        "title" : "Campus Konferenz",
        "icon" : "myicon"
    }
  }
}
public class MyFirebaseMessagingService extends FirebaseMessagingService {

    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {

        // Check if message contains a notification payload.
        if (remoteMessage.getNotification() != null) {
            Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
        }
    }

Nachricht an Gerätegruppe schicken

Client fordert Registration-Token an

Management der Gerätegruppen

  • Auf Applikationsserver
  • In Android-Client

Anlegen einer Gerätegruppe


POST https://android.googleapis.com/gcm/notification
Content-Type:application/json
Authorization:key=API_KEY
project_id:SENDER_ID

{
   "operation": "create",
   "notification_key_name": "appUser-Chris",
   "registration_ids": ["4", "8", "15", "16", "23", "42"]
}						
						

Applikationsserver sendet Nachricht an Gruppe


https://fcm.googleapis.com/fcm/send
Content-Type:application/json
Authorization:key=AIzaSyZ-1u...0GBYzPu7Udno5aA

{
    "to": "aUniqueKey",
    "data": {
        "hello": "This is a Firebase Cloud Messaging Device Group Message!",
    }
}						
						

Szenarien

  • Datenänderung an alle Geräte des selben Nutzers
  • Ausblenden einer Notification auf anderen Geräten des selben Nutzers

Nachricht an Thema

FirebaseMessaging.getInstance().subscribeToTopic("news");

POST https://fcm.googleapis.com/fcm/send
Content-Type:application/json
Authorization:key=AIzaSyZ-1u...0GBYzPu7Udno5aA
{
  "to": "/topics/news",
  "data": {
    "message": "Trump twittert wieder ...",
   }
}						
						

Nachrichtengruppierung

  • Wenn ein Wert für 'collapse_key' an den FCM-Dienst gegeben wird, dann werden alle vorangegangenen Nachrichten mit dem gleichen collapse_key verworfen.
  • Push-Notifications sind standardmäßig nicht collapsible

Priorität

  • Einer Push-Notification kann eine Priorität mitgegeben werden
    • Normal
    • Hoch
  • Default für Benachrichtigungen: Hoch
  • Default für Daten: Normal

Lebensdauer

  • Einer Push-Notification kann eine Lebensdauer mitgegeben werden
  • Der Wert für 'time_to_live' kann zwischen 0 und 2.419.200 Sekunden liegen
  • Dieser Wert gibt an, wie lange FCM eine Push-Notification maximal aufbewahren soll, wenn die Anwendung nicht erreichbar ist
  • Default: 2.419.200 = 28 Tage

Push zum Server

XMPP ONLY

Client sendet Nachricht


FirebaseMessaging fm = FirebaseMessaging.getInstance();

fm.send(new RemoteMessage.Builder(SENDER_ID + "@gcm.googleapis.com")
    .setMessageId(Integer.toString(msgId.incrementAndGet()))
    .addData("my_message", "Hello App Server")
    .addData("my_action","KNOCK KNOCK")
    .build());						
						

Applikationsserver empfängt Nachricht


<message id="">
  <gcm xmlns="google:mobile:data">
    {
        "category":"de.neusta.campuskonferenz", // to know which app sent it
        "data":
        {
            "my_message":"Hello App Server",
            "my_action":"KNOCK KNOCK"
        },
        "message_id":"m-123",
        "from":"REGID"
    }
  </gcm>
</message>					
						

Nice To Know

Mehrere Applikationsserver

  • Ein Client kann Push-Notifications mehrerer Applikationsserver erhalten
  • Maximal 100

Push-Benachrichtigung mit Daten

  • Eine Push-Notification kann sowohl eine Benachrichtigung ('notification') als auch Daten ('data') enthalten

Geschwindigkeit

  • Durchschnittliche Latenz: 60ms
  • 95% aller Nachrichten werden in weniger als 160ms ausgeliefert

Zuverlässigkeit

  • Google verarbeitet täglich 170 Milliarden Nachrichten mit FCM
  • Keine Garantie das Nachrichten ausgeliefert werden

Vielen Dank für eure Aufmerksamkeit!