Удаленные уведомления с помощью Google Cloud Messaging

Предупреждение

Google не рекомендует GCM с 10 апреля 2018 года. Следующие документы и примеры проектов больше не поддерживаются. Сервер Google и клиентские API будут удалены сразу же после 29 мая 2019 г. Google рекомендует перенести приложения GCM в Firebase Cloud Messaging (FCM). Дополнительные сведения об отмене и миграции GCM см. в разделе Google Cloud Messaging — DEPRECATED.

Чтобы приступить к работе с удаленными уведомлениями с помощью Firebase Cloud Messaging с Xamarin, ознакомьтесь с удаленными уведомлениями с помощью FCM.

В этом пошаговом руководстве показано, как использовать Google Cloud Messaging для реализации удаленных уведомлений (также называемых push-уведомлениями) в приложении Xamarin.Android. В нем описываются различные классы, которые необходимо реализовать для взаимодействия с Google Cloud Messaging (GCM), в нем объясняется, как задать разрешения в манифесте Android для доступа к GCM, и он демонстрирует сквозное обмен сообщениями с примером тестовой программы.

Обзор уведомлений GCM

В этом пошаговом руководстве мы создадим приложение Xamarin.Android, использующее Google Cloud Messaging (GCM) для реализации удаленных уведомлений (также известных как push-уведомления). Мы реализуем различные службы намерений и прослушивателя, которые используют GCM для удаленного обмена сообщениями, и мы протестируем реализацию с помощью программы командной строки, которая имитирует сервер приложений.

Прежде чем продолжить работу с этим пошаговом руководстве, необходимо получить необходимые учетные данные для использования серверов GCM Google; этот процесс описан в Google Cloud Messaging. В частности, вам потребуется ключ API и идентификатор отправителя для вставки в пример кода, представленного в этом пошаговом руководстве.

Для создания клиентского приложения Xamarin.Android с поддержкой GCM выполните следующие действия.

  1. Установите дополнительные пакеты, необходимые для обмена данными с серверами GCM.
  2. Настройте разрешения приложения для доступа к серверам GCM.
  3. Реализуйте код для проверка для присутствия служб Google Play.
  4. Реализуйте службу намерений регистрации, которая ведет переговоры с GCM для маркера регистрации.
  5. Реализуйте службу прослушивателя идентификаторов экземпляра, которая прослушивает обновления маркера регистрации из GCM.
  6. Реализуйте службу прослушивателя GCM, которая получает удаленные сообщения с сервера приложений через GCM.

Это приложение будет использовать новую функцию GCM, известную как обмен сообщениями по темам. В обмене сообщениями в разделе сервер приложений отправляет сообщение в раздел, а не в список отдельных устройств. Устройства, подписывающиеся на этот раздел, могут получать сообщения тем в виде push-уведомлений.

Когда клиентское приложение будет готово, мы реализуем приложение C# командной строки, которое отправляет push-уведомление в клиентское приложение через GCM.

Пошаговое руководство

Для начала создадим пустое решение с именем RemoteNotifications. Затем добавим новый проект Android в это решение, основанное на шаблоне приложения Android. Давайте вызовем этот проект ClientApp. (Если вы не знакомы с созданием проектов Xamarin.Android, см. статью Привет, Android.) Проект ClientApp будет содержать код клиентского приложения Xamarin.Android, получающего удаленные уведомления через GCM.

Добавление обязательных пакетов

Прежде чем реализовать код клиентского приложения, необходимо установить несколько пакетов, которые мы будем использовать для взаимодействия с GCM. Кроме того, мы должны добавить приложение Google Play Store на наше устройство, если оно еще не установлено.

Добавление пакета GCM служб Xamarin Google Play

Чтобы получать сообщения из Google Cloud Messaging, платформа служб Google Play должна присутствовать на устройстве. Без этой платформы приложение Android не может получать сообщения от серверов GCM. Службы Google Play выполняются в фоновом режиме, пока устройство Android работает на устройстве Android, тихо прослушивая сообщения из GCM. При поступлении этих сообщений службы Google Play преобразовывают сообщения в намерения, а затем передают эти намерения приложениям, зарегистрированным для них.

В Visual Studio щелкните правой кнопкой мыши ссылки > на элементы управления пакетами NuGet ...; в Visual Studio для Mac щелкните правой кнопкой мыши пакеты > добавления пакетов.... Выполните поиск служб Xamarin Google Play — GCM и установите этот пакет в проект ClientApp:

Installing Google Play Services

