Notifiche remote con Google Cloud Messaging

Avviso

Google deprecato GCM a partire dal 10 aprile 2018. I documenti e i progetti di esempio seguenti potrebbero non essere più mantenuti. Le API client e server GCM di Google verranno rimosse non appena il 29 maggio 2019. Google consiglia di eseguire la migrazione di app GCM a Firebase Cloud Messaging (FCM). Per altre informazioni sulla deprecazione e la migrazione di GCM, vedere Google Cloud Messaging - DEPRECATO.

Per iniziare a usare le notifiche remote con Firebase Cloud Messaging con Xamarin, vedere Remote Notifications with FCM (Notifiche remote con FCM).

Questa procedura dettagliata fornisce una spiegazione dettagliata di come usare Google Cloud Messaging per implementare notifiche remote (dette anche notifiche push) in un'applicazione Xamarin.Android. Descrive le varie classi che è necessario implementare per comunicare con Google Cloud Messaging (GCM), spiega come impostare le autorizzazioni nel manifesto Android per l'accesso a GCM e illustra la messaggistica end-to-end con un programma di test di esempio.

Panoramica delle notifiche GCM

In questa procedura dettagliata verrà creata un'applicazione Xamarin.Android che usa Google Cloud Messaging (GCM) per implementare le notifiche remote (note anche come notifiche push). Implementeremo i vari servizi intenti e listener che usano GCM per la messaggistica remota e testeremo l'implementazione con un programma da riga di comando che simula un server applicazioni.

Prima di poter procedere con questa procedura dettagliata, è necessario acquisire le credenziali necessarie per usare i server GCM di Google; questo processo è illustrato in Google Cloud Messaging. In particolare, sarà necessaria una chiave API e un ID mittente da inserire nel codice di esempio presentato in questa procedura dettagliata.

Verranno usati i passaggi seguenti per creare un'app client Xamarin.Android abilitata per GCM:

  1. Installare pacchetti aggiuntivi necessari per le comunicazioni con i server GCM.
  2. Configurare le autorizzazioni dell'app per l'accesso ai server GCM.
  3. Implementare il codice per verificare la presenza di Google Play Services.
  4. Implementare un servizio di finalità di registrazione che negozia con GCM per un token di registrazione.
  5. Implementare un servizio listener ID istanza in ascolto degli aggiornamenti del token di registrazione da GCM.
  6. Implementare un servizio listener GCM che riceve messaggi remoti dal server app tramite GCM.

Questa app userà una nuova funzionalità GCM nota come messaggistica degli argomenti. Nella messaggistica dell'argomento il server app invia un messaggio a un argomento, anziché a un elenco di singoli dispositivi. I dispositivi che sottoscrivono tale argomento possono ricevere messaggi di argomento come notifiche push.

Quando l'app client è pronta, verrà implementata un'applicazione C# della riga di comando che invia una notifica push all'app client tramite GCM.

scenario

Per iniziare, creare una nuova soluzione vuota denominata RemoteNotifications. Aggiungere quindi un nuovo progetto Android a questa soluzione basato sul modello App Android. Chiamare questo progetto ClientApp. Se non si ha familiarità con la creazione di progetti Xamarin.Android, vedere Hello, Android.) Il progetto ClientApp conterrà il codice per l'applicazione client Xamarin.Android che riceve notifiche remote tramite GCM.

Aggiungere pacchetti obbligatori

Prima di poter implementare il codice dell'app client, è necessario installare diversi pacchetti che verranno usati per la comunicazione con GCM. Inoltre, è necessario aggiungere l'applicazione Google Play Store al dispositivo, se non è già installata.

Aggiungere il pacchetto GCM di Xamarin Google Play Services

Per ricevere messaggi da Google Cloud Messaging, il framework di Google Play Services deve essere presente nel dispositivo. Senza questo framework, un'applicazione Android non può ricevere messaggi dai server GCM. Google Play Services viene eseguito in background mentre il dispositivo Android è acceso, ascoltando tranquillamente i messaggi da GCM. Quando arrivano questi messaggi, Google Play Services converte i messaggi nelle finalità e quindi trasmette queste finalità alle applicazioni registrate per loro.

