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

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

Google устаревшим GCM с 10 апреля 2018 г.Google deprecated GCM as of April 10, 2018. Следующие документы и примеры проектов могут больше не поддерживается.The following docs and sample projects may no longer be maintained. GCM сервер и клиентские API-интерфейсы Google удаляется как можно скорее 29 мая 2019 г.Google's GCM server and client APIs will be removed as soon as May 29, 2019. Google рекомендует перенос приложения GCM для Firebase Cloud Messaging (FCM).Google recommends migrating GCM apps to Firebase Cloud Messaging (FCM). Дополнительные сведения о прекращении GCM и миграции, см. в разделе Google Cloud Messaging — рекомендуется использовать.For more information about GCM deprecation and migration, see Google Cloud Messaging - DEPRECATED.

Чтобы начать работу с удаленных уведомлений, с помощью Firebase Cloud Messaging с помощью Xamarin, см. в разделе удаленные уведомления с помощью FCM.To get started with Remote Notifications using Firebase Cloud Messaging with Xamarin, see Remote Notifications with FCM.

Это пошаговое руководство содержит пошаговое объяснение того, как использовать Google Cloud Messaging для реализации удаленных уведомлений (также называемые Push-уведомления) в приложениях Xamarin.Android. Здесь описываются различные классы, которые необходимо реализовать для обмена данными с Google Cloud Messaging (GCM), также содержатся сведения о задании разрешений в манифесте Android для доступа к службе GCM, а он демонстрирует end-to-end обмена сообщениями с программой тестового примера.This walkthrough provides a step-by-step explanation of how to use Google Cloud Messaging to implement remote notifications (also called push notifications) in a Xamarin.Android application. It describes the various classes that you must implement to communicate with Google Cloud Messaging (GCM), it explains how to set permissions in the Android Manifest for access to GCM, and it demonstrates end-to-end messaging with a sample test program.

Общие сведения о уведомления GCMGCM Notifications Overview

В этом пошаговом руководстве мы создадим приложение Xamarin.Android, которое использует Google Cloud Messaging (GCM) для реализации удаленных уведомлений (также известный как Push-уведомления).In this walkthrough, we'll create a Xamarin.Android application that uses Google Cloud Messaging (GCM) to implement remote notifications (also known as push notifications). Мы реализуем различные службы намерения и прослушиватель, использующие GCM для удаленного обмена сообщениями, и мы протестируем нашей реализации с программой командной строки, которая имитирует сервер приложений.We'll implement the various intent and listener services that use GCM for remote messaging, and we'll test our implementation with a command-line program that simulates an application server.

Прежде чем вы сможете продолжить в этом пошаговом руководстве, необходимо получить необходимые учетные данные, используемые серверы GCM от Google; Этот процесс описан в Google Cloud Messaging.Before you can proceed with this walkthrough, you must acquire the necessary credentials to use Google's GCM servers; this process is explained in Google Cloud Messaging. В частности, необходимо будет ключ API и кода отправителя для вставки в примере код, представленный в этом пошаговом руководстве.In particular, you will need an API Key and a Sender ID to insert into the example code presented in this walkthrough.

Мы будем использовать следующие действия для создания клиентского приложения GCM с поддержкой Xamarin.Android:We'll use the following steps to create a GCM-enabled Xamarin.Android client app:

  1. Установите дополнительные пакеты, необходимые для обмена данными с серверами GCM.Install additional packages required for communications with GCM servers.
  2. Настройка разрешений приложения для доступа к серверам GCM.Configure app permissions for access to GCM servers.
  3. Реализуйте код для проверки на наличие служб Google Play.Implement code to check for the presence of Google Play Services.
  4. Реализуйте службу намерений регистрации, которая согласовывает с GCM для маркера регистрации.Implement a registration intent service that negotiates with GCM for a registration token.
  5. Реализуйте службу прослушивания Идентификаторов экземпляра, который прослушивает изменения токена регистрации из GCM.Implement an instance ID listener service that listens for registration token updates from GCM.
  6. Реализуйте службу прослушивания GCM, получающий удаленных сообщений с сервера приложений через GCM.Implement a GCM listener service that receives remote messages from the app server through GCM.

Это приложение будет использовать новую функцию GCM, известный как обмена сообщениями в разделе.This app will use a new GCM feature known as topic messaging. В разделе обмена сообщениями, сервера приложений отправляет сообщение в раздел, а не список отдельных устройств.In topic messaging, the app server sends a message to a topic, rather than to a list of individual devices. Устройства, которые подписаны на этот раздел может получать сообщения раздела как Push-уведомлений.Devices that subscribe to that topic can receive topic messages as push notifications. Дополнительные сведения об обмене сообщениями через раздел GCM, см. в разделе Google реализации обмена сообщениями разделе.For more information about GCM topic messaging, see Google's Implementing Topic Messaging.

