Remotebenachrichtigungen mit Google Cloud Messaging

Warnung

Google hat GCM ab dem 10. April 2018 als veraltet gekennzeichnet. Die folgenden Dokumente und Beispielprojekte werden möglicherweise nicht mehr verwaltet. Der GCM-Server und die Client-APIs von Google werden bereits am 29. Mai 2019 entfernt. Google empfiehlt die Migration von GCM-Apps zu Firebase Cloud Messaging (FCM). Weitere Informationen zur Einstellung und Migration von GCM finden Sie unter Google Cloud Messaging – VERALTET.

Informationen zu den ersten Schritten mit Remotebenachrichtigungen mit Firebase Cloud Messaging mit Xamarin finden Sie unter Remotebenachrichtigungen mit FCM.

Diese exemplarische Vorgehensweise enthält eine schrittweise Erläuterung der Verwendung von Google Cloud Messaging zum Implementieren von Remotebenachrichtigungen (auch als Pushbenachrichtigungen bezeichnet) in einer Xamarin.Android-Anwendung. Es beschreibt die verschiedenen Klassen, die Sie für die Kommunikation mit Google Cloud Messaging (GCM) implementieren müssen, erläutert, wie Berechtigungen im Android-Manifest für den Zugriff auf GCM festgelegt werden, und es veranschaulicht End-to-End-Messaging mit einem Beispieltestprogramm.

Übersicht über GCM-Benachrichtigungen

In dieser exemplarischen Vorgehensweise erstellen wir eine Xamarin.Android-Anwendung, die Google Cloud Messaging (GCM) verwendet, um Remotebenachrichtigungen (auch als Pushbenachrichtigungen bezeichnet) zu implementieren. Wir implementieren die verschiedenen Absichts- und Listenerdienste, die GCM für Remotemessaging verwenden, und testen die Implementierung mit einem Befehlszeilenprogramm, das einen Anwendungsserver simuliert.

Bevor Sie mit dieser exemplarischen Vorgehensweise fortfahren können, müssen Sie die erforderlichen Anmeldeinformationen für die Verwendung der GCM-Server von Google erwerben. dieser Vorgang wird in Google Cloud Messaging erläutert. Insbesondere benötigen Sie einen API-Schlüssel und eine Absender-ID , um in den in dieser exemplarischen Vorgehensweise dargestellten Beispielcode einzufügen.

Wir führen die folgenden Schritte aus, um eine GCM-fähige Xamarin.Android-Client-App zu erstellen:

  1. Installieren Sie zusätzliche Pakete, die für die Kommunikation mit GCM-Servern erforderlich sind.
  2. Konfigurieren Sie App-Berechtigungen für den Zugriff auf GCM-Server.
  3. Implementieren Sie Code, um das Vorhandensein von Google Play Services zu überprüfen.
  4. Implementieren Sie einen Registrierungsabsichtsdienst, der mit GCM ein Registrierungstoken aushandelt.
  5. Implementieren Sie einen instance ID-Listenerdienst, der auf Registrierungstokenupdates von GCM lauscht.
  6. Implementieren Sie einen GCM-Listenerdienst, der Remotenachrichten vom App-Server über GCM empfängt.

Diese App verwendet ein neues GCM-Feature, das als Themenmessaging bezeichnet wird. Beim Thema-Messaging sendet der App-Server eine Nachricht an ein Thema und nicht an eine Liste einzelner Geräte. Geräte, die dieses Thema abonnieren, können Themennachrichten als Pushbenachrichtigungen empfangen.

Wenn die Client-App bereit ist, implementieren wir eine C#-Befehlszeilenanwendung, die über GCM eine Pushbenachrichtigung an unsere Client-App sendet.

Exemplarische Vorgehensweise

Zunächst erstellen wir eine neue leere Lösung mit dem Namen RemoteNotifications. Als Nächstes fügen wir dieser Projektmappe ein neues Android-Projekt hinzu, das auf der Vorlage Android-App basiert. Nennen wir dieses Projekt ClientApp. (Wenn Sie nicht mit dem Erstellen von Xamarin.Android-Projekten vertraut sind, lesen Sie Hello, Android.) Das ClientApp-Projekt enthält den Code für die Xamarin.Android-Clientanwendung, die Remotebenachrichtigungen über GCM empfängt.

Hinzufügen erforderlicher Pakete

Bevor wir unseren Client-App-Code implementieren können, müssen wir mehrere Pakete installieren, die wir für die Kommunikation mit GCM verwenden. Außerdem müssen wir die Google Play Store-Anwendung zu unserem Gerät hinzufügen, wenn sie noch nicht installiert ist.

Hinzufügen des Xamarin Google Play Services-GCM-Pakets