In Visual Studio fare clic con il pulsante destro del mouse su Riferimenti > gestisci pacchetti NuGet ...; in Visual Studio per Mac fare clic con il pulsante destro del mouse su Pacchetti Aggiungi pacchetti>.... Cercare Xamarin Google Play Services - GCM e installare questo pacchetto nel progetto ClientApp:

Installing Google Play Services

Quando si installa Xamarin Google Play Services - GCM, Xamarin Google Play Services - Base viene installato automaticamente. Se viene visualizzato un errore, modificare l'impostazione Minimum Android (Android minimo) del progetto impostando come destinazione un valore diverso da Compile using SDK version (Compila usando la versione dell'SDK) e riprovare a installare NuGet.

Modificare quindi MainActivity.cs e aggiungere le istruzioni seguenti using :

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

In questo modo i tipi nel pacchetto GMS di Google Play Services sono disponibili per il codice e aggiungono funzionalità di registrazione che useremo per tenere traccia delle transazioni con GMS.

Google Play Store

Per ricevere messaggi da GCM, è necessario installare l'applicazione Google Play Store nel dispositivo. Ogni volta che viene installata un'applicazione Google Play in un dispositivo, google Play Store viene installato anche, quindi è probabile che sia già installato nel dispositivo di test. Senza Google Play, un'applicazione Android non può ricevere messaggi da GCM. Se non hai ancora installato l'app Google Play Store sul tuo dispositivo, visita il sito Web di Google Play per scaricare e installare Google Play .

In alternativa, è possibile usare un emulatore Android che esegue Android 2.2 o versione successiva anziché un dispositivo di test (non è necessario installare Google Play Store in un emulatore Android). Tuttavia, se usi un emulatore, devi usare Wi-Fi per connettersi a GCM e devi aprire diverse porte nel firewall Wi-Fi, come illustrato più avanti in questa procedura dettagliata.

Impostare il nome del pacchetto

In Google Cloud Messaging è stato specificato un nome di pacchetto per l'app abilitata per GCM (questo nome del pacchetto funge anche da ID applicazione associato alla chiave API e all'ID mittente). Aprire le proprietà per il progetto ClientApp e impostare il nome del pacchetto su questa stringa. In questo esempio il nome del pacchetto viene impostato su com.xamarin.gcmexample:

Setting the package name

Si noti che l'app client non sarà in grado di ricevere un token di registrazione da GCM se questo nome del pacchetto non corrisponde esattamente al nome del pacchetto immesso nella console di Google Developer.

Aggiungere autorizzazioni al manifesto Android

Un'applicazione Android deve disporre delle autorizzazioni seguenti configurate prima di poter ricevere notifiche da Google Cloud Messaging:

  • com.google.android.c2dm.permission.RECEIVE – Concede l'autorizzazione all'app per registrare e ricevere messaggi da Google Cloud Messaging. (Cosa c2dm significa? Questo è l'acronimo di Cloud to Device Messaging, che è il predecessore ora deprecato di GCM. GCM usa c2dm ancora in molte delle stringhe di autorizzazione.

  • android.permission.WAKE_LOCK – (Facoltativo) Impedisce la sospensione della CPU del dispositivo durante l'ascolto di un messaggio.

  • android.permission.INTERNET – Concede l'accesso a Internet in modo che l'app client possa comunicare con GCM.

  • .permission.C2D_MESSAGE package_name: registra l'applicazione con Android e richiede l'autorizzazione per ricevere esclusivamente tutti i messaggi C2D (da cloud a dispositivo). Il prefisso package_name corrisponde all'ID applicazione.

Queste autorizzazioni verranno impostate nel manifesto Android. È possibile modificare AndroidManifest.xml e sostituire il contenuto con il codice XML seguente:

<?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>

Nel codice XML precedente modificare YOUR_PACKAGE_NAME con il nome del pacchetto per il progetto dell'app client. Ad esempio: com.xamarin.gcmexample.

Verificare la presenza di Google Play Services

Per questa procedura dettagliata viene creata un'app bare-bones con un'unica TextView nell'interfaccia utente. Questa app non indica direttamente l'interazione con GCM. Si osserverà invece la finestra di output per vedere come l'handshake dell'app con GCM e si verificherà la presenza di nuove notifiche nella barra delle notifiche man mano che arrivano.

Creare prima di tutto un layout per l'area dei messaggi. Modificare Resources.layout.Main.axml e sostituire il contenuto con il codice XML seguente:

<?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>

Salvare Main.axml e chiuderlo.

All'avvio dell'app client, è necessario verificare che Google Play Services sia disponibile prima di tentare di contattare GCM. Modificare MainActivity.cs e sostituire la dichiarazione della count variabile di istanza con la dichiarazione di variabile di istanza seguente:

TextView msgText;

Aggiungere quindi il metodo seguente alla classe MainActivity :

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;
    }
}