Когда клиентское приложение будет готово, мы реализуем командной строки C# приложение, которое отправляет Push-уведомления на уровне приложения клиента с помощью GCM.When the client app is ready, we'll implement a command-line C# application that sends a push notification to our client app via GCM.

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

Чтобы начать, давайте создадим новое пустое решение вызывается RemoteNotifications.To begin, let's create a new empty Solution called RemoteNotifications. Далее добавим в это решение на основе проекта Android приложение Android шаблона.Next, let's add a new Android project to this Solution that is based on the Android App template. Давайте назовем этот проект ClientApp.Let's call this project ClientApp. (Если вы не умеете создавать проекты Xamarin.Android, см. в разделе Привет, Android.) ClientApp проект будет содержать код для клиентского приложения Xamarin.Android, получающий удаленные уведомления с помощью GCM.(If you're not familiar with creating Xamarin.Android projects, see Hello, Android.) The ClientApp project will contain the code for the Xamarin.Android client application that receives remote notifications via GCM.

Добавьте необходимые пакетыAdd Required Packages

Прежде чем мы можем реализовать наш код клиента приложения, необходимо установить несколько пакетов, которые мы будем использовать для связи с GCM.Before we can implement our client app code, we must install several packages that we'll use for communication with GCM. Кроме того мы необходимо добавить приложение Google Play Store устройство, если они еще не установлены.Also, we must add the Google Play Store application to our device if it is not already installed.

Добавьте пакет Xamarin Google Play Services GCMAdd the Xamarin Google Play Services GCM Package

Для получения сообщений из Google Cloud Messaging, сервисы Google Play framework должен присутствовать на устройстве.To receive messages from Google Cloud Messaging, the Google Play Services framework must be present on the device. Без этой платформы приложение Android не может принимать сообщения от серверов GCM.Without this framework, an Android application cannot receive messages from GCM servers. Сервисы Google Play выполняется в фоновом режиме при включении устройства Android, незаметно прослушивание сообщений из GCM.Google Play Services runs in the background while the Android device is powered on, quietly listening for messages from GCM. При поступлении этих сообщений, сервисы Google Play преобразовывает сообщения в объекты Intent и затем передает эти intents к приложениям, которые зарегистрированы для них.When these messages arrive, Google Play Services converts the messages into intents and then broadcasts these intents to applications that have registered for them.

В Visual Studio щелкните правой кнопкой мыши ссылки > Управление пакетами NuGet... ; в Visual Studio для Mac, щелкните правой кнопкой мыши пакеты > Добавить пакеты... . Поиск Xamarin сервисы Google Play - GCM и установить этот пакет в ClientApp проекта:In Visual Studio, right-click References > Manage NuGet Packages ...; in Visual Studio for Mac, right-click Packages > Add Packages.... Search for Xamarin Google Play Services - GCM and install this package into the ClientApp project:

Установка служб Google PlayInstalling Google Play Services

При установке Xamarin сервисы Google Play - GCM, Xamarin сервисы Google Play - Base устанавливается автоматически.When you install Xamarin Google Play Services - GCM, Xamarin Google Play Services - Base is automatically installed. Если отобразится сообщение об ошибке, измените проект минимум Android к целевому объекту параметр в значение, отличное от компиляция с помощью пакета SDK версии и повторите попытку установки NuGet.If you get an error, change the project's Minimum Android to target setting to a value other than Compile using SDK version and try the NuGet install again.

Далее следует изменить MainActivity.cs и добавьте следующие using инструкции:Next, edit MainActivity.cs and add the following using statements:

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

Это делает типы в пакете GMS-службы Google Play для нашего кода, а также добавляет функции ведения журнала, который будет использоваться для отслеживания операций с GMS.This makes types in the Google Play Services GMS package available to our code, and it adds logging functionality that we will use to track our transactions with GMS.

Google Play StoreGoogle Play Store