При установке служб Xamarin Google Play — GCM, Xamarin Google Play Services — база автоматически устанавливается. Если вы получите ошибку, измените минимальное значение Android проекта на целевое значение, отличное от компиляции с помощью версии ПАКЕТА SDK, и повторите установку NuGet.

Затем измените MainActivity.cs и добавьте следующие using инструкции:

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

Это делает типы в пакете GMS служб Google Play доступным для нашего кода, и он добавляет функции ведения журнала, которые мы будем использовать для отслеживания наших транзакций с GMS.

Магазин Google Play;

Чтобы получать сообщения от GCM, приложение Google Play Store должно быть установлено на устройстве. (Всякий раз, когда приложение Google Play установлено на устройстве, Google Play Store также устанавливается, поэтому, скорее всего, он уже установлен на тестовом устройстве.) Без Google Play приложение Android не может получать сообщения от GCM. Если на устройстве еще нет приложения Google Play Store, посетите веб-сайт Google Play , чтобы скачать и установить Google Play.

Кроме того, вы можете использовать эмулятор Android под управлением Android 2.2 или более поздней версии вместо тестового устройства (вам не нужно устанавливать Google Play Store в эмуляторе Android). Однако при использовании эмулятора необходимо использовать Wi-Fi для подключения к GCM, и необходимо открыть несколько портов в брандмауэре Wi-Fi, как описано далее в этом пошаговом руководстве.

Задание имени пакета

В Google Cloud Messaging мы указали имя пакета для приложения с поддержкой GCM (это имя пакета также служит идентификатором приложения, связанным с ключом API и идентификатором отправителя). Давайте открываем свойства для проекта ClientApp и задали имя пакета этой строке. В этом примере мы задали имя com.xamarin.gcmexampleпакета следующим образом:

Setting the package name

Обратите внимание, что клиентское приложение не сможет получить маркер регистрации из GCM, если это имя пакета не соответствует имени пакета, введенного в консоль разработчика Google.

Добавление разрешений в манифест Android

Приложение Android должно иметь следующие разрешения, прежде чем он сможет получать уведомления от Google Cloud Messaging:

  • com.google.android.c2dm.permission.RECEIVE — предоставляет приложению разрешение на регистрацию и получение сообщений из Google Cloud Messaging. (Что означает c2dm ? Это означает, что cloud to Device Messaging является устаревшим предшественником GCM. GCM по-прежнему используется c2dm во многих строках разрешений.)

  • android.permission.WAKE_LOCK — (необязательно) Запрещает загрузку ЦП устройства во время прослушивания сообщения.

  • android.permission.INTERNET — предоставляет доступ к Интернету, чтобы клиентское приложение могли взаимодействовать с GCM.

  • .permission.C2D_MESSAGE package_name — регистрирует приложение в Android и запрашивает разрешение исключительно на получение всех сообщений C2D (облако на устройство). Префикс package_name совпадает с идентификатором приложения.

Эти разрешения будут заданы в манифесте Android. Давайте изменим AndroidManifest.xml и замените содержимое следующим 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>

В приведенном выше XML измените YOUR_PACKAGE_NAME на имя пакета для проекта клиентского приложения. Например, com.xamarin.gcmexample.

Проверка использования служб Google Play

В этом пошаговом руководстве мы создадим приложение без костей с одним TextView в пользовательском интерфейсе. Это приложение не указывает непосредственное взаимодействие с GCM. Вместо этого мы рассмотрим окно вывода, чтобы узнать, как приложение трясется с помощью GCM, и мы проверка область уведомлений для новых уведомлений по мере их поступления.

Сначала создадим макет для области сообщений. Измените resources.layout.Main.axml и замените содержимое следующим 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>

Сохраните Main.axml и закройте его.

При запуске клиентского приложения мы хотим убедиться, что службы Google Play доступны, прежде чем пытаться связаться с GCM. Измените MainActivity.cs и замените объявление переменной экземпляра следующим объявлением переменной count экземпляра:

TextView msgText;

Затем добавьте следующий метод в класс 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;
    }
}

Этот код проверка устройство, чтобы узнать, установлен ли APK службы Google Play. Если оно не установлено, в области сообщений отображается сообщение, которое указывает пользователю скачать APK из Google Play Store (или включить его в системных параметрах устройства). Так как мы хотим запустить этот проверка при запуске клиентского приложения, мы добавим вызов этого метода в концеOnCreate.

Затем замените OnCreate метод следующим кодом:

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

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

    IsPlayServicesAvailable ();
}

Этот код проверка для присутствия APK служб Google Play и записывает результат в область сообщения.