Questo codice controlla il dispositivo per verificare se è installato l'APK di Google Play Services. Se non è installato, viene visualizzato un messaggio nell'area dei messaggi che indica all'utente di scaricare un APK da Google Play Store (o abilitarlo nelle impostazioni di sistema del dispositivo). Poiché si vuole eseguire questo controllo all'avvio dell'app client, si aggiungerà una chiamata a questo metodo alla fine di OnCreate.

Sostituire quindi il OnCreate metodo con il codice seguente:

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

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

    IsPlayServicesAvailable ();
}

Questo codice verifica la presenza dell'APK di Google Play Services e scrive il risultato nell'area dei messaggi.

Ricompilare ed eseguire completamente l'app. Verrà visualizzata una schermata simile alla schermata seguente:

Google Play Services is available

Se non si ottiene questo risultato, verificare che l'APK di Google Play Services sia installato nel dispositivo e che il pacchetto Xamarin Google Play Services - GCM venga aggiunto al progetto ClientApp come illustrato in precedenza. Se viene visualizzato un errore di compilazione, provare a pulire la soluzione e compilare di nuovo il progetto.

Successivamente, si scriverà il codice per contattare GCM e si otterrà un token di registrazione.

Registrarsi con GCM

Prima che l'app possa ricevere notifiche remote dal server app, deve registrarsi con GCM e ottenere un token di registrazione. Il lavoro di registrazione dell'applicazione con GCM viene gestito da un oggetto IntentService creato. La IntentService procedura seguente viene eseguita:

  1. Usa l'API InstanceID per generare token di sicurezza che autorizzano l'app client ad accedere al server app. In cambio, viene restituito un token di registrazione da GCM.

  2. Inoltra il token di registrazione al server app (se il server app lo richiede).

  3. Sottoscrive uno o più canali di argomenti di notifica.

Dopo l'implementazione di , IntentServiceverrà testato per verificare se viene restituito un token di registrazione da GCM.

Aggiungere un nuovo file denominato RegistrationIntentService.cs e sostituire il codice del modello con quanto segue:

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);
        }
    }
}

Nel codice di esempio precedente modificare YOUR_edizione Standard NDER_ID in Numero ID mittente per il progetto dell'app client. Per ottenere l'ID mittente per il progetto:

  1. Accedere a Google Cloud Console e selezionare il nome del progetto dal menu a discesa. Nel riquadro Informazioni progetto visualizzato per il progetto fare clic su Vai alle impostazioni del progetto:

    Selecting XamarinGCM project

  2. Nella pagina Impostazioni individuare il numero di progetto, ovvero l'ID mittente per il progetto:

    Project number displayed

Si vuole avviare l'app all'avvio RegistrationIntentService dell'esecuzione. Modifica MainActivity.cs e modifica il OnCreate metodo in modo che il nostro RegistrationIntentService venga avviato dopo aver verificato la presenza di Google Play Services:

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);
    }
}