Для получения сообщений из GCM, Google Play Store приложения должны устанавливаться на устройстве.To receive messages from GCM, the Google Play Store application must be installed on the device. (Каждый раз, когда на устройстве установлено приложение Google Play, Google Play Store также устанавливается, поэтому вполне вероятно, что он уже установлен на тестовом устройстве). Без Google Play приложение Android не может принимать сообщения из GCM.(Whenever a Google Play application is installed on a device, Google Play Store is also installed, so it's likely that it is already installed on your test device.) Without Google Play, an Android application cannot receive messages from GCM. Если у вас еще нет на Google Play Store приложение, установленное на вашем устройстве, посетите Google Play веб-сайта, чтобы загрузить и установить Google Play.If you do not yet have the Google Play Store app installed on your device, visit the Google Play web site to download and install Google Play.

Кроме того можно использовать эмулятор Android под управлением Android 2.2 или более поздней версии, а не на тестовое устройство (у вас нет для установки на эмуляторе Android Google Play Store).Alternately, you can use an Android emulator running Android 2.2 or later instead of a test device (you do not have to install Google Play Store on an Android emulator). Тем не менее если вы используете эмулятор, необходимо использовать Wi-Fi для подключения к службе GCM и необходимо открыть определенные порты в брандмауэре Wi-Fi, как описано далее в этом пошаговом руководстве.However, if you use an emulator, you must use Wi-Fi to connect to GCM and you must open several ports in your Wi-Fi firewall as explained later in this walkthrough.

Задайте имя пакетаSet the Package Name

В Google Cloud Messaging, мы указали имя пакета для нашего приложения с поддержкой GCM (это имя пакета также служит в качестве идентификатор приложения связанный ключ API и идентификатор отправителя).In Google Cloud Messaging, we specified a package name for our GCM-enabled app (this package name also serves as the application ID that is associated with our API key and Sender ID). Откроем свойства ClientApp проекта и задайте имя пакета для данной строки.Let's open the properties for the ClientApp project and set the package name to this string. В этом примере задается имя пакета com.xamarin.gcmexample:In this example, we set the package name to com.xamarin.gcmexample:

Задание имени пакетаSetting the package name

Обратите внимание, что клиентское приложение сможет получать маркер регистрации из GCM, если это имя пакета не точно совпадает с именем пакета, мы ввели в консоль разработчика Google.Note that the client app will be unable to receive a registration token from GCM if this package name does not exactly match the package name that we entered into the Google Developer console.

Добавление разрешений в манифест AndroidAdd Permissions to the Android Manifest

Приложение Android необходимо иметь следующие разрешения настроены, прежде чем он может получать уведомления от Google Cloud Messaging:An Android application must have the following permissions configured before it can receive notifications from Google Cloud Messaging:

  • com.google.android.c2dm.permission.RECEIVE – Предоставляет разрешение на уровне приложения для регистрации и получения сообщений из Google Cloud Messaging.com.google.android.c2dm.permission.RECEIVE – Grants permission to our app to register and receive messages from Google Cloud Messaging. (Что делает c2dm означает?(What does c2dm mean? Это означает облака для обмена сообщениями устройства, которой была создана неподдерживаемые до GCM.This stands for Cloud to Device Messaging, which is the now-deprecated predecessor to GCM. По-прежнему использует GCM c2dm во многих строк его разрешений.)GCM still uses c2dm in many of its permission strings.)

  • android.permission.WAKE_LOCK – (Необязательно) Устройство ЦП не переходить в спящий режим при прослушивании для сообщения.android.permission.WAKE_LOCK – (Optional) Prevents the device CPU from going to sleep while listening for a message.

  • android.permission.INTERNET – Предоставляет доступ к Интернету, чтобы клиентское приложение могло взаимодействовать с GCM.android.permission.INTERNET – Grants internet access so the client app can communicate with GCM.

  • имя_пакета .permission.C2D_MESSAGE – регистрирует приложение в Android и запрашивает разрешение на исключительно получать все C2D сообщений (облака на устройство).package_name.permission.C2D_MESSAGE – Registers the application with Android and requests permission to exclusively receive all C2D (cloud to device) messages. Имя_пакета префикс — так же, как идентификатор вашего приложения.The package_name prefix is the same as your application ID.

Мы настроим эти разрешения в манифесте Android.We'll set these permissions in the Android manifest. Изменим то AndroidManifest.xml и замените его содержимое следующим кодом XML:Let's edit AndroidManifest.xml and replace the contents with the following 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 имени пакета для проекта клиентского приложения.In the above XML, change YOUR_PACKAGE_NAME to the package name for your client app project. Например, com.xamarin.gcmexample.For example, com.xamarin.gcmexample.

Проверка службы Google PlayCheck for Google Play Services

В этом пошаговом руководстве мы создаем приложение Минималистическая с одним TextView в пользовательском Интерфейсе.For this walkthrough, we're creating a bare-bones app with a single TextView in the UI. Это приложение не указано, что непосредственно взаимодействие с GCM.This app doesn't directly indicate interaction with GCM. Вместо этого мы будет отслеживать в окне вывода, чтобы увидеть как наши приложения подтверждений в GCM, и мы проверим область уведомлений для новых уведомлений при их поступлении.Instead, we'll watch the output window to see how our app handshakes with GCM, and we'll check the notification tray for new notifications as they arrive.

Во-первых давайте создадим макет для области сообщений.First, let's create a layout for the message area. Изменить Resources.layout.Main.axml и замените его содержимое следующим кодом XML:Edit Resources.layout.Main.axml and replace the contents with the following 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 и закройте его.Save Main.axml and close it.

При запуске клиентского приложения, мы хотим его, чтобы проверить, что сервисы Google Play доступен, прежде чем мы попытаемся связаться GCM.When the client app starts, we want it to verify that Google Play Services is available before we attempt to contact GCM. Изменить MainActivity.cs и замените count экземпляра объявление переменной со следующим объявлением переменной экземпляра:Edit MainActivity.cs and replace the count instance variable declaration with the following instance variable declaration:

TextView msgText;

Добавьте следующий метод в MainActivity класса:Next, add the following method to the MainActivity class:

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.This code checks the device to see if the Google Play Services APK is installed. Если он не установлен, сообщение отображается в области сообщений, который указывает, что пользователю загрузить пакет APK в Google Play Store (или включить эту функцию в настройках устройства системы).If it is not installed, a message is displayed in the message area that instructs the user to download an APK from the Google Play Store (or enable it in the device's system settings). Поскольку нам нужно выполнять эту проверку при запуске клиентского приложения, мы добавим вызов этого метода в конце OnCreate.Because we want to run this check when the client app starts, we'll add a call to this method at the end of OnCreate.

Затем замените OnCreate метод следующим кодом:Next, replace the OnCreate method with the following code:

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

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

    IsPlayServicesAvailable ();
}

Этот код проверяет наличие пакета APK служб Google Play и записывает результаты в области сообщений.This code checks for the presence of the Google Play Services APK and writes the result to the message area.

Давайте полностью перестроить и запустить приложение.Let's completely rebuild and run the app. Вы увидите экран, который выглядит примерно так:You should see a screen that looks like the following screenshot:

Сервисы Google Play доступенGoogle Play Services is available

Если полученный в результате проверка установки APK служб Google Play на устройстве и который Xamarin сервисы Google Play - GCM пакет будет добавлен к вашей ClientApp проекта, как описано ранее.If you don't get this result, verify that the Google Play Services APK is installed on your device and that the Xamarin Google Play Services - GCM package is added to your ClientApp project as explained earlier. Если возникнет ошибка сборки, очистки решения и сборку проекта еще раз.If you get a build error, try cleaning the Solution and building the project again.

Далее мы напишем код, обратитесь в службу GCM и получать маркер регистрации.Next, we'll write code to contact GCM and get back a registration token.

Регистрации в GCMRegister with GCM

Прежде чем приложение сможет получать удаленные уведомления с сервера приложений, его регистрации в GCM и получить маркер регистрации.Before the app can receive remote notifications from the app server, it must register with GCM and get back a registration token. Обрабатывается работу по регистрации в GCM наше приложение IntentService , мы создаем.The work of registering our application with GCM is handled by an IntentService that we create. Наши IntentService выполняет следующие действия:Our IntentService performs the following steps:

  1. Использует InstanceID API для формирования токенов безопасности, который разрешает наше приложение клиента для доступа к серверу приложений.Uses the InstanceID API to generate security tokens that authorize our client app to access the app server. Взамен мы получаем регистрации токена из GCM.In return, we get back a registration token from GCM.

  2. Перенаправляет токен регистрации для сервера приложений (если сервер приложений требует его).Forwards the registration token to the app server (if the app server requires it).

  3. Подписывается на один или несколько каналов раздел уведомлений.Subscribes to one or more notification topic channels.

После реализовать это IntentService, мы протестируем его, чтобы увидеть, если мы получаем регистрации токена из GCM.After we implement this IntentService, we'll test it to see if we get back a registration token from GCM.

Добавьте новый файл с именем RegistrationIntentService.cs и замените код шаблона следующим:Add a new file called RegistrationIntentService.cs and replace the template code with the following:

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 с номером идентификатора отправителя для проекта клиентского приложения.In the above sample code, change YOUR_SENDER_ID to the Sender ID number for your client app project. Для получения идентификатора отправителя для проекта:To get the Sender ID for your project:

  1. Войдите на консоли Google Cloud и выберите имя проекта в раскрывающемся меню.Log into the Google Cloud Console and select your project name from the pull down menu. В проекта info области, отображаемый для проекта, выберите перейдите к параметрам проекта:In the Project info pane that is displayed for your project, click Go to project settings:

    Выбор проекта XamarinGCMSelecting XamarinGCM project

  2. На параметры найдите номер проекта – это идентификатор отправителя для проекта:On the Settings page, locate the Project number – this is the Sender ID for your project:

    Отображаемый номер проектаProject number displayed

Нам нужно запустить наш RegistrationIntentService при запуске нашего приложения.We want to start our RegistrationIntentService when our app starts running. Изменить MainActivity.cs и изменение OnCreate метод, чтобы наши RegistrationIntentService запускается после проверяется на наличие служб Google Play:Edit MainActivity.cs and modify the OnCreate method so that our RegistrationIntentService is started after we check for the presence of 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);
    }
}

