Udostępnij za pośrednictwem


Powiadomienia zdalne za pomocą usługi Google Cloud Messaging

Ostrzeżenie

Google wycofał GCM od 10 kwietnia 2018 r. Następujące dokumenty i przykładowe projekty mogą nie być już obsługiwane. Interfejsy API serwera GCM i klienta firmy Google zostaną usunięte zaraz po 29 maja 2019 r. Firma Google zaleca migrowanie aplikacji GCM do usługi Firebase Cloud Messaging (FCM). Aby uzyskać więcej informacji na temat wycofywania i migracji usługi GCM, zobacz Google Cloud Messaging — PRZESTARZAŁE.

Aby rozpocząć pracę z powiadomieniami zdalnymi przy użyciu usługi Firebase Cloud Messaging z platformą Xamarin, zobacz Remote Notifications with FCM (Zdalne powiadomienia za pomocą usługi FCM).

Ten przewodnik zawiera szczegółowe wyjaśnienie sposobu używania usługi Google Cloud Messaging do implementowania powiadomień zdalnych (nazywanych również powiadomieniami wypychanym) w aplikacji platformy Xamarin.Android. Opisuje on różne klasy, które należy zaimplementować w celu komunikowania się z usługą Google Cloud Messaging (GCM), wyjaśnia, jak ustawić uprawnienia w manifeście systemu Android w celu uzyskania dostępu do usługi GCM i demonstruje kompleksowe komunikaty za pomocą przykładowego programu testowego.

Omówienie powiadomień usługi GCM

W tym przewodniku utworzymy aplikację platformy Xamarin.Android, która używa usługi Google Cloud Messaging (GCM) do implementowania powiadomień zdalnych (nazywanych również powiadomieniami wypychanym). Zaimplementujemy różne usługi intencji i odbiorników, które używają usługi GCM do obsługi komunikatów zdalnych, i przetestujemy implementację za pomocą programu wiersza polecenia, który symuluje serwer aplikacji.

Przed kontynuowaniem tego przewodnika należy uzyskać niezbędne poświadczenia do korzystania z serwerów GCM firmy Google; ten proces został wyjaśniony w usłudze Google Cloud Messaging. W szczególności będziesz potrzebować klucza interfejsu API i identyfikatora nadawcy do wstawienia do przykładowego kodu przedstawionego w tym przewodniku.

Użyjemy następujących kroków, aby utworzyć aplikację kliencką platformy Xamarin.Android z obsługą usługi GCM:

  1. Zainstaluj dodatkowe pakiety wymagane do komunikacji z serwerami GCM.
  2. Skonfiguruj uprawnienia aplikacji na potrzeby dostępu do serwerów GCM.
  3. Zaimplementuj kod, aby sprawdzić obecność usług Google Play.
  4. Zaimplementuj usługę intencji rejestracji, która jest negocjowana z usługą GCM na potrzeby tokenu rejestracji.
  5. Zaimplementuj usługę odbiornika identyfikatora wystąpienia, która nasłuchuje aktualizacji tokenu rejestracji z usługi GCM.
  6. Zaimplementuj usługę odbiornika GCM, która odbiera komunikaty zdalne z serwera aplikacji za pośrednictwem usługi GCM.

Ta aplikacja będzie używać nowej funkcji GCM znanej jako obsługa komunikatów tematu. W przypadku komunikatów tematu serwer aplikacji wysyła komunikat do tematu, a nie do listy poszczególnych urządzeń. Urządzenia, które subskrybują ten temat, mogą odbierać komunikaty tematu jako powiadomienia wypychane.

Gdy aplikacja kliencka będzie gotowa, zaimplementujemy aplikację C# wiersza polecenia, która wysyła powiadomienie wypychane do aplikacji klienckiej za pośrednictwem usługi GCM.

Przewodnik

Aby rozpocząć, utwórzmy nowe puste rozwiązanie o nazwie RemoteNotifications. Następnie dodajmy nowy projekt systemu Android do tego rozwiązania, który jest oparty na szablonie aplikacji systemu Android. Wywołajmy ten projekt ClientApp. (Jeśli nie znasz tworzenia projektów platformy Xamarin.Android, zobacz Witaj, Android.) Projekt ClientApp będzie zawierać kod aplikacji klienckiej platformy Xamarin.Android, która odbiera powiadomienia zdalne za pośrednictwem usługi GCM.