Si esaminerà ora ogni sezione di RegistrationIntentService per comprendere il funzionamento.

Prima di tutto, viene annotato RegistrationIntentService con l'attributo seguente per indicare che il servizio non deve essere creata un'istanza dal sistema:

[Service (Exported = false)]

Il RegistrationIntentService costruttore assegna un nome al thread di lavoro RegistrationIntentService per semplificare il debug.

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

La funzionalità di base di RegistrationIntentService risiede nel OnHandleIntent metodo . Esaminiamo questo codice per vedere come registra l'app con GCM.

Richiedere un token di registrazione

OnHandleIntentchiama prima il metodo InstanceID.GetToken di Google per richiedere un token di registrazione da GCM. Questo codice viene eseguito in modo lock da evitare la possibilità che si verifichino più finalità di registrazione contemporaneamente, lock assicurando che queste finalità vengano elaborate in sequenza. Se non si ottiene un token di registrazione, viene generata un'eccezione e viene registrato un errore. Se la registrazione ha esito positivo, token viene impostata sul token di registrazione restituito da GCM:

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 ...

Inoltrare il token di registrazione al server app

Se si ottiene un token di registrazione (ovvero non è stata generata alcuna eccezione), viene chiamato SendRegistrationToAppServer per associare il token di registrazione dell'utente all'account lato server (se presente) gestito dall'applicazione. Poiché questa implementazione dipende dalla progettazione del server app, viene fornito un metodo vuoto qui:

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

In alcuni casi, il server app non necessita del token di registrazione dell'utente; in tal caso, questo metodo può essere omesso. Quando un token di registrazione viene inviato al server app, SendRegistrationToAppServer deve mantenere un valore booleano per indicare se il token è stato inviato al server. Se questo valore booleano è false, SendRegistrationToAppServer invia il token al server app. In caso contrario, il token è già stato inviato al server app in una chiamata precedente.

Sottoscrivere l'argomento di notifica

Successivamente, viene chiamato il Subscribe metodo per indicare a GCM che si vuole sottoscrivere un argomento di notifica. In Subscribeviene chiamato l'API GcmPubSub.Subscribe per sottoscrivere l'app client a tutti i messaggi in /topics/global:

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

Il server app deve inviare messaggi di notifica a /topics/global se devono essere ricevuti. Si noti che il nome dell'argomento in /topics può essere qualsiasi elemento desiderato, purché il server app e l'app client siano entrambi d'accordo su questi nomi. In questo caso è stato scelto il nome global per indicare che si vogliono ricevere messaggi in tutti gli argomenti supportati dal server app.

Implementare un servizio listener ID istanza

I token di registrazione sono univoci e sicuri; Tuttavia, l'app client (o GCM) potrebbe dover aggiornare il token di registrazione in caso di reinstallazione dell'app o di un problema di sicurezza. Per questo motivo, è necessario implementare un oggetto InstanceIdListenerService che risponde alle richieste di aggiornamento dei token da GCM.

Aggiungere un nuovo file denominato InstanceIdListenerService.cs e sostituire il codice del modello con quanto segue:

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);
        }
    }
}

Annotare InstanceIdListenerService con l'attributo seguente per indicare che il servizio non deve essere creata un'istanza dal sistema e che può ricevere richieste di aggiornamento del token di registrazione GCM (detto anche ID istanza):

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

Il OnTokenRefresh metodo nel servizio avvia in RegistrationIntentService modo che possa intercettare il nuovo token di registrazione.

Testare la registrazione con GCM

Ricompilare ed eseguire completamente l'app. Se si riceve correttamente un token di registrazione da GCM, il token di registrazione deve essere visualizzato nella finestra di output. Ad esempio:

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

Gestire i messaggi downstream

