Добавление push-уведомлений в приложение Xamarin.Android

Обзор

В этом руководстве мы добавим push-уведомления в проект быстрого запуска Xamarin.Android, чтобы при каждом добавлении новой записи на устройство отправлялось push-уведомление.

Если вы не используете скачанный проект сервера, необходимо добавить пакет расширений для push-уведомлений. Дополнительные сведения см. в статье Работа с пакетом SDK для внутреннего сервера .NET для мобильных приложений Azure.

Предварительные требования

Для работы с этим руководством требуется настройка:

Настройка концентратора уведомлений

Компонент мобильных приложений в службе приложений Azure использует Центры уведомлений Azure для отправки push-уведомлений, поэтому вам нужно настроить центр уведомлений для мобильного приложения.

  1. На портале Azure щелкните Службы приложений, а затем выберите серверную часть приложения. В разделе Параметры выберите Push.

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

    Настройка концентратора

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

Включение Firebase Cloud Messaging

  1. Войдите в консоль Firebase. Создайте проект Firebase, если его еще нет.

  2. После создания проекта выберите Add Firebase to your Android app (Добавить Firebase в приложение Android).

    Добавление Firebase в приложение Android

  3. Выполните следующие действия на странице Add Firebase to your Android app (Добавление Firebase в приложение Android):

    1. Для Имя пакета Android скопируйте свое значение applicationId в файл приложения build.gradle. В нашем примере он выглядит следующим образом: com.fabrikam.fcmtutorial1app.

      Указание имени пакета.

    2. Выберите Регистрация приложения.

  4. Выберите Download google-services.json (Загрузить google-services.json), сохраните файл в папку приложения проекта, а затем выберите Далее.

    Загрузка файла google-services.json.

  5. Внесите следующие изменения конфигурации в проект в Android Studio.

    1. В файл build.gradle уровня проекта (<project>/build.gradle) добавьте следующий текст в раздел зависимости.

      classpath 'com.google.gms:google-services:4.0.1'
      
    2. В файле build.gradle уровня приложения (<project>/<app-module>/build.gradle) в раздел зависимостей добавьте следующий текст.

      implementation 'com.google.firebase:firebase-core:16.0.8'
      implementation 'com.google.firebase:firebase-messaging:17.3.4'
      
    3. Добавьте следующую строку в конец файла build.gradle уровня приложения после раздела с зависимостями.

      apply plugin: 'com.google.gms.google-services'
      
    4. На панели инструментов щелкните Синхронизировать сейчас.

      Изменения конфигурации build.gradle.

  6. Выберите Далее.

  7. Выберите Пропустить этот шаг.

    Пропуск последнего шага.

  8. В консоли Firebase щелкните значок шестеренки возле имени проекта. Выберите пункт Project Settings (Параметры проекта).

    Выбор параметров проекта

  9. Если вы еще не скачали файл google-services.json в папку app проекта Android Studio, это можно сделать на этой странице.

  10. Переключитесь на вкладку Обмен сообщениями в облаке в верхней части.

  11. Скопируйте и сохраните Ключ сервера для последующего использования. Это значение используется для настройки имени центра.

Настройка Azure для отправки push-запросов

  1. На портале Azure щелкните Просмотреть все>Службы приложений, а затем выберите серверную часть своего мобильного приложения. В разделе Параметры щелкните App Service Push (Push-уведомления службы приложений) и выберите имя центра уведомлений.

  2. Выберите Google (GCM), введите значение ключа сервера, полученное от Firebase в ходе предыдущей процедуры, и нажмите кнопку Сохранить.

    Указание ключа API на портале

Теперь серверная часть вашего мобильного приложения настроена для использования Firebase Cloud Messaging. Это позволяет отправлять push-уведомления приложению Android через центр уведомлений.

Обновление серверного проекта для отправки push-уведомлений

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

Выберите одну из следующих процедур, которые соответствуют типу проекта серверной части — серверной части .NET или Node.js серверной части.

Серверный проект .NET

  1. В Visual Studio щелкните правой кнопкой мыши серверный проект. Затем выберите Управление пакетами NuGet. Найдите Microsoft.Azure.NotificationHubs, а затем нажмите кнопку Установить. Этот процесс устанавливает библиотеку Центров уведомлений для отправки уведомлений из серверной части.

  2. В серверном проекте откройте файл Controllers>TodoItemController.cs. Затем добавьте следующие операторы using:

    using System.Collections.Generic;
    using Microsoft.Azure.NotificationHubs;
    using Microsoft.Azure.Mobile.Server.Config;
    
  3. В метод PostTodoItem добавьте следующий код после вызова InsertAsync.

    // Get the settings for the server project.
    HttpConfiguration config = this.Configuration;
    MobileAppSettingsDictionary settings =
        this.Configuration.GetMobileAppSettingsProvider().GetMobileAppSettings();
    
    // Get the Notification Hubs credentials for the mobile app.
    string notificationHubName = settings.NotificationHubName;
    string notificationHubConnection = settings
        .Connections[MobileAppSettingsKeys.NotificationHubConnectionString].ConnectionString;
    
    // Create a new Notification Hub client.
    NotificationHubClient hub = NotificationHubClient
    .CreateClientFromConnectionString(notificationHubConnection, notificationHubName);
    
    // Send the message so that all template registrations that contain "messageParam"
    // receive the notifications. This includes APNS, GCM, WNS, and MPNS template registrations.
    Dictionary<string,string> templateParams = new Dictionary<string,string>();
    templateParams["messageParam"] = item.Text + " was added to the list.";
    
    try
    {
        // Send the push notification and log the results.
        var result = await hub.SendTemplateNotificationAsync(templateParams);
    
        // Write the success result to the logs.
        config.Services.GetTraceWriter().Info(result.State.ToString());
    }
    catch (System.Exception ex)
    {
        // Write the failure result to the logs.
        config.Services.GetTraceWriter()
            .Error(ex.Message, null, "Push.SendAsync Error");
    }
    

    При вставке нового элемента отправляется шаблонное уведомление, содержащее item.Text.

  4. Повторная публикация серверного проекта