Dodawanie wymaganych pakietów

Zanim będziemy mogli zaimplementować kod aplikacji klienckiej, musimy zainstalować kilka pakietów, które będą używane do komunikacji z usługą GCM. Ponadto musimy dodać aplikację sklepu Google Play do naszego urządzenia, jeśli nie została jeszcze zainstalowana.

Dodawanie pakietu GCM usług Xamarin Google Play

Aby odbierać komunikaty z usługi Google Cloud Messaging, platforma usług Google Play musi być obecna na urządzeniu. Bez tej struktury aplikacja systemu Android nie może odbierać komunikatów z serwerów GCM. Usługi Google Play działają w tle, gdy urządzenie z systemem Android jest włączone, po cichu nasłuchuje komunikatów z usługi GCM. Po nadejściu tych komunikatów usługi Google Play konwertują komunikaty na intencje, a następnie emitują te intencje do aplikacji zarejestrowanych dla nich.

W programie Visual Studio kliknij prawym przyciskiem myszy pozycję Odwołania Zarządzaj pakietami NuGet ...; w Visual Studio dla komputerów Mac kliknij prawym przyciskiem myszy pozycję Pakiety Dodaj pakiety>....> Wyszukaj usługę Xamarin Google Play — GCM i zainstaluj ten pakiet w projekcie ClientApp:

Installing Google Play Services

Podczas instalowania usług Xamarin Google Play — GCM program Xamarin Google Play Services — baza jest instalowana automatycznie. Jeśli wystąpi błąd, zmień ustawienie Minimum android projektu na wartość docelową inną niż Kompilowanie przy użyciu wersji zestawu SDK i spróbuj zainstalować pakiet NuGet ponownie.

Następnie zmodyfikuj MainActivity.cs i dodaj następujące using instrukcje:

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

Dzięki temu typy w pakiecie GMS usług Google Play są dostępne dla naszego kodu i dodaje funkcje rejestrowania, które będą używane do śledzenia transakcji z usługą GMS.

Sklep Google Play

Aby odbierać komunikaty z usługi GCM, na urządzeniu musi być zainstalowana aplikacja sklepu Google Play. (Za każdym razem, gdy aplikacja Google Play jest zainstalowana na urządzeniu, sklep Google Play jest również zainstalowany, więc prawdopodobnie jest już zainstalowany na urządzeniu testowym). Bez sklepu Google Play aplikacja systemu Android nie może odbierać komunikatów z usługi GCM. Jeśli na urządzeniu nie zainstalowano jeszcze aplikacji ze Sklepu Google Play, odwiedź witrynę internetową Google Play, aby pobrać i zainstalować sklep Google Play .

Alternatywnie można użyć emulatora systemu Android z systemem Android 2.2 lub nowszym zamiast urządzenia testowego (nie trzeba instalować sklepu Google Play w emulatorze systemu Android). Jeśli jednak używasz emulatora, musisz użyć sieci Wi-Fi do nawiązania połączenia z usługą GCM i musisz otworzyć kilka portów w zaporze sieci Wi-Fi, jak wyjaśniono w dalszej części tego przewodnika.

Ustawianie nazwy pakietu

W usłudze Google Cloud Messaging określiliśmy nazwę pakietu dla naszej aplikacji obsługującej usługę GCM (ta nazwa pakietu służy również jako identyfikator aplikacji skojarzony z naszym kluczem interfejsu API i identyfikatorem nadawcy). Otwórzmy właściwości projektu ClientApp i ustawmy nazwę pakietu na ten ciąg. W tym przykładzie ustawiliśmy nazwę pakietu na :com.xamarin.gcmexample

Setting the package name

Należy pamiętać, że aplikacja kliencka nie będzie mogła odebrać tokenu rejestracji z usługi GCM, jeśli ta nazwa pakietu nie jest dokładnie zgodna z nazwą pakietu wprowadzoną w konsoli dewelopera Google.