Il codice implementato finora è solo codice "set-up" ; verifica se Google Play Services è installato e negozia con GCM e il server app per preparare l'app client per la ricezione di notifiche remote. Tuttavia, è ancora necessario implementare il codice che riceve ed elabora effettivamente i messaggi di notifica downstream. A tale scopo, è necessario implementare un servizio listener GCM. Questo servizio riceve messaggi di argomento dal server app e li trasmette in locale come notifiche. Dopo aver implementato questo servizio, verrà creato un programma di test per inviare messaggi a GCM in modo che sia possibile verificare se l'implementazione funziona correttamente.

Aggiungere un'icona di notifica

Aggiungere prima di tutto un'icona piccola che verrà visualizzata nell'area di notifica all'avvio della notifica. È possibile copiare questa icona nel progetto o creare un'icona personalizzata. Il file icona verrà denominato ic_stat_button_click.png e copiarlo nella cartella Resources/drawable . Ricordarsi di usare Aggiungi > elemento esistente ... per includere questo file icona nel progetto.

Implementare un servizio listener GCM

Aggiungere un nuovo file denominato GcmListenerService.cs e sostituire il codice del modello con il codice seguente:

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());
        }
    }
}

Esaminiamo ogni sezione del nostro GcmListenerService per capire come funziona.

Prima di tutto, viene annotato GcmListenerService con un attributo per indicare che questo servizio non deve essere creata un'istanza dal sistema e viene incluso un filtro finalità per indicare che riceve messaggi GCM:

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

Quando GcmListenerService riceve un messaggio da GCM, viene richiamato il OnMessageReceived metodo . Questo metodo estrae il contenuto del messaggio dal passato Bundle, registra il contenuto del messaggio (in modo da poterlo visualizzare nella finestra di output) e chiama SendNotification per avviare una notifica locale con il contenuto del messaggio ricevuto:

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

Il SendNotification metodo usa Notification.Builder per creare la notifica e quindi usa per NotificationManager avviare la notifica. In effetti, questo converte il messaggio di notifica remota in una notifica locale da presentare all'utente. Per altre informazioni sull'uso Notification.Builder di e NotificationManager, vedere Notifiche locali.

Dichiarare il ricevitore nel manifesto

Prima di poter ricevere messaggi da GCM, è necessario dichiarare il listener GCM nel manifesto Android. Modificare AndroidManifest.xml e sostituire la <application> sezione con il codice XML seguente:

<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>

Nel codice XML precedente modificare YOUR_PACKAGE_NAME con il nome del pacchetto per il progetto dell'app client. Nell'esempio di procedura dettagliata il nome del pacchetto è com.xamarin.gcmexample.

Verranno ora esaminate le operazioni che ogni impostazione in questo codice XML esegue:

Impostazione Descrizione
com.google.android.gms.gcm.GcmReceiver Dichiara che l'app implementa un ricevitore GCM che acquisisce ed elabora i messaggi di notifica push in ingresso.
com.google.android.c2dm.permission.SEND Dichiara che solo i server GCM possono inviare messaggi direttamente all'app.
com.google.android.c2dm.intent.RECEIVE Filtro finalità pubblicità che l'app gestisce i messaggi trasmessi da GCM.
com.google.android.c2dm.intent.REGISTRATION Annunci di filtro finalità che l'app gestisce le nuove finalità di registrazione, ovvero è stato implementato un servizio listener ID istanza.

In alternativa, è possibile decorare GcmListenerService con questi attributi anziché specificarli in XML. In questo caso vengono specificati in AndroidManifest.xml in modo che gli esempi di codice siano più facili da seguire.

Creare un mittente di messaggi per testare l'app

Aggiungere ora un progetto di applicazione console desktop C# alla soluzione e chiamarlo MessageSender. Questa applicazione console verrà usata per simulare un server applicazioni, che invierà messaggi di notifica a ClientApp tramite GCM.

Aggiungere il pacchetto Json.NET

In questa app console si sta creando un payload JSON che contiene il messaggio di notifica che si vuole inviare all'app client. Verrà usato il pacchetto Json.NET in MessageSender per semplificare la compilazione dell'oggetto JSON richiesto da GCM. In Visual Studio fare clic con il pulsante destro del mouse su Riferimenti > gestisci pacchetti NuGet ...; in Visual Studio per Mac fare clic con il pulsante destro del mouse su Pacchetti Aggiungi pacchetti>....