Теперь давайте рассмотрим каждый раздел RegistrationIntentService для понимания принципов его работы.Now let's take a look at each section of RegistrationIntentService to understand how it works.

Во-первых, мы заметки к нашей RegistrationIntentService атрибутом ниже, чтобы указать, что наша служба не для создания экземпляра системы:First, we annotate our RegistrationIntentService with the following attribute to indicate that our service is not to be instantiated by the system:

[Service (Exported = false)]

RegistrationIntentService Конструктор имена рабочий поток RegistrationIntentService упростить отладку.The RegistrationIntentService constructor names the worker thread RegistrationIntentService to make debugging easier.

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

Основные функциональные возможности RegistrationIntentService находится в OnHandleIntent метод.The core functionality of RegistrationIntentService resides in the OnHandleIntent method. Давайте подробно рассмотрим этот код, чтобы увидеть, как наше приложение регистрацию в GCM.Let's walk through this code to see how it registers our app with GCM.

Запрос маркера регистрацииRequest a Registration Token

OnHandleIntent сначала вызывает Google InstanceID.GetToken метод для запроса маркера регистрации из GCM.OnHandleIntent first calls Google's InstanceID.GetToken method to request a registration token from GCM. Мы поместить этот код в lock Чтобы защититься от возможности несколько способов регистрации, которые выполняются одновременно – lock гарантирует, что эти intents обрабатываются последовательно.We wrap this code in a lock to guard against the possibility of multiple registration intents occurring simultaneously – the lock ensures that these intents are processed sequentially. Если мы не удалось получить маркер регистрации, возникает исключение, и мы в журнал ошибку.If we fail to get a registration token, an exception is thrown and we log an error. Если регистрация выполняется успешно, token задан маркер регистрации, мы вернулись из GCM:If the registration succeeds, token is set to the registration token we got back from 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 ...
Пересылать маркер регистрации для сервера приложенийForward the Registration Token to the App Server