Dodawanie uprawnień do manifestu systemu Android

Aplikacja systemu Android musi mieć skonfigurowane następujące uprawnienia, zanim będzie mogła odbierać powiadomienia z usługi Google Cloud Messaging:

  • com.google.android.c2dm.permission.RECEIVE – Udziela aplikacji uprawnień do rejestrowania i odbierania wiadomości z usługi Google Cloud Messaging. (Co to znaczy c2dm ? Oznacza to usługę Cloud to Device Messaging, która jest obecnie przestarzałym poprzednikem usługi GCM. Usługa GCM nadal używa c2dm w wielu ciągach uprawnień).

  • android.permission.WAKE_LOCK — (Opcjonalnie) Uniemożliwia uśpienie procesora CPU urządzenia podczas nasłuchiwania komunikatu.

  • android.permission.INTERNET — przyznaje dostęp do Internetu, aby aplikacja kliencka mogła komunikować się z usługą GCM.

  • .permission.C2D_MESSAGE package_name — rejestruje aplikację w systemie Android i żąda uprawnień do wyłącznego odbierania wszystkich komunikatów C2D (chmura do urządzenia). Prefiks package_name jest taki sam jak identyfikator aplikacji.

Ustawimy te uprawnienia w manifeście systemu Android. Edytujmy AndroidManifest.xml i zastąpmy zawartość następującym kodem XML:

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

W powyższym pliku XML zmień YOUR_PACKAGE_NAME na nazwę pakietu dla projektu aplikacji klienckiej. Na przykład com.xamarin.gcmexample.

Sprawdzanie usług Google Play

W tym przewodniku utworzymy aplikację bez kości z pojedynczą TextView aplikacją w interfejsie użytkownika. Ta aplikacja nie wskazuje bezpośrednio interakcji z usługą GCM. Zamiast tego zobaczymy okno danych wyjściowych, aby zobaczyć, jak nasze uzgadnianie aplikacji z usługą GCM i sprawdzimy pasek powiadomień pod kątem nowych powiadomień po ich nadejściu.

Najpierw utwórzmy układ obszaru komunikatów. Edytuj plik Resources.layout.Main.axml i zastąp zawartość następującym kodem XML:

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

Zapisz plik Main.axml i zamknij go.

Po uruchomieniu aplikacji klienckiej chcemy sprawdzić, czy usługi Google Play są dostępne przed podjęciem próby skontaktowania się z usługą GCM. Edytuj MainActivity.cs i zastąp deklarację count zmiennej wystąpienia następującą deklaracją zmiennej wystąpienia:

TextView msgText;

Następnie dodaj następującą metodę do klasy 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;
    }
}

Ten kod sprawdza, czy na urządzeniu zainstalowano pakiet APK usług Google Play. Jeśli nie jest zainstalowany, w obszarze komunikatu zostanie wyświetlony komunikat, który nakazuje użytkownikowi pobranie pakietu APK ze Sklepu Google Play (lub włączenie go w ustawieniach systemowych urządzenia). Ponieważ chcemy uruchomić tę kontrolę po uruchomieniu aplikacji klienckiej OnCreate, dodamy wywołanie tej metody na końcu metody .

Następnie zastąp metodę OnCreate następującym kodem:

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

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

    IsPlayServicesAvailable ();
}

Ten kod sprawdza obecność pakietu APK usług Google Play i zapisuje wynik w obszarze komunikatu.

Całkowicie skompilujmy i uruchomimy aplikację. Powinien zostać wyświetlony ekran podobny do poniższego zrzutu ekranu:

Google Play Services is available

Jeśli nie otrzymasz tego wyniku, sprawdź, czy na urządzeniu zainstalowano pakiet APK usług Google Play i czy pakiet Xamarin Google Play — GCM został dodany do projektu ClientApp zgodnie z wcześniejszym opisem. Jeśli wystąpi błąd kompilacji, spróbuj wyczyścić rozwiązanie i ponownie skompilować projekt.

Następnie napiszemy kod, aby skontaktować się z GCM i odzyskać token rejestracji.

Rejestrowanie w usłudze GCM