Um Nachrichten von Google Cloud Messaging zu empfangen, muss das Google Play Services-Framework auf dem Gerät vorhanden sein. Ohne dieses Framework kann eine Android-Anwendung keine Nachrichten von GCM-Servern empfangen. Google Play Services wird im Hintergrund ausgeführt, während das Android-Gerät eingeschaltet ist und leise auf Nachrichten von GCM lauscht. Wenn diese Nachrichten eingehen, wandelt Google Play Services die Nachrichten in Absichten um und sendet diese Absichten dann an Anwendungen, die sich für sie registriert haben.

Klicken Sie in Visual Studio mit der rechten Maustaste auf Verweise > NuGet-Pakete verwalten .... Klicken Sie in Visual Studio für Mac mit der rechten Maustaste auf Pakete > Pakete hinzufügen.... Suchen Sie nach Xamarin Google Play Services – GCM, und installieren Sie dieses Paket im ClientApp-Projekt:

Installieren von Google Play Services

Wenn Sie Xamarin Google Play Services – GCM installieren, wird Xamarin Google Play Services - Base automatisch installiert. Wenn sie einen Fehler erhalten, ändern Sie die Einstellung Minimum Android für das Projekt auf einen anderen Wert als Kompilieren mit SDK-Version , und versuchen Sie die NuGet-Installation erneut.

Bearbeiten Sie als Nächstes MainActivity.cs , und fügen Sie die folgenden using Anweisungen hinzu:

using Android.Gms.Common;
using Android.Util;

Dies macht Typen im GMS-Paket von Google Play Services für unseren Code verfügbar und fügt Protokollierungsfunktionen hinzu, die wir zum Nachverfolgen unserer Transaktionen mit GMS verwenden.

Google Play Store

Um Nachrichten von GCM zu empfangen, muss die Google Play Store-Anwendung auf dem Gerät installiert sein. (Wenn eine Google Play-Anwendung auf einem Gerät installiert ist, wird auch google Play Store installiert, sodass es wahrscheinlich bereits auf Ihrem Testgerät installiert ist.) Ohne Google Play kann eine Android-Anwendung keine Nachrichten von GCM empfangen. Wenn Sie die Google Play Store-App noch nicht auf Ihrem Gerät installiert haben, besuchen Sie die Google Play-Website , um Google Play herunterzuladen und zu installieren.

Alternativ können Sie einen Android-Emulator mit Android 2.2 oder höher anstelle eines Testgeräts verwenden (Sie müssen Google Play Store nicht auf einem Android-Emulator installieren). Wenn Sie jedoch einen Emulator verwenden, müssen Sie Wi-Fi verwenden, um eine Verbindung mit GCM herzustellen, und Sie müssen mehrere Ports in Ihrer Wi-Fi Firewall öffnen, wie weiter unten in dieser exemplarischen Vorgehensweise erläutert.

Festlegen des Paketnamens

In Google Cloud Messaging haben wir einen Paketnamen für unsere GCM-fähige App angegeben (dieser Paketname dient auch als Anwendungs-ID , die unserem API-Schlüssel und der Absender-ID zugeordnet ist). Öffnen Sie nun die Eigenschaften für das ClientApp-Projekt , und legen Sie den Paketnamen auf diese Zeichenfolge fest. In diesem Beispiel legen wir den Paketnamen auf fest com.xamarin.gcmexample:

Festlegen des Paketnamens

Beachten Sie, dass die Client-App kein Registrierungstoken von GCM empfangen kann, wenn dieser Paketname nicht genau mit dem Paketnamen übereinstimmt, den wir in der Google Developer-Konsole eingegeben haben.

Hinzufügen von Berechtigungen zum Android-Manifest

Eine Android-Anwendung muss über die folgenden Berechtigungen konfiguriert sein, damit sie Benachrichtigungen von Google Cloud Messaging empfangen kann:

  • com.google.android.c2dm.permission.RECEIVE – Gewährt unserer App die Berechtigung, Nachrichten von Google Cloud Messaging zu registrieren und zu empfangen. (Was bedeutet c2dm ? Dies steht für Cloud-to-Device-Messaging, der inzwischen veraltete Vorgänger von GCM. GCM verwendet c2dm weiterhin in vielen seiner Berechtigungszeichenfolgen.)

  • android.permission.WAKE_LOCK – (Optional) Verhindert, dass die GERÄTE-CPU in den Ruhezustand wechselt, während sie auf eine Nachricht lauscht.

  • android.permission.INTERNET – Gewährt Internetzugriff, damit die Client-App mit GCM kommunizieren kann.

  • .permission.C2D_MESSAGE package_name – Registriert die Anwendung bei Android und fordert die Berechtigung an, ausschließlich alle C2D-Nachrichten (Cloud-to-Device) zu empfangen. Das package_name Präfix ist identisch mit Ihrer Anwendungs-ID.