Серверный проект Node.js

  1. Настройте внутренний проект.

  2. Замените существующий код в файле todoitem.js следующим кодом:

    var azureMobileApps = require('azure-mobile-apps'),
    promises = require('azure-mobile-apps/src/utilities/promises'),
    logger = require('azure-mobile-apps/src/logger');
    
    var table = azureMobileApps.table();
    
    table.insert(function (context) {
    // For more information about the Notification Hubs JavaScript SDK,
    // see https://aka.ms/nodejshubs.
    logger.info('Running TodoItem.insert');
    
    // Define the template payload.
    var payload = '{"messageParam": "' + context.item.text + '" }';  
    
    // Execute the insert. The insert returns the results as a promise.
    // Do the push as a post-execute action within the promise flow.
    return context.execute()
        .then(function (results) {
            // Only do the push if configured.
            if (context.push) {
                // Send a template notification.
                context.push.send(null, payload, function (error) {
                    if (error) {
                        logger.error('Error while sending push notification: ', error);
                    } else {
                        logger.info('Push notification sent successfully!');
                    }
                });
            }
            // Don't forget to return the results from the context.execute().
            return results;
        })
        .catch(function (error) {
            logger.error('Error while running context.execute: ', error);
        });
    });
    
    module.exports = table;  
    

    При вставке нового элемента отправляется шаблонное уведомление, содержащее item.Text.

  3. При редактировании этого файла на локальном компьютере повторно опубликуйте серверный проект.

Настройка клиентского проекта для использования push-уведомлений

  1. В представлении решения (или Обозреватель решений в Visual Studio) щелкните правой кнопкой мыши папку "Компоненты", выберите команду "Получить дополнительные компоненты...", найдите компонент клиента Google Cloud Messaging и добавьте его в проект.

  2. Откройте файл проекта ToDoActivity.cs и добавьте в класс следующую инструкцию using:

    using Gcm.Client;
    
  3. Добавьте в класс ToDoActivity следующий новый код:

    // Create a new instance field for this activity.
    static ToDoActivity instance = new ToDoActivity();
    
    // Return the current activity instance.
    public static ToDoActivity CurrentActivity
    {
        get
        {
            return instance;
        }
    }
    // Return the Mobile Services client.
    public MobileServiceClient CurrentClient
    {
        get
        {
            return client;
        }
    }
    

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

  4. После создания MobileServiceClient добавьте в метод OnCreate следующий код:

    // Set the current instance of TodoActivity.
    instance = this;
    
    // Make sure the GCM client is set up correctly.
    GcmClient.CheckDevice(this);
    GcmClient.CheckManifest(this);
    
    // Register the app for push notifications.
    GcmClient.Register(this, ToDoBroadcastReceiver.senderIDs);
    

Ваш класс ToDoActivity теперь готов для добавления push-уведомлений.