Если мы получаем маркер регистрации (то есть исключение не создано), мы вызываем SendRegistrationToAppServer связываемый регистрации пользователя токена с учетной записью на сервере (если таковые имеются), обслуживаемый нашего приложения.If we get a registration token (that is, no exception was thrown), we call SendRegistrationToAppServer to associate the user's registration token with the server-side account (if any) that is maintained by our application. Поскольку эта реализация зависит от структуры приложения сервера, пустой метод представлено ниже:Because this implementation depends on the design of the app server, an empty method is provided here:

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

В некоторых случаях сервера приложений не требуется маркер регистрации пользователя; в этом случае этот метод может опускаться.In some cases, the app server does not need the user's registration token; in that case, this method can be omitted. При отправке маркера регистрации сервера приложений, SendRegistrationToAppServer следует поддерживать логическое значение, указывающее был ли маркер отправлен на сервер.When a registration token is sent to the app server, SendRegistrationToAppServer should maintain a boolean to indicate whether the token has been sent to the server. Если это логическое выражение имеет значение false, SendRegistrationToAppServer отправляет маркер для сервера приложений – в противном случае маркер уже было отправлено на сервер приложения в предыдущем вызове метода.If this boolean is false, SendRegistrationToAppServer sends the token to the app server – otherwise, the token was already sent to the app server in a previous call.

Подписаться на тему уведомленияSubscribe to the Notification Topic

Затем мы вызываем наших Subscribe метод для указания в GCM, которую необходимо подписаться на раздел уведомлений.Next, we call our Subscribe method to indicate to GCM that we want to subscribe to a notification topic. В Subscribe, мы вызываем GcmPubSub.Subscribe API подписаться наше приложение клиента ко всем сообщениям, в разделе /topics/global:In Subscribe, we call the GcmPubSub.Subscribe API to subscribe our client app to all messages under /topics/global:

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

Сервера приложений необходимо отправить уведомления /topics/global , чтобы получать их.The app server must send notification messages to /topics/global if we are to receive them. Обратите внимание, что имя раздела в разделе /topics можно изменить в зависимости, до тех пор, пока сервер приложений, так и с помощью клиентского приложения согласовать эти имена.Note that the topic name under /topics can be anything you want, as long as the app server and the client app both agree on these names. (Здесь мы выбрали имя global для указания, что мы хотим получать сообщения на все разделы, поддерживаемые сервером приложения.)(Here, we chose the name global to indicate that we want to receive messages on all topics supported by the app server.)

Сведения о разделе GCM, обмен сообщениями на стороне сервера, см. в разделе Google отправки сообщений на разделы.For information about GCM topic messaging on the server side, see Google's Send Messaging to Topics.

Реализовать службу прослушивания идентификатор экземпляраImplement an Instance ID Listener Service

Маркеры регистрации являются уникальным и безопасными; Тем не менее клиентское приложение (или GCM) может потребоваться обновить маркер регистрации в случае повторной установки приложения или проблема с безопасностью.Registration tokens are unique and secure; however, the client app (or GCM) may need to refresh the registration token in the event of app reinstallation or a security issue. По этой причине нужно реализовать InstanceIdListenerService , отвечает на запросы токена обновления от GCM.For this reason, we must implement an InstanceIdListenerService that responds to token refresh requests from GCM.

