将推送通知添加到 Xamarin.Android 应用

概述

在本教程中,将推送通知添加到 Xamarin.Android 快速入门 项目,以便在每次插入记录时向设备发送推送通知。

如果不使用下载的快速启动服务器项目,则需要推送通知扩展包。 有关详细信息,请参阅 适用于 Azure 移动应用的 .NET 后端服务器 SDK 指南。

先决条件

本教程需要设置:

配置通知中心

Azure 应用服务的移动应用功能使用 Azure 通知中心 发送推送,因此你将为移动应用配置通知中心。

  1. Azure 门户中,转到 应用服务,然后选择应用后端。 在 设置中,选择 推送

  2. 若要向应用添加通知中心资源,请选择 连接。 可以创建中心或连接到现有中心。

    配置集线器

现在,已将通知中心连接到移动应用后端项目。 稍后,请将此通知中心配置为连接到平台通知系统(PNS),以推送到设备。

启用 Firebase Cloud Messaging

  1. 登录到 Firebase 控制台。 如果还没有 Firebase 项目,创建一个新项目。

  2. 创建项目后,选择“向 Android 应用添加 Firebase”。

    将 Firebase 添加到 Android 应用

  3. 在“将 Firebase 添加到 Android 应用”页上,执行以下步骤:

    1. 对于“Android 程序包名称”,请在应用程序的 build.gradle 文件中复制 applicationId 的值。 在此示例中,它是 com.fabrikam.fcmtutorial1app

      指定程序包名称

    2. 选择“注册应用”。

  4. 选择“下载 google-services.json”,将该文件保存到项目的 app 文件夹中,然后选择“下一步”

    下载 google-services.json

  5. 在 Android Studio 中对你的项目进行以下配置更改

    1. 在项目级 build.gradle 文件 (<project>/build.gradle) 中,向 dependencies 部分中添加以下语句。

      classpath 'com.google.gms:google-services:4.0.1'
      
    2. 在应用级 build.gradle 文件 (<project>/<app-module>/build.gradle) 中,向 dependencies 部分中添加以下语句。

      implementation 'com.google.firebase:firebase-core:16.0.8'
      implementation 'com.google.firebase:firebase-messaging:17.3.4'
      
    3. 在应用级 build.gradle 文件的末尾,在 dependencies 部分后面添加以下行。

      apply plugin: 'com.google.gms.google-services'
      
    4. 在工具栏上选择“立即同步”。

      build.gradle 配置更改

  6. 选择“下一步”。

  7. 选择“跳过此步骤”

    跳过最后一步

  8. 在 Firebase 控制台中,选择与项目相对应的齿轮图标。 然后,选择“项目设置”。

    选择“项目设置”

  9. 如果尚未将 google-services.json 文件下载到你的 Android Studio 项目的 app 文件夹中,则可以在此页面上执行此操作。

  10. 切换到顶部的“Cloud Messaging”选项卡。

  11. 复制并保存服务器密钥以供将来使用。 您可以使用此值来配置集线器。

配置 Azure 以发送推送请求

  1. Azure 门户中,单击“浏览所有”>“应用服务”,然后单击您的移动应用后端。 在 设置下,单击 应用服务推送,然后单击通知中心名称。

  2. 转到 Google (GCM),输入在上一过程中从 Firebase 获取的 服务器密钥 值,然后单击“保存”。

    在门户中设置 API 密钥

移动应用后端现已配置为使用 Firebase Cloud Messaging。 这样,便可以使用通知中心将推送通知发送到在 Android 设备上运行的应用。

更新服务器项目以发送推送通知

在本部分中,将更新现有移动应用后端项目中的代码,以每次添加新项时发送推送通知。 此过程由 Azure 通知中心的 模板 功能提供支持,该功能支持跨平台推送。 各种客户端都使用模板注册推送通知,单个通用推送可以访问所有客户端平台。

选择以下过程之一,该过程应与您的后端项目类型匹配:.NET 后端Node.js 后端

.NET 后端项目

  1. 在 Visual Studio 中,右键单击服务器项目。 然后选择 管理 NuGet 包。 搜索 Microsoft.Azure.NotificationHubs,然后选择 安装。 此过程安装通知中心库,用于从后端发送通知。

  2. 在服务器项目中,打开 控制器>TodoItemController.cs。 然后使用以下语句添加:

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

    此过程发送包含项的模板通知。插入新项时的文本。

  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. 在本地计算机上编辑该文件时,请重新发布服务器项目。

为推送通知配置客户端项目

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

    这样,便可以从推送处理程序服务进程访问移动客户端实例。

  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 现已准备好添加推送通知。

向应用添加推送通知代码

  1. 在项目中创建一个名为ToDoBroadcastReceiver的新类。

  2. 将以下 using 语句添加到 ToDoBroadcastReceiver 类:

    using Gcm.Client;
    using Microsoft.WindowsAzure.MobileServices;
    using Newtonsoft.Json.Linq;
    
  3. using 语句和 命名空间 声明之间添加以下权限请求:

    [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 ,并且 服务 属性必须应用于此类。

    注释

    GcmServiceBase 类实现 OnRegistered()OnUnRegistered()OnMessage()OnError() 方法。 必须在 PushHandlerService 类中重写这些方法。

  6. 将以下代码添加到替代 OnRegistered 事件处理程序的 PushHandlerService 类。

    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 注册 ID 向 Azure 注册以获取推送通知。 只能在创建标记后将其添加到注册中。 有关详细信息,请参阅 如何将标签添加到设备安装以启用标记推送

  7. 使用以下代码替代 PushHandlerService 中的 OnMessage 方法:

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

在应用中测试推送通知

可以在模拟器中使用虚拟设备测试应用。 在模拟器上运行时,还需要执行其他配置步骤。

  1. 虚拟设备必须在 Android 虚拟设备(AVD)管理器中将 Google API 设置为目标。

  2. 单击 “应用>设置>添加帐户”,将 Google 帐户添加到 Android 设备,然后按照提示作。

  3. 像以前一样运行待办事项列表应用,并插入新的待办事项项。 这一次,通知区域会显示一个通知图标。 可以打开通知抽屉以查看通知的全文。