Zanim aplikacja będzie mogła odbierać powiadomienia zdalne z serwera aplikacji, musi zarejestrować się w usłudze GCM i uzyskać token rejestracji. Praca rejestrowania aplikacji w usłudze GCM jest obsługiwana przez utworzony przez nas element IntentService . Wykonamy IntentService następujące czynności:

  1. Używa interfejsu API InstanceID do generowania tokenów zabezpieczających, które autoryzowały aplikację kliencą w celu uzyskania dostępu do serwera aplikacji. W zamian otrzymujemy token rejestracji z usługi GCM.

  2. Przekazuje token rejestracji do serwera aplikacji (jeśli jest to wymagane przez serwer aplikacji).

  3. Subskrybuje co najmniej jeden kanał tematów powiadomień.

Po zaimplementowaniu tego elementu IntentServiceprzetestujemy go, aby sprawdzić, czy wrócimy do tokenu rejestracji z usługi GCM.

Dodaj nowy plik o nazwie RegistrationIntentService.cs i zastąp kod szablonu następującym kodem:

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

W powyższym przykładowym kodzie zmień YOUR_SENDER_ID na identyfikator nadawcy projektu aplikacji klienckiej. Aby uzyskać identyfikator nadawcy dla projektu:

  1. Zaloguj się do konsoli Google Cloud Console i wybierz swoją nazwę projektu z menu rozwijanego. W okienku Informacje o projekcie, które jest wyświetlane dla projektu, kliknij pozycję Przejdź do ustawień projektu:

    Selecting XamarinGCM project

  2. Na stronie Ustawienia znajdź numer projektu — jest to identyfikator nadawcy projektu:

    Project number displayed

Chcemy uruchomić naszą RegistrationIntentService aplikację po uruchomieniu aplikacji. Edytuj MainActivity.cs i zmodyfikuj metodę OnCreate , aby nasza RegistrationIntentService metoda została uruchomiona po sprawdzeniu obecności usług Google Play:

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

Teraz przyjrzyjmy się każdej sekcji, RegistrationIntentService aby zrozumieć, jak działa.

Najpierw dodajemy RegistrationIntentService adnotację do następującego atrybutu, aby wskazać, że nasza usługa nie ma być tworzone przez system:

[Service (Exported = false)]

Konstruktor RegistrationIntentService nazywa wątek procesu roboczego RegistrationIntentService , aby ułatwić debugowanie.

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

Podstawowe funkcje metody RegistrationIntentService znajdują się w metodzie OnHandleIntent . Przyjrzyjmy się temu kodowi, aby zobaczyć, jak rejestruje aplikację w usłudze GCM.

Żądanie tokenu rejestracji

OnHandleIntentnajpierw wywołuje metodę InstanceID.GetToken firmy Google, aby zażądać tokenu rejestracji z usługi GCM. Opakowujemy ten kod w obiekcie lock , aby chronić przed możliwością jednoczesnego wystąpienia wielu intencji rejestracji — lock gwarantuje, że te intencje są przetwarzane sekwencyjnie. Jeśli nie uda nam się uzyskać tokenu rejestracji, zgłaszany jest wyjątek i rejestrujemy błąd. Jeśli rejestracja zakończy się pomyślnie, token zostanie ustawiona wartość tokenu rejestracji, który otrzymaliśmy z usługi 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 ...

Przekazywanie tokenu rejestracji do serwera aplikacji

Jeśli otrzymamy token rejestracji (czyli nie zgłoszono wyjątku), wywołamy skojarzenie SendRegistrationToAppServer tokenu rejestracji użytkownika z kontem po stronie serwera (jeśli istnieje) obsługiwanym przez naszą aplikację. Ponieważ ta implementacja zależy od projektu serwera aplikacji, w tym miejscu podano pustą metodę:

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

W niektórych przypadkach serwer aplikacji nie potrzebuje tokenu rejestracji użytkownika; w takim przypadku można pominąć tę metodę. Po wysłaniu tokenu rejestracji do serwera aplikacji należy zachować wartość logiczną, aby wskazać, SendRegistrationToAppServer czy token został wysłany do serwera. Jeśli wartość logiczna jest fałszywa, SendRegistrationToAppServer wysyła token do serwera aplikacji — w przeciwnym razie token został już wysłany do serwera aplikacji w poprzednim wywołaniu.