Давайте полностью перестроим и запустите приложение. Вы увидите экран, который выглядит следующим образом:

Google Play Services is available

Если вы не получите этот результат, убедитесь, что на устройстве установлен APK службы Google Play и что пакет GCM добавляется в проект ClientApp , как описано ранее. Если возникает ошибка сборки, попробуйте очистить решение и снова создать проект.

Затем мы напишем код, чтобы связаться с GCM и вернуть маркер регистрации.

Регистрация с помощью GCM

Прежде чем приложение сможет получать удаленные уведомления с сервера приложений, он должен зарегистрировать в GCM и вернуть маркер регистрации. Работа по регистрации приложения в GCM обрабатывается созданным приложением IntentService . Мы IntentService выполняем следующие действия.

  1. Использует API InstanceID для создания маркеров безопасности, которые разрешают клиентскому приложению доступ к серверу приложений. В свою очередь, мы возвращаем маркер регистрации из GCM.

  2. Перенаправит маркер регистрации на сервер приложений (если для этого требуется сервер приложений).

  3. Подписывается на один или несколько каналов тем уведомлений.

После реализации этого IntentServiceмы проверим его, чтобы узнать, возвращается ли маркер регистрации из GCM.

Добавьте новый файл с именем RegistrationIntentService.cs и замените код шаблона следующим образом:

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

В приведенном выше примере кода измените YOUR_SENDER_ID на номер идентификатора отправителя для проекта клиентского приложения. Чтобы получить идентификатор отправителя для проекта, выполните следующие действия.

  1. Войдите в Google Cloud Console и выберите имя проекта в раскрывающемся меню. В области сведений о проекте, отображаемой для проекта, нажмите кнопку "Перейти к параметрам проекта":

    Selecting XamarinGCM project

  2. На странице Параметры найдите номер проекта— это идентификатор отправителя для проекта:

    Project number displayed

Мы хотим начать работу RegistrationIntentService приложения. Измените MainActivity.cs и измените OnCreate метод, чтобы мы RegistrationIntentService начали работу после проверка для присутствия служб 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);
    }
}

Теперь рассмотрим каждый раздел RegistrationIntentService , чтобы понять, как это работает.

Во-первых, мы заметим следующий RegistrationIntentService атрибут, чтобы указать, что наша служба не должна создаваться системой:

[Service (Exported = false)]

Конструктор RegistrationIntentService называет рабочий поток RegistrationIntentService , чтобы упростить отладку.

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

Основная функциональность RegistrationIntentService находится в методе OnHandleIntent . Давайте рассмотрим этот код, чтобы узнать, как оно регистрирует наше приложение с помощью GCM.

Запрос маркера регистрации

OnHandleIntent сначала вызывает метод Google InstanceID.GetToken для запроса маркера регистрации из GCM. Мы упаковаем этот код в lock защиту от возможности одновременного выполнения нескольких намерений регистрации— lock гарантирует, что эти намерения обрабатываются последовательно. Если не удается получить маркер регистрации, создается исключение, и мы регистрируем ошибку. Если регистрация выполнена успешно, установите маркер регистрации, token который мы вернулись из 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 ...

Переадресация маркера регистрации на сервер приложений

Если мы получаем маркер регистрации (т. е. исключение не было создано), мы вызываем SendRegistrationToAppServer связывание маркера регистрации пользователя с учетной записью на стороне сервера (если таковые есть), которая поддерживается нашим приложением. Так как эта реализация зависит от структуры сервера приложений, здесь предоставляется пустой метод:

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

В некоторых случаях серверу приложений не нужен маркер регистрации пользователя; В этом случае этот метод может быть опущен. Когда маркер регистрации отправляется на сервер приложений, должен поддерживать логическое значение, SendRegistrationToAppServer чтобы указать, был ли маркер отправлен на сервер. Если логическое значение равно false, SendRegistrationToAppServer отправляет маркер на сервер приложений. В противном случае маркер уже был отправлен на сервер приложений в предыдущем вызове.

Подписка на раздел уведомлений

Затем мы вызовем наш Subscribe метод, чтобы указать GCM, что мы хотим подписаться на раздел уведомлений. В Subscribeэтом случае мы вызываем API GcmPubSub.Subscribe, чтобы подписать наше клиентское приложение на все сообщения в разделе /topics/global:

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

Сервер приложений должен отправлять уведомления, чтобы /topics/global получать их. Обратите внимание, что имя /topics раздела может быть любым нужным, если сервер приложений и клиентское приложение согласны с этими именами. (Здесь мы выбрали имя global , указывающее, что мы хотим получать сообщения по всем темам, поддерживаемым сервером приложений.)