Добавьте новый файл с именем InstanceIdListenerService.cs и замените код шаблона следующим:Add a new file called InstanceIdListenerService.cs and replace the template code with the following:

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 (также называется идентификатор экземпляра) запросов:Annotate InstanceIdListenerService with the following attribute to indicate that the service is not to be instantiated by the system and that it can receive GCM registration token (also called instance ID) refresh requests:

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

OnTokenRefresh Метод наших начинает RegistrationIntentService таким образом, чтобы его можно перехватить новый маркер регистрации.The OnTokenRefresh method in our service starts the RegistrationIntentService so that it can intercept the new registration token.

Проверка регистрации в GCMTest Registration with GCM

Давайте полностью перестроить и запустить приложение.Let's completely rebuild and run the app. Если вы успешно получили маркер регистрации из GCM, маркер регистрации должны отображаться в окне вывода.If you successfully receive a registration token from GCM, the registration token should be displayed in the output window. Пример:For example:

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

Дескриптор подчиненных сообщенийHandle Downstream Messages

Код, который мы реализовали в данный момент — только код «настройки»; он проверяет, если сервисы Google Play установлено и проводит согласование с GCM и сервера приложений, для подготовки к нашей клиентское приложение для получения удаленных уведомлений.The code we have implemented thus far is only "set-up" code; it checks to see if Google Play Services is installed and negotiates with GCM and the app server to prepare our client app for receiving remote notifications. Тем не менее у нас есть еще реализовать код, который фактически получает и обрабатывает сообщения подчиненных уведомления.However, we have yet to implement code that actually receives and processes downstream notification messages. Для этого нужно реализовать служба прослушивания GCM.To do this, we must implement a GCM Listener Service. Такая служба получает сообщения раздела с сервера приложений и локально передает их в виде уведомлений.This service receives topic messages from the app server and locally broadcasts them as notifications. После мы реализуем эту службу, мы создадим тестовую программу для отправки сообщений в GCM, таким образом, мы видим, если наша реализация работает правильно.After we implement this service, we'll create a test program to send messages to GCM so that we can see if our implementation works correctly.

Добавление значка уведомленияAdd a Notification Icon

Сначала добавим мелкого значка, который будет отображаться в области уведомлений при запуске наших уведомлений.Let's first add a small icon that will appear in the notification area when our notification is launched. Вы можете скопировать этот значок в проект или создайте собственный пользовательский значок.You can copy this icon to your project or create your own custom icon. Мы назовем файл значка ic_stat_button_click.png и скопируйте его ресурсы/drawable папки.We'll name the icon file ic_stat_button_click.png and copy it to the Resources/drawable folder. Не забывайте использовать Добавить > существующий элемент... разместит этот файл значка в проекте.Remember to use Add > Existing Item ... to include this icon file in your project.

Реализовать службу прослушивания GCMImplement a GCM Listener Service

Добавьте новый файл с именем GcmListenerService.cs и замените код шаблона следующим:Add a new file called GcmListenerService.cs and replace the template code with the following:

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 для понимания принципов его работы.Let's take a look at each section of our GcmListenerService to understand how it works.

Во-первых, мы аннотировать GcmListenerService с атрибут, указывающий, что эта служба является не быть создан системой, и мы приводим намерений фильтра, чтобы указать, что он получает сообщения GCM:First, we annotate GcmListenerService with an attribute to indicate that this service is not to be instantiated by the system, and we include an intent filter to indicate that it receives GCM messages:

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

Когда GcmListenerService получает сообщение из GCM, OnMessageReceived вызывается метод.When GcmListenerService receives a message from GCM, the OnMessageReceived method is invoked. Этот метод извлекает содержимое сообщения из переданного Bundle, регистрирует содержимое сообщения (поэтому его можно просмотреть в окне вывода) и вызывает метод SendNotification для запуска локального уведомления с содержимым полученное сообщение:This method extracts the message content from the passed-in Bundle, logs the message content (so we can view it in the output window), and calls SendNotification to launch a local notification with the received message content:

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

SendNotification Использует метод Notification.Builder для создания уведомления, а затем использует NotificationManager для запуска уведомления.The SendNotification method uses Notification.Builder to create the notification, and then it uses the NotificationManager to launch the notification. Фактически это преобразует сообщение удаленного уведомления в локальное уведомление, которые будут отображаться для пользователя.Effectively, this converts the remote notification message into a local notification to be presented to the user. Дополнительные сведения об использовании Notification.Builder и NotificationManager, см. в разделе локальных уведомлений.For more information about using Notification.Builder and NotificationManager, see Local Notifications.

Объявите получателя в манифестеDeclare the Receiver in the Manifest