Добавление кода push-уведомлений в приложение

  1. Создайте класс в проекте с именем ToDoBroadcastReceiver.

  2. Добавьте следующие инструкции using в класс ToDoBroadcastReceiver :

    using Gcm.Client;
    using Microsoft.WindowsAzure.MobileServices;
    using Newtonsoft.Json.Linq;
    
  3. Добавьте следующие разрешения запросов между операторами using и объявлением namespace:

    [assembly: Permission(Name = "@PACKAGE_NAME@.permission.C2D_MESSAGE")]
    [assembly: UsesPermission(Name = "@PACKAGE_NAME@.permission.C2D_MESSAGE")]
    [assembly: UsesPermission(Name = "com.google.android.c2dm.permission.RECEIVE")]
    //GET_ACCOUNTS is only needed for android versions 4.0.3 and below
    [assembly: UsesPermission(Name = "android.permission.GET_ACCOUNTS")]
    [assembly: UsesPermission(Name = "android.permission.INTERNET")]
    [assembly: UsesPermission(Name = "android.permission.WAKE_LOCK")]
    
  4. Замените существующее определение класса ToDoBroadcastReceiver следующим:

    [BroadcastReceiver(Permission = Gcm.Client.Constants.PERMISSION_GCM_INTENTS)]
    [IntentFilter(new string[] { Gcm.Client.Constants.INTENT_FROM_GCM_MESSAGE }, 
        Categories = new string[] { "@PACKAGE_NAME@" })]
    [IntentFilter(new string[] { Gcm.Client.Constants.INTENT_FROM_GCM_REGISTRATION_CALLBACK }, 
        Categories = new string[] { "@PACKAGE_NAME@" })]
    [IntentFilter(new string[] { Gcm.Client.Constants.INTENT_FROM_GCM_LIBRARY_RETRY }, 
    Categories = new string[] { "@PACKAGE_NAME@" })]
    public class ToDoBroadcastReceiver : GcmBroadcastReceiverBase<PushHandlerService>
    {
        // Set the Google app ID.
        public static string[] senderIDs = new string[] { "<PROJECT_NUMBER>" };
    }
    

    В приведенном выше коде необходимо заменить <PROJECT_NUMBER> номером проекта, назначенным службой Google при подготовке приложения к работе на портале разработчика Google.

  5. В файле проекта ToDoBroadcastReceiver.cs добавьте следующий код, который определяет класс PushHandlerService :

    // The ServiceAttribute must be applied to the class.
    [Service]
    public class PushHandlerService : GcmServiceBase
    {
        public static string RegistrationID { get; private set; }
        public PushHandlerService() : base(ToDoBroadcastReceiver.senderIDs) { }
    }
    

    Обратите внимание, что этот класс является производным от GcmServiceBase, поэтому к нему необходимо применить атрибут Service.

    Примечание

    Класс GcmServiceBase реализует методы OnRegistered(), OnUnRegistered(), OnMessage() и OnError(). Эти методы необходимо переопределить в классе PushHandlerService .

  6. Добавьте приведенный ниже код в класс PushHandlerService, который переопределяет обработчик событий OnRegistered.

    protected override void OnRegistered(Context context, string registrationId)
    {
        System.Diagnostics.Debug.WriteLine("The device has been registered with GCM.", "Success!");
    
        // Get the MobileServiceClient from the current activity instance.
        MobileServiceClient client = ToDoActivity.CurrentActivity.CurrentClient;
        var push = client.GetPush();
    
        // Define a message body for GCM.
        const string templateBodyGCM = "{\"data\":{\"message\":\"$(messageParam)\"}}";
    
        // Define the template registration as JSON.
        JObject templates = new JObject();
        templates["genericMessage"] = new JObject
        {
            {"body", templateBodyGCM }
        };
    
        try
        {
            // Make sure we run the registration on the same thread as the activity, 
            // to avoid threading errors.
            ToDoActivity.CurrentActivity.RunOnUiThread(
    
                // Register the template with Notification Hubs.
                async () => await push.RegisterAsync(registrationId, templates));
    
            System.Diagnostics.Debug.WriteLine(
                string.Format("Push Installation Id", push.InstallationId.ToString()));
        }
        catch (Exception ex)
        {
            System.Diagnostics.Debug.WriteLine(
                string.Format("Error with Azure push registration: {0}", ex.Message));
        }
    }
    

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

  7. Переопределите метод OnMessage в PushHandlerService с использованием следующего кода:

    protected override void OnMessage(Context context, Intent intent)
    {
        string message = string.Empty;
    
        // Extract the push notification message from the intent.
        if (intent.Extras.ContainsKey("message"))
        {
            message = intent.Extras.Get("message").ToString();
            var title = "New item added:";
    
            // Create a notification manager to send the notification.
            var notificationManager = 
                GetSystemService(Context.NotificationService) as NotificationManager;
    
            // Create a new intent to show the notification in the UI. 
            PendingIntent contentIntent =
                PendingIntent.GetActivity(context, 0,
                new Intent(this, typeof(ToDoActivity)), 0);
    
            // Create the notification using the builder.
            var builder = new Notification.Builder(context);
            builder.SetAutoCancel(true);
            builder.SetContentTitle(title);
            builder.SetContentText(message);
            builder.SetSmallIcon(Resource.Drawable.ic_launcher);
            builder.SetContentIntent(contentIntent);
            var notification = builder.Build();
    
            // Display the notification in the Notifications Area.
            notificationManager.Notify(1, notification);
    
        }
    }
    
  8. Переопределите методы OnUnRegistered() и OnError() с помощью следующего кода:

    protected override void OnUnRegistered(Context context, string registrationId)
    {
        throw new NotImplementedException();
    }
    
    protected override void OnError(Context context, string errorId)
    {
        System.Diagnostics.Debug.WriteLine(
            string.Format("Error occurred in the notification: {0}.", errorId));
    }
    

Тестирование push-уведомлений в приложении

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

  1. На виртуальном устройстве необходимо задать API-интерфейсы Google в качестве целевого объекта для диспетчера виртуальных устройств Android (AVD).

  2. Добавьте учетную запись Google на устройство Android, нажав кнопку "Параметры>приложений>" добавить учетную запись, а затем следуйте инструкциям.

  3. Запустите приложение todolist, как ранее, и вставьте новый элемент списка дел. На этот раз в области уведомлений отображается значок уведомления. Вы можете открыть панель уведомлений, чтобы просмотреть полный текст уведомления.