Subskrybowanie tematu powiadomień

Następnie wywołujemy naszą Subscribe metodę, aby wskazać usłudze GCM, że chcemy zasubskrybować temat powiadomienia. W Subscribesystemie wywołujemy interfejs API GcmPubSub.Subscribe, aby subskrybować naszą aplikację kliencją do wszystkich komunikatów w obszarze /topics/global:

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

Serwer aplikacji musi wysyłać komunikaty powiadomień, aby /topics/global je otrzymywać. Pamiętaj, że nazwa tematu w obszarze /topics może być dowolny, o ile serwer aplikacji i aplikacja kliencka zgadzają się na te nazwy. (W tym miejscu wybraliśmy nazwę global , aby wskazać, że chcemy otrzymywać komunikaty we wszystkich tematach obsługiwanych przez serwer aplikacji).

Implementowanie usługi odbiornika identyfikatora wystąpienia

Tokeny rejestracji są unikatowe i bezpieczne; jednak aplikacja kliencka (lub GCM) może wymagać odświeżenia tokenu rejestracji w przypadku ponownej instalacji aplikacji lub problemu z zabezpieczeniami. Z tego powodu musimy zaimplementować moduł InstanceIdListenerService , który odpowiada na żądania odświeżania tokenu z usługi GCM.

Dodaj nowy plik o nazwie InstanceIdListenerService.cs i zastąp kod szablonu następującym kodem:

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

Dodaj adnotację InstanceIdListenerService przy użyciu następującego atrybutu, aby wskazać, że usługa nie ma być tworzone przez system i że może odbierać żądania odświeżania tokenu rejestracji usługi GCM (nazywanego również identyfikatorem wystąpienia):

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

Metoda OnTokenRefresh w naszej usłudze uruchamia RegistrationIntentService element , aby mógł przechwycić nowy token rejestracji.

Testowanie rejestracji za pomocą usługi GCM

Całkowicie skompilujmy i uruchomimy aplikację. Jeśli pomyślnie otrzymasz token rejestracji z usługi GCM, token rejestracji powinien zostać wyświetlony w oknie danych wyjściowych. Na przykład:

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

Obsługa komunikatów podrzędnych

Kod, który zaimplementowaliśmy do tej pory, to tylko "konfiguracja" kodu; Sprawdza, czy usługi Google Play są zainstalowane i negocjowane z usługą GCM i serwerem aplikacji w celu przygotowania aplikacji klienckiej do odbierania powiadomień zdalnych. Jednak musimy jeszcze zaimplementować kod, który faktycznie odbiera i przetwarza komunikaty powiadomień podrzędnych. W tym celu musimy zaimplementować usługę odbiornika GCM. Ta usługa odbiera komunikaty tematu z serwera aplikacji i lokalnie rozgłasza je jako powiadomienia. Po zaimplementowaniu tej usługi utworzymy program testowy do wysyłania komunikatów do usługi GCM, aby sprawdzić, czy nasza implementacja działa prawidłowo.

Dodawanie ikony powiadomienia

Najpierw dodajmy małą ikonę, która będzie wyświetlana w obszarze powiadomień po uruchomieniu powiadomienia. Możesz skopiować tę ikonę do projektu lub utworzyć własną ikonę niestandardową. Nadamy nazwę plikowi ikony ic_stat_button_click.png i skopiujemy go do folderu Resources/drawable. Pamiętaj, aby użyć opcji Dodaj > istniejący element ... w celu uwzględnienia tego pliku ikony w projekcie.

Implementowanie usługi odbiornika GCM

Dodaj nowy plik o nazwie GcmListenerService.cs i zastąp kod szablonu następującym kodem:

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

Przyjrzyjmy się każdej sekcji, GcmListenerService aby zrozumieć, jak działa.

Najpierw dodajemy GcmListenerService adnotacje z atrybutem, aby wskazać, że ta usługa nie ma być tworzone przez system, i uwzględniamy filtr intencji wskazujący, że odbiera komunikaty GCM:

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