Реализация службы прослушивателя идентификаторов экземпляра

Маркеры регистрации являются уникальными и безопасными; однако клиентское приложение (или GCM) может потребоваться обновить маркер регистрации в случае переустановки приложения или проблемы с безопасностью. По этой причине мы должны реализовать запросы InstanceIdListenerService на обновление маркеров от GCM.

Добавьте новый файл с именем InstanceIdListenerService.cs и замените код шаблона следующим образом:

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

Заметите InstanceIdListenerService с помощью следующего атрибута, чтобы указать, что служба не должна создаваться системой и что она может получать запросы на обновление маркера регистрации GCM (также называемый идентификатором экземпляра):

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

Метод OnTokenRefresh в нашей службе запускается RegistrationIntentService таким образом, чтобы он смог перехватить новый маркер регистрации.

Проверка регистрации с помощью GCM

Давайте полностью перестроим и запустите приложение. Если маркер регистрации успешно получен из GCM, маркер регистрации должен отображаться в окне вывода. Например:

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

Обработка подчиненных сообщений

Код, реализованный до сих пор, является только "настройка" кода; он проверка, чтобы узнать, установлены ли службы Google Play и согласовывается с GCM и сервером приложений, чтобы подготовить клиентское приложение для получения удаленных уведомлений. Однако нам еще предстоит реализовать код, который фактически получает и обрабатывает подчиненные сообщения уведомлений. Для этого необходимо реализовать службу прослушивателя GCM. Эта служба получает сообщения раздела от сервера приложений и локально передает их в виде уведомлений. После реализации этой службы мы создадим тестовую программу для отправки сообщений в GCM, чтобы увидеть, работает ли наша реализация правильно.

Значок добавления уведомления

Сначала добавим небольшой значок, который появится в области уведомлений при запуске уведомления. Этот значок можно скопировать в проект или создать собственный пользовательский значок . Мы назовем файл значка ic_stat_button_click.png и скопируйм его в папку Resources/drawable . Не забудьте использовать добавление > существующего элемента ... для включения этого файла значка в проект.

Реализация службы прослушивателя GCM

Добавьте новый файл с именем GcmListenerService.cs и замените код шаблона следующим образом:

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

Давайте рассмотрим каждый раздел нашей GcmListenerService статьи, чтобы понять, как это работает.

Во-первых, мы заметим GcmListenerService атрибут, чтобы указать, что эта служба не должна быть создана системой, и мы включаем фильтр намерений, чтобы указать, что он получает сообщения GCM:

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

При GcmListenerService получении сообщения от GCM OnMessageReceived вызывается метод. Этот метод извлекает содержимое сообщения из переданного Bundleобъекта, регистрирует содержимое сообщения (чтобы его можно было просмотреть в окне вывода) и вызывается SendNotification для запуска локального уведомления с полученным содержимым сообщения:

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

Метод SendNotification используется Notification.Builder для создания уведомления, а затем использует NotificationManager его для запуска уведомления. Фактически это преобразует сообщение удаленного уведомления в локальное уведомление, которое будет представлено пользователю. Дополнительные сведения об использовании Notification.Builder и NotificationManagerиспользовании см. в разделе "Локальные уведомления".

Объявление получателя в манифесте

Прежде чем получать сообщения из GCM, необходимо объявить прослушиватель GCM в манифесте Android. Давайте изменим AndroidManifest.xml и замените <application> раздел следующим 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>

В приведенном выше XML измените YOUR_PACKAGE_NAME на имя пакета для проекта клиентского приложения. В нашем пошаговом примере имя пакета — com.xamarin.gcmexampleэто .

Давайте рассмотрим, что делает каждый параметр в этом XML-коде:

Параметр Description
com.google.android.gms.gcm.GcmReceiver Объявляет, что наше приложение реализует приемник GCM, который записывает и обрабатывает входящие push-уведомления.
com.google.android.c2dm.permission.SEND Объявляет, что только серверы GCM могут отправлять сообщения непосредственно в приложение.
com.google.android.c2dm.intent.RECEIVE Фильтрация намерений рекламы, которую приложение обрабатывает широковещательные сообщения из GCM.
com.google.android.c2dm.intent.REGISTRATION Фильтрация намерений, которую приложение обрабатывает новые намерения регистрации (т. е. мы реализовали службу прослушивателя идентификаторов экземпляра).