Прежде чем мы может получать сообщения из GCM, мы должны объявлять прослушивателя GCM в манифесте Android.Before we can receive messages from GCM, we must declare the GCM listener in the Android manifest. Изменим то AndroidManifest.xml и замените <application> раздел с следующий код XML:Let's edit AndroidManifest.xml and replace the <application> section with the following 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 имени пакета для проекта клиентского приложения.In the above XML, change YOUR_PACKAGE_NAME to the package name for your client app project. В нашем примере Пошаговое руководство, имя пакета — com.xamarin.gcmexample.In our walkthrough example, the package name is com.xamarin.gcmexample.

Давайте взглянем на назначение каждого из параметров в этот XML-код:Let's look at what each setting in this XML does:

ПараметрSetting ОписаниеDescription
com.google.android.gms.gcm.GcmReceiver Объявляет, что наше приложение реализует получатель GCM, который перехватывает и обрабатывает входящие сообщения push-уведомлений.Declares that our app implements a GCM receiver that captures and processes incoming push notification messages.
com.google.android.c2dm.permission.SEND Объявляет, что только серверы GCM может отправлять сообщения непосредственно в приложение.Declares that only GCM servers can send messages directly to the app.
com.google.android.c2dm.intent.RECEIVE Фильтр намерений рекламу, что наше приложение обрабатывает широковещательные сообщения от GCM.Intent filter advertising that our app handles broadcast messages from GCM.
com.google.android.c2dm.intent.REGISTRATION Фильтр намерений, рекламу, что наше приложение обрабатывает новых инструментов intents регистрации (то есть мы реализовали службу прослушивания Идентификаторов экземпляра).Intent filter advertising that our app handles new registration intents (that is, we have implemented an Instance ID Listener Service).

Кроме того, вы можете дополнить GcmListenerService с этих атрибутов, а не указывая их в XML; здесь мы указываем их в AndroidManifest.xml таким образом, проще воспринимать, примеры кода.Alternatively, you can decorate GcmListenerService with these attributes rather than specifying them in XML; here we specify them in AndroidManifest.xml so that the code samples are easier to follow.

Создание отправителя сообщения для тестирования приложенияCreate a Message Sender to Test the App

Давайте добавим C# рабочего стола консольного приложения проекта в решение и назовите его MessageSender.Let's add a C# desktop console application project to the Solution and call it MessageSender. Мы будем использовать это консольное приложение для имитации серверу приложений – будут отправляться сообщения уведомления для ClientApp через GCM.We'll use this console application to simulate an application server – it will send notification messages to ClientApp via GCM.

Добавьте пакет Json.NETAdd the Json.NET Package

Это консольное приложение мы создаем, полезные данные JSON, содержащий сообщение уведомления, которые нужно отправить в клиентское приложение.In this console app, we're building a JSON payload that contains the notification message we want to send to the client app. Мы будем использовать Json.NET упаковать в MessageSender для упрощения построения объект JSON, необходимый для GCM.We'll use the Json.NET package in MessageSender to make it easier to build the JSON object required by GCM. В Visual Studio щелкните правой кнопкой мыши ссылки > Управление пакетами NuGet... ; в Visual Studio для Mac, щелкните правой кнопкой мыши пакеты > Добавить пакеты... .In Visual Studio, right-click References > Manage NuGet Packages ...; in Visual Studio for Mac, right-click Packages > Add Packages....

Выполним поиск Json.NET пакет и установите его в проект:Let's search for the Json.NET package and install it in the project:

Установка пакета Json.NETInstalling the Json.NET package

Добавьте ссылку на System.Net.HttpAdd a Reference to System.Net.Http

Нам также нужно будет добавить ссылку на System.Net.Http таким образом, можно создать экземпляр HttpClient для отправки сообщений теста GCM.We'll also need to add a reference to System.Net.Http so that we can instantiate an HttpClient for sending our test message to GCM. В MessageSender проекта, щелкните правой кнопкой мыши ссылки > Добавить ссылку и прокрутите вниз, пока не увидите System.Net.Http.In the MessageSender project, Right-click References > Add Reference and scroll down until you see System.Net.Http. Установите флажок рядом с полем System.Net.Http и нажмите кнопку ОК.Put a check mark next to System.Net.Http and click OK.

Реализовать код, который отправляет тестовое сообщениеImplement Code that Sends a Test Message

В MessageSender, изменить Program.cs и замените его содержимое следующим кодом:In MessageSender, edit Program.cs and replace the contents with the following code:

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

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

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

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

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

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

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

В приведенном выше коде измените YOUR_API_KEY на ключ API для проекта клиентского приложения.In the above code, change YOUR_API_KEY to the API Key for your client app project.

Этот сервер приложения тестирования отправляет приведенное ниже формате JSON в GCM:This test app server sends the following JSON-formatted message to GCM:

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