Cercare il pacchetto Json.NET e installarlo nel progetto:

Installing the Json.NET package

Aggiungere un riferimento a System.Net.Http

Sarà anche necessario aggiungere un riferimento a System.Net.Http in modo che sia possibile creare un'istanza HttpClient di per inviare il messaggio di test a GCM. Nel progetto MessageSender fare clic con il pulsante destro del mouse su Riferimenti > Aggiungi riferimento e scorrere verso il basso fino a visualizzare System.Net.Http. Inserire un segno di spunta accanto a System.Net.Http e fare clic su OK.

Implementare il codice che invia un messaggio di test

In MessageSender modificare Program.cs e sostituire il contenuto con il codice seguente:

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);
            }
        }
    }
}

Nel codice precedente modificare YOUR_API_KEY alla chiave API per il progetto dell'app client.

Questo server dell'app di test invia il seguente messaggio in formato JSON a GCM:

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

GCM, a sua volta, inoltra questo messaggio all'app client. Compilare MessageSender e aprire una finestra della console in cui è possibile eseguirla dalla riga di comando.

Prova

A questo momento è possibile testare l'app client. Se si usa un emulatore o se il dispositivo comunica con GCM tramite Wi-Fi, è necessario aprire le porte TCP seguenti sul firewall per ottenere i messaggi GCM: 5228, 5229 e 5230.

Avviare l'app client e controllare la finestra di output. Dopo aver RegistrationIntentService ricevuto correttamente un token di registrazione da GCM, la finestra di output dovrebbe visualizzare il token con output del log simile al seguente:

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

A questo punto l'app client è pronta per ricevere un messaggio di notifica remota. Dalla riga di comando eseguire il programma MessageSender.exe per inviare un messaggio di notifica "Hello, Xamarin" all'app client. Se il progetto MessageSender non è ancora stato compilato, procedere ora.

Per eseguire MessageSender.exe in Visual Studio, aprire un prompt dei comandi, passare alla directory MessageSender/bin/Debug ed eseguire il comando direttamente:

MessageSender.exe

Per eseguire MessageSender.exe in Visual Studio per Mac, aprire una sessione terminale, passare a MessageSender/bin/Debug della directory e usare mono per eseguire MessageSender.exe

mono MessageSender.exe

La propagazione del messaggio tramite GCM e il backup nell'app client potrebbero essere necessari fino a un minuto. Se il messaggio viene ricevuto correttamente, verrà visualizzato un output simile al seguente nella finestra di output:

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

È inoltre necessario notare che nella barra delle notifiche è presente una nuova icona di notifica:

Notification icon appears on device

Quando si apre la barra delle notifiche per visualizzare le notifiche, verrà visualizzata la notifica remota:

Notification message is displayed

Congratulazioni, l'app ha ricevuto la prima notifica remota.

Si noti che i messaggi GCM non verranno più ricevuti se l'app viene arrestata forzatamente. Per riprendere le notifiche dopo un arresto forzato, l'app deve essere riavviata manualmente. Per altre informazioni su questo criterio Android, vedere Avviare i controlli nelle applicazioni arrestate e questo post di overflow dello stack.

Riepilogo

Questa procedura dettagliata illustra in dettaglio i passaggi per l'implementazione di notifiche remote in un'applicazione Xamarin.Android. È stato descritto come installare pacchetti aggiuntivi necessari per le comunicazioni GCM e come configurare le autorizzazioni dell'app per l'accesso ai server GCM. Ha fornito codice di esempio che illustra come verificare la presenza di Google Play Services, come implementare un servizio di ascolto delle finalità di registrazione e un servizio listener ID istanza che negozia con GCM per un token di registrazione e come implementare un servizio listener GCM che riceve ed elabora messaggi di notifica remota. Infine, è stato implementato un programma di test da riga di comando per inviare notifiche di test all'app client tramite GCM.