Po GcmListenerService odebraniu komunikatu z usługi GCM wywoływana OnMessageReceived jest metoda . Ta metoda wyodrębnia zawartość komunikatu z przekazanego elementu Bundle, rejestruje zawartość komunikatu (aby można było ją wyświetlić w oknie danych wyjściowych) i wywołuje polecenie SendNotification w celu uruchomienia powiadomienia lokalnego z odebraną zawartością komunikatu:

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

Metoda SendNotification używa Notification.Builder metody do utworzenia powiadomienia, a następnie używa elementu , NotificationManager aby uruchomić powiadomienie. W rzeczywistości spowoduje to przekonwertowanie komunikatu powiadomienia zdalnego na powiadomienie lokalne, które ma być prezentowane użytkownikowi. Aby uzyskać więcej informacji na temat używania poleceń Notification.Builder i NotificationManager, zobacz Powiadomienia lokalne.

Deklarowanie odbiornika w manifeście

Zanim będziemy mogli odbierać komunikaty z usługi GCM, musimy zadeklarować odbiornik GCM w manifeście systemu Android. Edytujmy AndroidManifest.xml i zastąp sekcję <application> następującym kodem XML:

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

W powyższym pliku XML zmień YOUR_PACKAGE_NAME na nazwę pakietu dla projektu aplikacji klienckiej. W naszym przykładzie przewodnika nazwa pakietu to com.xamarin.gcmexample.

Przyjrzyjmy się temu, co robi każde ustawienie w tym pliku XML:

Ustawienie opis
com.google.android.gms.gcm.GcmReceiver Deklaruje, że nasza aplikacja implementuje odbiornik GCM, który przechwytuje i przetwarza przychodzące komunikaty powiadomień wypychanych.
com.google.android.c2dm.permission.SEND Deklaruje, że tylko serwery GCM mogą wysyłać komunikaty bezpośrednio do aplikacji.
com.google.android.c2dm.intent.RECEIVE Filtr intencji filtruje reklamy obsługiwane przez naszą aplikację do emisji komunikatów z usługi GCM.
com.google.android.c2dm.intent.REGISTRATION Filtrowanie intencji reklam, które nasza aplikacja obsługuje nowe intencje rejestracji (czyli zaimplementowaliśmy usługę odbiornika identyfikatora wystąpienia).

Alternatywnie można ozdobić GcmListenerService tymi atrybutami zamiast określać je w formacie XML. Tutaj określamy je w AndroidManifest.xml tak, aby przykłady kodu były łatwiejsze do naśladowania.

Tworzenie nadawcy komunikatów w celu przetestowania aplikacji

Dodajmy projekt aplikacji konsolowej w języku C# do rozwiązania i wywołajmy go MessageSender. Użyjemy tej aplikacji konsolowej do symulowania serwera aplikacji — będzie wysyłać komunikaty powiadomień do aplikacji ClientApp za pośrednictwem usługi GCM.

Dodawanie pakietu Json.NET

W tej aplikacji konsolowej tworzymy ładunek JSON zawierający komunikat powiadomienia, który chcemy wysłać do aplikacji klienckiej. Użyjemy pakietu Json.NET w usłudze MessageSender, aby ułatwić kompilowanie obiektu JSON wymaganego przez usługę GCM. W programie Visual Studio kliknij prawym przyciskiem myszy pozycję Odwołania Zarządzaj pakietami NuGet ...; w Visual Studio dla komputerów Mac kliknij prawym przyciskiem myszy pozycję Pakiety Dodaj pakiety>....>

Wyszukajmy pakiet Json.NET i zainstalujmy go w projekcie:

Installing the Json.NET package

Dodawanie odwołania do pliku System.Net.Http

Musimy również dodać odwołanie, aby System.Net.Http utworzyć wystąpienie HttpClient elementu do wysyłania komunikatu testowego do usługi GCM. W projekcie MessageSender kliknij prawym przyciskiem myszy pozycję Odwołania > Dodaj odwołanie i przewiń w dół do momentu wyświetlenia pozycji System.Net.Http. Umieść znacznik wyboru obok pozycji System.Net.Http i kliknij przycisk OK.

Implementowanie kodu wysyłającego komunikat testowy