Wir legen diese Berechtigungen im Android-Manifest fest. Bearbeiten sie AndroidManifest.xml und ersetzen Sie den Inhalt durch den folgenden XML-Code:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="YOUR_PACKAGE_NAME"
    android:versionCode="1"
    android:versionName="1.0"
    android:installLocation="auto">
    <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="YOUR_PACKAGE_NAME.permission.C2D_MESSAGE" />
    <permission android:name="YOUR_PACKAGE_NAME.permission.C2D_MESSAGE"
                android:protectionLevel="signature" />
    <application android:label="ClientApp" android:icon="@drawable/Icon">
    </application>
</manifest>

Ändern Sie im obigen XML-Code YOUR_PACKAGE_NAME in den Paketnamen für Ihr Client-App-Projekt. Beispiel: com.xamarin.gcmexample.

Überprüfen auf Google Play-Dienste

Für diese exemplarische Vorgehensweise erstellen wir eine Bare-Bones-App mit einem einzelnen TextView in der Benutzeroberfläche. Diese App weist nicht direkt auf die Interaktion mit GCM hin. Stattdessen watch wir das Ausgabefenster, um zu sehen, wie der App-Handshak mit GCM erfolgt, und wir überprüfen die Benachrichtigungsleiste auf neue Benachrichtigungen, sobald sie eingehen.

Zunächst erstellen wir ein Layout für den Nachrichtenbereich. Bearbeiten Sie Resources.layout.Main.axml , und ersetzen Sie den Inhalt durch den folgenden XML-Code:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="10dp">
    <TextView
        android:text=" "
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/msgText"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:padding="10dp" />
</LinearLayout>

Speichern Sie Main.axml , und schließen Sie sie.

Wenn die Client-App gestartet wird, soll überprüft werden, ob Google Play Services verfügbar ist, bevor wir versuchen, GCM zu kontaktieren. Bearbeiten Sie MainActivity.cs, und ersetzen Sie die count instance-Variablendeklaration durch die folgende instance-Variablendeklaration:

TextView msgText;

Fügen Sie als Nächstes die folgende Methode zur MainActivity-Klasse hinzu:

public bool IsPlayServicesAvailable ()
{
    int resultCode = GoogleApiAvailability.Instance.IsGooglePlayServicesAvailable (this);
    if (resultCode != ConnectionResult.Success)
    {
        if (GoogleApiAvailability.Instance.IsUserResolvableError (resultCode))
            msgText.Text = GoogleApiAvailability.Instance.GetErrorString (resultCode);
        else
        {
            msgText.Text = "Sorry, this device is not supported";
            Finish ();
        }
        return false;
    }
    else
    {
        msgText.Text = "Google Play Services is available.";
        return true;
    }
}

Dieser Code überprüft das Gerät, um festzustellen, ob das Google Play Services-APK installiert ist. Wenn es nicht installiert ist, wird im Meldungsbereich eine Meldung angezeigt, die den Benutzer anweist, ein APK aus dem Google Play Store herunterzuladen (oder es in den Systemeinstellungen des Geräts zu aktivieren). Da wir diese Überprüfung beim Starten der Client-App ausführen möchten, fügen wir am Ende von OnCreateeinen Aufruf dieser Methode hinzu.

Ersetzen Sie als Nächstes die OnCreate -Methode durch den folgenden Code:

protected override void OnCreate (Bundle bundle)
{
    base.OnCreate (bundle);

    SetContentView (Resource.Layout.Main);
    msgText = FindViewById<TextView> (Resource.Id.msgText);

    IsPlayServicesAvailable ();
}

Dieser Code überprüft, ob das Google Play Services-APK vorhanden ist, und schreibt das Ergebnis in den Nachrichtenbereich.

Lassen Sie uns die App vollständig neu erstellen und ausführen. Es sollte ein Bildschirm angezeigt werden, der wie im folgenden Screenshot aussieht:

Google Play Services ist verfügbar

Wenn Sie dieses Ergebnis nicht erhalten, überprüfen Sie, ob das Google Play Services-APK auf Ihrem Gerät installiert ist und dass das Xamarin Google Play Services - GCM-Paket Ihrem ClientApp-Projekt wie zuvor erläutert hinzugefügt wird. Wenn sie einen Buildfehler erhalten, versuchen Sie, die Projektmappe zu bereinigen und das Projekt erneut zu erstellen.

Als Nächstes schreiben wir Code, um GCM zu kontaktieren und ein Registrierungstoken zurückzuholen.

Registrieren bei GCM