Кроме того, можно декорировать GcmListenerService эти атрибуты, а не указывать их в XML. Здесь мы указываем их в AndroidManifest.xml , чтобы примеры кода были проще следовать.

Создание отправителя сообщения для тестирования приложения

Давайте добавим проект консольного приложения C# в решение и вызовем его MessageSender. Мы будем использовать это консольное приложение для имитации сервера приложений— оно будет отправлять уведомления в ClientApp через GCM.

Добавление пакета Json.NET

В этом консольном приложении мы создадим полезные данные JSON, содержащие уведомление, которое мы хотим отправить в клиентское приложение. Мы будем использовать пакет Json.NET в MessageSender , чтобы упростить сборку объекта JSON, необходимого GCM. В Visual Studio щелкните правой кнопкой мыши ссылки > на элементы управления пакетами NuGet ...; в Visual Studio для Mac щелкните правой кнопкой мыши пакеты > добавления пакетов....

Давайте найдите пакет Json.NET и установите его в проекте:

Installing the Json.NET package

Добавление ссылки на System.Net.Http

Нам также потребуется добавить ссылку System.Net.Http , чтобы создать экземпляр тестового HttpClient сообщения в GCM. В проекте MessageSender щелкните правой кнопкой мыши ссылку>и прокрутите вниз, пока не увидите System.Net.Http. Поместите знак проверка рядом с System.Net.Http и нажмите кнопку "ОК".

Реализация кода, отправляющего тестовое сообщение

В MessageSender измените Program.cs и замените содержимое следующим кодом:

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

В приведенном выше коде измените YOUR_API_KEY на ключ API для проекта клиентского приложения.

Этот тестовый сервер приложений отправляет следующее сообщение в формате JSON в GCM:

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

GCM, в свою очередь, перенаправит это сообщение в клиентское приложение. Давайте создадим MessageSender и откройте окно консоли, где его можно запустить из командной строки.

Попробуйте!

Теперь мы готовы протестировать клиентское приложение. Если вы используете эмулятор или устройство взаимодействует с GCM через Wi-Fi, необходимо открыть следующие TCP-порты в брандмауэре для получения сообщений GCM: 5228, 5229 и 5230.

Запустите клиентское приложение и просмотрите окно вывода. RegistrationIntentService После успешного получения маркера регистрации из GCM в окне вывода должен отобразиться маркер с выходными данными журнала, похожими на следующее:

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

На этом этапе клиентское приложение готово к получению сообщения удаленного уведомления. В командной строке запустите программу MessageSender.exe , чтобы отправить уведомление Hello, Xamarin в клиентское приложение. Если вы еще не создали проект MessageSender , сделайте это сейчас.

Чтобы запустить MessageSender.exe в Visual Studio, откройте командную строку, перейдите в каталог MessageSender/bin/Debug и выполните команду напрямую:

MessageSender.exe

Чтобы запустить MessageSender.exe в Visual Studio для Mac, откройте сеанс терминала, перейдите на MessageSender/bin/Debug каталог и используйте mono для запуска MessageSender.exe

mono MessageSender.exe

Для распространения сообщения через GCM и обратно в клиентское приложение может потребоваться до минуты. Если сообщение получено успешно, в окне вывода должно появиться следующее:

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

Кроме того, следует заметить, что в области уведомлений появился новый значок уведомления:

Notification icon appears on device

При открытии области уведомлений для просмотра уведомлений вы увидите наше удаленное уведомление:

Notification message is displayed

Поздравляем, ваше приложение получило свое первое удаленное уведомление!

Обратите внимание, что сообщения GCM больше не будут получены, если приложение принудительно остановлено. Чтобы возобновить уведомления после принудительной остановки, приложение должно быть перезапущено вручную. Дополнительные сведения об этой политике Android см. в разделе "Запуск элементов управления" для остановленных приложений и после переполнения стека.

Итоги

В этом пошаговом руководстве описаны шаги по реализации удаленных уведомлений в приложении Xamarin.Android. В нем описано, как установить дополнительные пакеты, необходимые для обмена данными GCM, и в нем объясняется, как настроить разрешения приложения для доступа к серверам GCM. В нем приведен пример кода, который иллюстрирует, как проверка для присутствия служб Google Play, как реализовать службу намерения регистрации и службу прослушивателя идентификаторов экземпляров, которая ведет переговоры с GCM для маркера регистрации, а также как реализовать службу прослушивателя GCM, которая получает и обрабатывает сообщения удаленного уведомления. Наконец, мы реализовали программу тестирования командной строки для отправки уведомлений о тестах в клиентское приложение через GCM.