W polu MessageSender zmodyfikuj Program.cs i zastąp zawartość następującym kodem:

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

W powyższym kodzie zmień YOUR_API_KEY na klucz interfejsu API dla projektu aplikacji klienckiej.

Ten testowy serwer aplikacji wysyła następujący komunikat w formacie JSON do usługi GCM:

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

Z kolei usługa GCM przekazuje ten komunikat do aplikacji klienckiej. Skompilujmy usługę MessageSender i otwórzmy okno konsoli, w którym można go uruchomić z poziomu wiersza polecenia.

Wypróbuj!

Teraz jesteśmy gotowi do przetestowania naszej aplikacji klienckiej. Jeśli używasz emulatora lub jeśli urządzenie komunikuje się z usługą GCM za pośrednictwem sieci Wi-Fi, musisz otworzyć następujące porty TCP w zaporze dla komunikatów GCM, aby uzyskać dostęp do: 5228, 5229 i 5230.

Uruchom aplikację kliencka i obejrzyj okno danych wyjściowych. Po pomyślnym odebraniu RegistrationIntentService tokenu rejestracji z usługi GCM w oknie danych wyjściowych powinien zostać wyświetlony token z danymi wyjściowymi dziennika podobnymi do następujących:

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

W tym momencie aplikacja kliencka jest gotowa do odbierania komunikatu powiadomienia zdalnego. W wierszu polecenia uruchom program MessageSender.exe , aby wysłać komunikat powiadomienia "Hello, Xamarin" do aplikacji klienckiej. Jeśli nie utworzono jeszcze projektu MessageSender , zrób to teraz.

Aby uruchomić MessageSender.exe w programie Visual Studio, otwórz wiersz polecenia, przejdź do katalogu MessageSender/bin/Debug i uruchom polecenie bezpośrednio:

MessageSender.exe

Aby uruchomić MessageSender.exe w Visual Studio dla komputerów Mac, otwórz sesję terminalu, przejdź do elementu MessageSender/bin/Debuguj katalog i użyj mono do uruchomienia MessageSender.exe

mono MessageSender.exe

Propagacja komunikatu za pośrednictwem usługi GCM i powrót do aplikacji klienckiej może potrwać do minuty. Jeśli komunikat zostanie pomyślnie odebrany, w oknie danych wyjściowych powinny zostać wyświetlone dane wyjściowe podobne do następujących:

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

Ponadto w obszarze powiadomień powinna zostać wyświetlona nowa ikona powiadomienia:

Notification icon appears on device

Po otwarciu paska powiadomień w celu wyświetlenia powiadomień powinno zostać wyświetlone powiadomienie zdalne:

Notification message is displayed

Gratulacje, Twoja aplikacja otrzymała swoje pierwsze powiadomienie zdalne!

Pamiętaj, że komunikaty usługi GCM nie będą już odbierane, jeśli aplikacja zostanie zatrzymana. Aby wznowić powiadomienia po zatrzymaniu wymuszonym, aplikacja musi zostać ręcznie uruchomiona ponownie. Aby uzyskać więcej informacji na temat tych zasad systemu Android, zobacz Uruchamianie kontrolek dla zatrzymanych aplikacji i tego wpisu przepełnienia stosu.

Podsumowanie

Ten przewodnik zawiera szczegółowe instrukcje implementowania powiadomień zdalnych w aplikacji platformy Xamarin.Android. Opisano w nim sposób instalowania dodatkowych pakietów potrzebnych do komunikacji usługi GCM i wyjaśniono, jak skonfigurować uprawnienia aplikacji na potrzeby dostępu do serwerów GCM. Podano przykładowy kod, który ilustruje, jak sprawdzić obecność usług Google Play, jak zaimplementować usługę intencji rejestracji i usługę odbiornika identyfikatora wystąpienia, która negocjuje z usługą GCM na potrzeby tokenu rejestracji oraz jak zaimplementować usługę odbiornika GCM, która odbiera i przetwarza komunikaty powiadomień zdalnych. Na koniec zaimplementowaliśmy program testowy wiersza polecenia do wysyłania powiadomień testowych do aplikacji klienckiej za pośrednictwem usługi GCM.