Bevor die App Remotebenachrichtigungen vom App-Server empfangen kann, muss sie sich bei GCM registrieren und ein Registrierungstoken abrufen. Die Registrierung unserer Anwendung bei GCM erfolgt durch eine IntentService von uns erstellte. Unsere IntentService führt die folgenden Schritte aus:

  1. Verwendet die InstanceID-API , um Sicherheitstoken zu generieren, die unsere Client-App für den Zugriff auf den App-Server autorisieren. Im Gegenzug erhalten wir ein Registrierungstoken von GCM zurück.

  2. Leitet das Registrierungstoken an den App-Server weiter (wenn der App-Server dies erfordert).

  3. Abonnieren Sie mindestens einen Benachrichtigungsthemakanal.

Nachdem wir dies IntentServiceimplementiert haben, testen wir es, um festzustellen, ob wir ein Registrierungstoken von GCM erhalten.

Fügen Sie eine neue Datei namens RegistrationIntentService.cs hinzu, und ersetzen Sie den Vorlagencode durch Folgendes:

using System;
using Android.App;
using Android.Content;
using Android.Util;
using Android.Gms.Gcm;
using Android.Gms.Gcm.Iid;

namespace ClientApp
{
    [Service(Exported = false)]
    class RegistrationIntentService : IntentService
    {
        static object locker = new object();

        public RegistrationIntentService() : base("RegistrationIntentService") { }

        protected override void OnHandleIntent (Intent intent)
        {
            try
            {
                Log.Info ("RegistrationIntentService", "Calling InstanceID.GetToken");
                lock (locker)
                {
                    var instanceID = InstanceID.GetInstance (this);
                    var token = instanceID.GetToken (
                        "YOUR_SENDER_ID", GoogleCloudMessaging.InstanceIdScope, null);

                    Log.Info ("RegistrationIntentService", "GCM Registration Token: " + token);
                    SendRegistrationToAppServer (token);
                    Subscribe (token);
                }
            }
            catch (Exception e)
            {
                Log.Debug("RegistrationIntentService", "Failed to get a registration token");
                return;
            }
        }

        void SendRegistrationToAppServer (string token)
        {
            // Add custom implementation here as needed.
        }

        void Subscribe (string token)
        {
            var pubSub = GcmPubSub.GetInstance(this);
            pubSub.Subscribe(token, "/topics/global", null);
        }
    }
}

Ändern Sie im obigen Beispielcode YOUR_SENDER_ID in die Absender-ID-Nummer für Ihr Client-App-Projekt. So rufen Sie die Absender-ID für Ihr Projekt ab:

  1. Melden Sie sich bei der Google Cloud Console an, und wählen Sie ihren Projektnamen im Pulldownmenü aus. Klicken Sie im Bereich Projektinformationen , der für Ihr Projekt angezeigt wird, auf Zu Projekteinstellungen wechseln:

    Auswählen des XamarinGCM-Projekts

  2. Suchen Sie auf der Seite Einstellungen die Projektnummer – dies ist die Absender-ID für Ihr Projekt:

    Angezeigte Projektnummer

Wir möchten unsere RegistrationIntentService starten, wenn unsere App ausgeführt wird. Bearbeiten Sie MainActivity.cs , und ändern Sie die OnCreate Methode so, dass unsere RegistrationIntentService gestartet wird, nachdem wir die Anwesenheit von Google Play Services überprüft haben:

protected override void OnCreate (Bundle bundle)
{
    base.OnCreate (bundle);

    SetContentView(Resource.Layout.Main);
    msgText = FindViewById<TextView> (Resource.Id.msgText);

    if (IsPlayServicesAvailable ())
    {
        var intent = new Intent (this, typeof (RegistrationIntentService));
        StartService (intent);
    }
}

Sehen wir uns nun jeden Abschnitt von RegistrationIntentService an, um zu verstehen, wie es funktioniert.

Zunächst kommentieren wir unsere RegistrationIntentService mit dem folgenden Attribut, um anzugeben, dass unser Dienst nicht vom System instanziiert werden soll:

[Service (Exported = false)]

Der RegistrationIntentService Konstruktor benennt den Workerthread RegistrationIntentService , um das Debuggen zu vereinfachen.

public RegistrationIntentService() : base ("RegistrationIntentService") { }

Die Kernfunktionalität von RegistrationIntentService befindet sich in der OnHandleIntent -Methode. Sehen Sie sich diesen Code an, um zu sehen, wie unsere App bei GCM registriert wird.

Anfordern eines Registrierungstokens

OnHandleIntent Ruft zuerst die InstanzID.GetToken-Methode von Google auf, um ein Registrierungstoken von GCM anzufordern. Wir umschließen diesen Code in ein lock , um die Möglichkeit zu schützen, dass mehrere Registrierungsabsichten gleichzeitig auftreten – die lock stellt sicher, dass diese Absichten sequenziell verarbeitet werden. Wenn ein Registrierungstoken nicht abgerufen werden kann, wird eine Ausnahme ausgelöst, und wir protokollieren einen Fehler. Wenn die Registrierung erfolgreich ist, wird auf das Registrierungstoken festgelegt, token das wir von GCM erhalten haben:

static object locker = new object ();
...
try
{
    lock (locker)
    {
        var instanceID = InstanceID.GetInstance (this);
        var token = instanceID.GetToken (
            "YOUR_SENDER_ID", GoogleCloudMessaging.InstanceIdScope, null);
        ...
    }
}
catch (Exception e)
{
    Log.Debug ...

Weiterleiten des Registrierungstokens an den App Server

Wenn wir ein Registrierungstoken erhalten (d. h. es wurde keine Ausnahme ausgelöst), rufen wir auf SendRegistrationToAppServer , um das Registrierungstoken des Benutzers dem serverseitigen Konto (falls vorhanden) zuzuordnen, das von unserer Anwendung verwaltet wird. Da diese Implementierung vom Entwurf des App-Servers abhängt, wird hier eine leere Methode bereitgestellt:

void SendRegistrationToAppServer (string token)
{
    // Add custom implementation here as needed.
}

In einigen Fällen benötigt der App-Server nicht das Registrierungstoken des Benutzers. in diesem Fall kann diese Methode weggelassen werden. Wenn ein Registrierungstoken an den App-Server gesendet wird, sollte ein boolescher Wert beibehalten werden, SendRegistrationToAppServer um anzugeben, ob das Token an den Server gesendet wurde. Wenn dieser boolesche Wert false ist, SendRegistrationToAppServer sendet das Token an den App-Server. Andernfalls wurde das Token bereits bei einem vorherigen Aufruf an den App-Server gesendet.

Abonnieren des Benachrichtigungsthemas

Als Nächstes rufen wir unsere Subscribe Methode auf, um GCM mitzuteilen, dass wir ein Benachrichtigungsthema abonnieren möchten. In Subscriberufen wir die GcmPubSub.Subscribe-API auf, um unsere Client-App für alle Nachrichten unter /topics/globalzu abonnieren:

void Subscribe (string token)
{
    var pubSub = GcmPubSub.GetInstance(this);
    pubSub.Subscribe(token, "/topics/global", null);
}

Der App-Server muss Benachrichtigungen an senden, wenn /topics/global sie empfangen werden sollen. Beachten Sie, dass der Themenname unter /topics alles sein kann, was Sie möchten, solange sich der App-Server und die Client-App auf diese Namen einigen. (Hier haben wir den Namen global ausgewählt, um anzugeben, dass wir Nachrichten zu allen Themen empfangen möchten, die vom App-Server unterstützt werden.)

Implementieren eines Instanz-ID-Listenerdiensts

Registrierungstoken sind eindeutig und sicher; Die Client-App (oder GCM) muss das Registrierungstoken jedoch möglicherweise aktualisieren, wenn die App neu oder ein Sicherheitsproblem auftritt. Aus diesem Grund müssen wir ein InstanceIdListenerService implementieren, das auf Tokenaktualisierungsanforderungen von GCM reagiert.

Fügen Sie eine neue Datei namens InstanceIdListenerService.cs hinzu, und ersetzen Sie den Vorlagencode durch Folgendes:

using Android.App;
using Android.Content;
using Android.Gms.Gcm.Iid;

namespace ClientApp
{
    [Service(Exported = false), IntentFilter(new[] { "com.google.android.gms.iid.InstanceID" })]
    class MyInstanceIDListenerService : InstanceIDListenerService
    {
        public override void OnTokenRefresh()
        {
            var intent = new Intent (this, typeof (RegistrationIntentService));
            StartService (intent);
        }
    }
}

Kommentieren Sie InstanceIdListenerService mit dem folgenden Attribut, um anzugeben, dass der Dienst nicht vom System instanziiert werden soll und dass er GCM-Registrierungstoken (auch als instance ID bezeichnet) Aktualisierungsanforderungen empfangen kann:

[Service(Exported = false), IntentFilter(new[] { "com.google.android.gms.iid.InstanceID" })]

Die OnTokenRefresh -Methode in unserem Dienst startet die RegistrationIntentService , sodass das neue Registrierungstoken abgefangen werden kann.

Testen der Registrierung mit GCM

Lassen Sie uns die App vollständig neu erstellen und ausführen. Wenn Sie erfolgreich ein Registrierungstoken von GCM erhalten, sollte das Registrierungstoken im Ausgabefenster angezeigt werden. Beispiel:

D/Mono    ( 1934): Assembly Ref addref ClientApp[0xb4ac2400] -> Xamarin.GooglePlayServices.Gcm[0xb4ac2640]: 2
I/RegistrationIntentService( 1934): Calling InstanceID.GetToken
I/RegistrationIntentService( 1934): GCM Registration Token: f8LdveCvXig:APA91bFIsjUAbP-V8TPQdLR89qQbEJh1SYG38AcCbBUf34z5gSdUc5OsXrgs93YFiGcRSRafPfzkz23lf3-LvYV1CwrFheMjHgwPeFSh12MywnRIhz

Behandeln von Nachgeschalteten Nachrichten

Der Code, den wir bisher implementiert haben, ist nur "Setup"-Code; Es überprüft, ob Google Play Services installiert ist, und verhandelt mit GCM und dem App-Server, um unsere Client-App auf den Empfang von Remotebenachrichtigungen vorzubereiten. Wir müssen jedoch noch Code implementieren, der tatsächlich nachgeschaltete Benachrichtigungsnachrichten empfängt und verarbeitet. Dazu müssen wir einen GCM-Listenerdienst implementieren. Dieser Dienst empfängt Themennachrichten vom App-Server und sendet sie lokal als Benachrichtigungen. Nachdem wir diesen Dienst implementiert haben, erstellen wir ein Testprogramm zum Senden von Nachrichten an GCM, damit wir sehen können, ob unsere Implementierung ordnungsgemäß funktioniert.

Hinzufügen eines Benachrichtigungssymbols

Fügen Sie zunächst ein kleines Symbol hinzu, das im Benachrichtigungsbereich angezeigt wird, wenn unsere Benachrichtigung gestartet wird. Sie können dieses Symbol in Ihr Projekt kopieren oder Ein eigenes benutzerdefiniertes Symbol erstellen. Wir benennen die Symboldatei ic_stat_button_click.png und kopieren sie in den Ordner Resources/Drawable . Denken Sie daran, vorhandenes Element hinzufügen > ... zu verwenden, um diese Symboldatei in Ihr Projekt einzuschließen.

Implementieren eines GCM-Listenerdiensts

Fügen Sie eine neue Datei namens GcmListenerService.cs hinzu, und ersetzen Sie den Vorlagencode durch Folgendes:

using Android.App;
using Android.Content;
using Android.OS;
using Android.Gms.Gcm;
using Android.Util;

namespace ClientApp
{
    [Service (Exported = false), IntentFilter (new [] { "com.google.android.c2dm.intent.RECEIVE" })]
    public class MyGcmListenerService : GcmListenerService
    {
        public override void OnMessageReceived (string from, Bundle data)
        {
            var message = data.GetString ("message");
            Log.Debug ("MyGcmListenerService", "From:    " + from);
            Log.Debug ("MyGcmListenerService", "Message: " + message);
            SendNotification (message);
        }

        void SendNotification (string message)
        {
            var intent = new Intent (this, typeof(MainActivity));
            intent.AddFlags (ActivityFlags.ClearTop);
            var pendingIntent = PendingIntent.GetActivity (this, 0, intent, PendingIntentFlags.OneShot);

            var notificationBuilder = new Notification.Builder(this)
                .SetSmallIcon (Resource.Drawable.ic_stat_ic_notification)
                .SetContentTitle ("GCM Message")
                .SetContentText (message)
                .SetAutoCancel (true)
                .SetContentIntent (pendingIntent);

            var notificationManager = (NotificationManager)GetSystemService(Context.NotificationService);
            notificationManager.Notify (0, notificationBuilder.Build());
        }
    }
}

Sehen wir uns jeden Abschnitt unserer GcmListenerService an, um zu verstehen, wie es funktioniert.

Zunächst kommentieren GcmListenerService wir mit einem Attribut, um anzugeben, dass dieser Dienst nicht vom System instanziiert werden soll, und fügen einen Absichtsfilter ein, um anzugeben, dass er GCM-Nachrichten empfängt:

[Service (Exported = false), IntentFilter (new [] { "com.google.android.c2dm.intent.RECEIVE" })]

Wenn GcmListenerService eine Nachricht von GCM empfangen wird, wird die OnMessageReceived -Methode aufgerufen. Diese Methode extrahiert den Nachrichteninhalt aus dem übergebenen Bundle, protokolliert den Nachrichteninhalt (damit wir ihn im Ausgabefenster anzeigen können) und ruft auf SendNotification , um eine lokale Benachrichtigung mit dem empfangenen Nachrichteninhalt zu starten:

var message = data.GetString ("message");
Log.Debug ("MyGcmListenerService", "From:    " + from);
Log.Debug ("MyGcmListenerService", "Message: " + message);
SendNotification (message);

Die SendNotification -Methode verwendet Notification.Builder , um die Benachrichtigung zu erstellen, und verwendet dann den NotificationManager , um die Benachrichtigung zu starten. Dadurch wird die Remotebenachrichtigung in eine lokale Benachrichtigung konvertiert, die dem Benutzer angezeigt wird. Weitere Informationen zur Verwendung von Notification.Builder und NotificationManagerfinden Sie unter Lokale Benachrichtigungen.

Deklarieren des Empfängers im Manifest

Bevor wir Nachrichten von GCM empfangen können, müssen wir den GCM-Listener im Android-Manifest deklarieren. Bearbeiten Sie AndroidManifest.xml und ersetzen Sie den <application> Abschnitt durch den folgenden XML-Code:

<application android:label="RemoteNotifications" android:icon="@drawable/Icon">
    <receiver android:name="com.google.android.gms.gcm.GcmReceiver"
              android:exported="true"
              android:permission="com.google.android.c2dm.permission.SEND">
        <intent-filter>
            <action android:name="com.google.android.c2dm.intent.RECEIVE" />
            <action android:name="com.google.android.c2dm.intent.REGISTRATION" />
            <category android:name="YOUR_PACKAGE_NAME" />
        </intent-filter>
    </receiver>
</application>

Ändern Sie im obigen XML-Code YOUR_PACKAGE_NAME in den Paketnamen für Ihr Client-App-Projekt. In unserem exemplarischen Beispiel ist com.xamarin.gcmexampleder Paketname .

Sehen wir uns an, was die einzelnen Einstellungen in diesem XML-Code machen:

Einstellung BESCHREIBUNG
com.google.android.gms.gcm.GcmReceiver Deklariert, dass unsere App einen GCM-Empfänger implementiert, der eingehende Pushbenachrichtigungen erfasst und verarbeitet.
com.google.android.c2dm.permission.SEND Deklariert, dass nur GCM-Server Nachrichten direkt an die App senden können.
com.google.android.c2dm.intent.RECEIVE Absichtsfilterwerbung, die von unserer App gesendete Nachrichten von GCM verarbeitet.
com.google.android.c2dm.intent.REGISTRATION Absichtsfilterwerbung, dass unsere App neue Registrierungsabsichten verarbeitet (das heißt, wir haben einen Instanz-ID-Listenerdienst implementiert).

Alternativ können Sie mit diesen Attributen dekorieren, anstatt sie in XML anzugeben. Hier geben wir sie in AndroidManifest.xml an, damit die Codebeispiele GcmListenerService leichter zu befolgen sind.

Erstellen eines Nachrichtensenders zum Testen der App

Fügen Sie der Projektmappe ein C#-Desktopkonsolenanwendungsprojekt hinzu, und nennen Sie es MessageSender. Wir verwenden diese Konsolenanwendung, um einen Anwendungsserver zu simulieren– sie sendet Benachrichtigungsmeldungen über GCM an ClientApp .

Hinzufügen des Json.NET-Pakets

In dieser Konsolen-App erstellen wir eine JSON-Nutzlast, die die Benachrichtigungsnachricht enthält, die wir an die Client-App senden möchten. Wir verwenden das Json.NET-Paket in MessageSender , um die Erstellung des für GCM erforderlichen JSON-Objekts zu vereinfachen. Klicken Sie in Visual Studio mit der rechten Maustaste auf Verweise > NuGet-Pakete verwalten ...; klicken Sie in Visual Studio für Mac mit der rechten Maustaste auf Pakete > Hinzufügen von Paketen....

Suchen Sie nach dem paket Json.NET und installieren Sie es im Projekt:

Installieren des Json.NET-Pakets

Hinzufügen eines Verweises auf System.Net.Http

Wir müssen auch einen Verweis System.Net.Http auf hinzufügen, damit wir eine HttpClient instanziieren können, um unsere Testnachricht an GCM zu senden. Klicken Sie im Projekt MessageSender mit der rechten Maustaste auf Verweise > Verweis hinzufügen , und scrollen Sie nach unten, bis System.Net.Http angezeigt wird. Setzen Sie ein Häkchen neben System.Net.Http , und klicken Sie auf OK.

Implementieren von Code, der eine Testnachricht sendet

Bearbeiten Sie in MessageSenderProgram.cs , und ersetzen Sie den Inhalt durch den folgenden Code:

using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json.Linq;

namespace MessageSender
{
    class MessageSender
    {
        public const string API_KEY = "YOUR_API_KEY";
        public const string MESSAGE = "Hello, Xamarin!";

        static void Main (string[] args)
        {
            var jGcmData = new JObject();
            var jData = new JObject();

            jData.Add ("message", MESSAGE);
            jGcmData.Add ("to", "/topics/global");
            jGcmData.Add ("data", jData);

            var url = new Uri ("https://gcm-http.googleapis.com/gcm/send");
            try
            {
                using (var client = new HttpClient())
                {
                    client.DefaultRequestHeaders.Accept.Add(
                        new MediaTypeWithQualityHeaderValue("application/json"));

                    client.DefaultRequestHeaders.TryAddWithoutValidation (
                        "Authorization", "key=" + API_KEY);

                    Task.WaitAll(client.PostAsync (url,
                        new StringContent(jGcmData.ToString(), Encoding.Default, "application/json"))
                            .ContinueWith(response =>
                            {
                                Console.WriteLine(response);
                                Console.WriteLine("Message sent: check the client device notification tray.");
                            }));
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("Unable to send GCM message:");
                Console.Error.WriteLine(e.StackTrace);
            }
        }
    }
}

Ändern Sie im obigen Code YOUR_API_KEY in den API-Schlüssel für Ihr Client-App-Projekt.

Dieser Test-App-Server sendet die folgende JSON-formatierte Nachricht an GCM:

{
  "to": "/topics/global",
  "data": {
    "message": "Hello, Xamarin!"
  }
}

GCM leitet diese Nachricht wiederum an Ihre Client-App weiter. Lassen Sie uns MessageSender erstellen und ein Konsolenfenster öffnen, in dem wir es über die Befehlszeile ausführen können.

Probieren Sie es aus!

Jetzt können wir unsere Client-App testen. Wenn Sie einen Emulator verwenden oder Ihr Gerät mit GCM über WLAN kommuniziert, müssen Sie die folgenden TCP-Ports an Ihrer Firewall öffnen, damit GCM-Nachrichten durchkommen: 5228, 5229 und 5230.

Starten Sie Ihre Client-App, und watch Sie das Ausgabefenster. Nach dem erfolgreichen RegistrationIntentService Empfang eines Registrierungstokens von GCM sollte das Ausgabefenster das Token mit protokollierender Ausgabe wie folgt anzeigen:

I/RegistrationIntentService(16103): GCM Registration Token: eX9ggabZV1Q:APA91bHjBnQXMUeBOT6JDiLpRt8m2YWtY ...

An diesem Punkt kann die Client-App eine Remotebenachrichtigung empfangen. Führen Sie über die Befehlszeile das programmMessageSender.exe aus, um eine Benachrichtigung "Hello, Xamarin" an die Client-App zu senden. Wenn Sie das MessageSender-Projekt noch nicht erstellt haben, tun Sie dies jetzt.

Um MessageSender.exe unter Visual Studio auszuführen, öffnen Sie eine Eingabeaufforderung, wechseln Sie zum Verzeichnis MessageSender/bin/Debug , und führen Sie den Befehl direkt aus:

MessageSender.exe

Um MessageSender.exe unter Visual Studio für Mac auszuführen, öffnen Sie eine Terminalsitzung, wechseln Sie zu MessageSender/bin/Debuggen des Verzeichnisses, und verwenden Sie Mono, um MessageSender.exe

mono MessageSender.exe

Es kann bis zu einer Minute dauern, bis die Nachricht über GCM weitergegeben und an Ihre Client-App zurückversetzt ist. Wenn die Nachricht erfolgreich empfangen wurde, sollte im Ausgabefenster eine Ausgabe wie folgt angezeigt werden:

D/MyGcmListenerService(16103): From:    /topics/global
D/MyGcmListenerService(16103): Message: Hello, Xamarin!

Darüber hinaus sollten Sie feststellen, dass ein neues Benachrichtigungssymbol in der Benachrichtigungsleiste angezeigt wurde:

Das Benachrichtigungssymbol wird auf dem Gerät angezeigt

Wenn Sie die Benachrichtigungsleiste öffnen, um Benachrichtigungen anzuzeigen, sollte unsere Remotebenachrichtigung angezeigt werden:

Benachrichtigungsmeldung wird angezeigt

Herzlichen Glückwunsch, Ihre App hat ihre erste Remotebenachrichtigung erhalten!

Beachten Sie, dass GCM-Nachrichten nicht mehr empfangen werden, wenn die App erzwungen wird. Um Benachrichtigungen nach einem Erzwingen fortzusetzen, muss die App manuell neu gestartet werden. Weitere Informationen zu dieser Android-Richtlinie finden Sie unter Starten von Steuerelementen für beendete Anwendungen und diesem Stapelüberlaufbeitrag.

Zusammenfassung

In dieser exemplarischen Vorgehensweise wurden die Schritte zum Implementieren von Remotebenachrichtigungen in einer Xamarin.Android-Anwendung beschrieben. Es wurde beschrieben, wie zusätzliche Pakete installiert werden, die für die GCM-Kommunikation erforderlich sind, und es wurde erläutert, wie App-Berechtigungen für den Zugriff auf GCM-Server konfiguriert werden. Es wurden Beispielcode bereitgestellt, der veranschaulicht, wie Sie überprüfen, ob Google Play Services vorhanden sind, wie Sie einen Registrierungsabsichtsdienst und instance ID-Listenerdienst implementieren, der mit GCM ein Registrierungstoken aushandelt, und wie Sie einen GCM-Listenerdienst implementieren, der Remotebenachrichtigungsnachrichten empfängt und verarbeitet. Schließlich haben wir ein Befehlszeilentestprogramm implementiert, um Testbenachrichtigungen über GCM an unsere Client-App zu senden.