GCM, в свою очередь, передает это сообщение, чтобы клиентское приложение.GCM, in turn, forwards this message to your client app. Давайте создадим MessageSender и откройте окно консоли, где мы его могут запустить из командной строки.Let's build MessageSender and open a console window where we can run it from the command line.

Попробуйте!Try It!

Теперь мы готовы протестировать наше приложение клиента.Now we're ready to test our client app. Если вы используете эмулятор или устройство обменивается с GCM Wi-Fi, необходимо открыть следующие TCP-порты в брандмауэре сообщений GCM, позволяющих протащить: 5228 5229 и 5230: создание.If you're using an emulator or if your device is communicating with GCM over Wi-Fi, you must open the following TCP ports on your firewall for GCM messages to get through: 5228, 5229, and 5230.

Запустите клиентское приложение и просмотрите окно вывода.Start your client app and watch the output window. После RegistrationIntentService успешно получает регистрации токена из GCM, в окне вывода отобразится маркер с выходными данными журнала, аналогичный следующему:After the RegistrationIntentService successfully receives a registration token from GCM, the output window should display the token with log output resembling the following:

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

На этом этапе клиентское приложение готова получать сообщение удаленного уведомления.At this point the client app is ready to receive a remote notification message. В командной строке выполните MessageSender.exe программы, чтобы отправить сообщение «Hello, Xamarin» уведомления в клиентское приложение.From the command line, run the MessageSender.exe program to send a "Hello, Xamarin" notification message to the client app. Если вы еще не построены MessageSender проекта, сделайте это сейчас.If you have not yet built the MessageSender project, do so now.

Для запуска MessageSender.exe в Visual Studio, откройте командную строку, измените MessageSender/bin/Debug каталог и выполните команду напрямую:To run MessageSender.exe under Visual Studio, open a command prompt, change to the MessageSender/bin/Debug directory, and run the command directly:

MessageSender.exe

Для запуска MessageSender.exe в Visual Studio для Mac откройте сеанс терминала, измените MessageSender/bin/Debug моно использовать для запуска и каталог MessageSender.exeTo run MessageSender.exe under Visual Studio for Mac, open a Terminal session, change to MessageSender/bin/Debug the directory, and use mono to run MessageSender.exe

mono MessageSender.exe

Он может занять до минуты для сообщения для распространения через GCM и обратно вниз, чтобы клиентское приложение.It may take up to a minute for the message to propagate through GCM and back down to your client app. Если сообщение успешно получено, мы должны увидеть результат, аналогичный следующему в окне вывода.If the message is received successfully, we should see output resembling the following in the output window:

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

Кроме того можно заметить, что в области уведомлений отображается значок нового уведомления:In addition, you should notice that a new notification icon has appeared in the notification tray:

Значок уведомления отображается на устройствеNotification icon appears on device

При открытии в область уведомлений для просмотра уведомлений, вы увидите, что наши удаленного уведомления:When you open the notification tray to view notifications, you should see our remote notification:

Отображается сообщение уведомленияNotification message is displayed

Поздравляем, ваше приложение получило его первого удаленного уведомления.Congratulations, your app has received its first remote notification!

Обратите внимание на то, что GCM сообщения больше не будут приниматься, если приложение является force остановлено.Note that GCM messages will no longer be received if the app is force-stopped. Чтобы возобновить уведомления после принудительно остановите, приложение необходимо вручную перезапустить.To resume notifications after a force-stop, the app must be manually restarted. Дополнительные сведения об этой политике Android см. в разделе запуска элементы управления, на остановленные приложения и это post переполнения стека.For more information about this Android policy, see Launch controls on stopped applications and this stack overflow post.

СводкаSummary

В этом пошаговом руководстве подробные шаги по реализации удаленные уведомления в приложениях Xamarin.Android.This walkthrough detailed the steps for implementing remote notifications in a Xamarin.Android application. Оно было описано, как установить дополнительные пакеты, необходимые для связи с GCM, а его было рассмотрено, как настроить приложение разрешения для доступа к серверам GCM.It described how to install additional packages needed for GCM communications, and it explained how to configure app permissions for access to GCM servers. Она предоставляла пример кода, демонстрирующий, как проверить наличие служб Google Play, как реализовать службу прослушивания Идентификаторов экземпляра, которая согласовывает с, GCM для маркера регистрации и намерением службы регистрации и как реализовать прослушиватель GCM Служба, которая получает и обрабатывает сообщения удаленного уведомления.It provided example code that illustrates how to check for the presence of Google Play Services, how to implement a registration intent service and instance ID listener service that negotiates with GCM for a registration token, and how to implement a GCM listener service that receives and processes remote notification messages. Наконец мы реализовали программы тестирования командной строки для отправки тестовых уведомлений на уровне приложения клиента через GCM.Finally, we implemented a command-line test program to send test notifications to our client app through GCM.