将推送通知添加到 iOS 应用

概述

本教程介绍如何向 iOS 快速入门项目添加推送通知,以便每次插入一条记录时,都向设备发送一条推送通知。

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

iOS 模拟器不支持推送通知。 需要一个物理 iOS 设备和 Apple 开发人员计划成员身份

配置通知中心

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

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

  2. 若要将通知中心资源添加到应用中,请选择“连接”。 可以创建一个中心,也可以连接到一个现有的中心。

    配置中心

现在已将通知中心连接到移动应用后端项目。 稍后需对此通知中心进行配置,以便连接到将内容推送到设备的平台通知系统 (PNS)。

为推送通知注册应用

  • 为应用注册应用 ID。 创建显式应用 ID (不是通配符应用 ID) ,对于 捆绑 ID,请使用 Xcode 快速入门项目中的确切捆绑 ID。 此外,必须选择“推送通知”选项。
  • 接下来,为了准备配置推送通知,请创建“开发”或“分发”SSL 证书。

配置 Azure 以发送推送通知

  1. 在 Mac 上启动“Keychain Access”。 在左侧导航栏中的“类别”下,打开“我的证书”。 找到已在前一部分下载的 SSL 证书,并公开其内容。 仅选择证书(不选择私钥)。 然后将其导出
  2. Azure 门户中,选择“浏览全部”>“应用程序服务”。 然后选择“移动应用”后端。
  3. 在“设置”下,选择“应用服务推送”。 然后选择通知中心名称。
  4. 转到“Apple Push Notification 服务”>“上传证书” 。 上传 .p12 文件,选择正确的模式(具体取决于此前的客户端 SSL 证书是生产证书还是沙盒证书)。 保存任何更改。

现在,服务已配置为在 iOS 上使用通知中心。

更新后端以发送推送通知

.NET 后端 (C#)

  1. 在 Visual Studio 中,右键单击服务器项目并单击“管理 NuGet 包”,搜索 Microsoft.Azure.NotificationHubs,并单击“安装”。 这会安装通知中心库,以便从后端发送通知。

  2. 在后端的 Visual Studio 项目中,依次打开“控制器”>“TodoItemController.cs” 。 在文件的顶部,添加以下 using 语句:

    using Microsoft.Azure.Mobile.Server.Config;
    using Microsoft.Azure.NotificationHubs;
    
  3. PostTodoItem 方法替换为以下代码:

    public async Task<IHttpActionResult> PostTodoItem(TodoItem item)
    {
        TodoItem current = await InsertAsync(item);
        // 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);
    
        // iOS payload
        var appleNotificationPayload = "{\"aps\":{\"alert\":\"" + item.Text + "\"}}";
    
        try
        {
            // Send the push notification and log the results.
            var result = await hub.SendAppleNativeNotificationAsync(appleNotificationPayload);
    
            // 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");
        }
        return CreatedAtRoute("Tables", new { id = current.Id }, current);
    }
    
  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();
    
    // When adding record, send a push notification via APNS
    table.insert(function (context) {
        // For details of the Notification Hubs JavaScript SDK, 
        // see https://aka.ms/nodejshubs
        logger.info('Running TodoItem.insert');
    
        // Create a payload that contains the new item Text.
        var payload = "{\"aps\":{\"alert\":\"" + context.item.text + "\"}}";
    
        // Execute the insert; Push as a post-execute action when results are returned as a Promise.
        return context.execute()
            .then(function (results) {
                // Only do the push if configured
                if (context.push) {
                    context.push.apns.send(null, payload, function (error) {
                        if (error) {
                            logger.error('Error while sending push notification: ', error);
                        } else {
                            logger.info('Push notification sent successfully!');
                        }
                    });
                }
                return results;
            })
            .catch(function (error) {
                logger.error('Error while running context.execute: ', error);
            });
    });
    
    module.exports = table;
    
  3. 编辑本地计算机上的文件时,请重新发布服务器项目。

向应用添加推送通知

Objective-C

  1. QSAppDelegate.m 中,导入 iOS SDK 和 QSTodoService.h

    #import <MicrosoftAzureMobile/MicrosoftAzureMobile.h>
    #import "QSTodoService.h"
    
  2. QSAppDelegate.m 中的 didFinishLaunchingWithOptions 内,紧靠在 return YES; 的前面插入以下行:

    UIUserNotificationSettings* notificationSettings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound categories:nil];
    [[UIApplication sharedApplication] registerUserNotificationSettings:notificationSettings];
    [[UIApplication sharedApplication] registerForRemoteNotifications];
    
  3. 在“QSAppDelegate.m” 中,添加以下处理程序方法。 应用现已更新,可支持推送通知。

    // Registration with APNs is successful
    - (void)application:(UIApplication *)application
    didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
    
        QSTodoService *todoService = [QSTodoService defaultService];
        MSClient *client = todoService.client;
    
        [client.push registerDeviceToken:deviceToken completion:^(NSError *error) {
            if (error != nil) {
                NSLog(@"Error registering for notifications: %@", error);
            }
        }];
    }
    
    // Handle any failure to register
    - (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:
    (NSError *)error {
        NSLog(@"Failed to register for remote notifications: %@", error);
    }
    
    // Use userInfo in the payload to display an alert.
    - (void)application:(UIApplication *)application
            didReceiveRemoteNotification:(NSDictionary *)userInfo {
        NSLog(@"%@", userInfo);
    
        NSDictionary *apsPayload = userInfo[@"aps"];
        NSString *alertString = apsPayload[@"alert"];
    
        // Create alert with notification content.
        UIAlertController *alertController = [UIAlertController
                                        alertControllerWithTitle:@"Notification"
                                        message:alertString
                                        preferredStyle:UIAlertControllerStyleAlert];
    
        UIAlertAction *cancelAction = [UIAlertAction
                                        actionWithTitle:NSLocalizedString(@"Cancel", @"Cancel")
                                        style:UIAlertActionStyleCancel
                                        handler:^(UIAlertAction *action)
                                        {
                                            NSLog(@"Cancel");
                                        }];
    
        UIAlertAction *okAction = [UIAlertAction
                                    actionWithTitle:NSLocalizedString(@"OK", @"OK")
                                    style:UIAlertActionStyleDefault
                                    handler:^(UIAlertAction *action)
                                    {
                                        NSLog(@"OK");
                                    }];
    
        [alertController addAction:cancelAction];
        [alertController addAction:okAction];
    
        // Get current view controller.
        UIViewController *currentViewController = [[[[UIApplication sharedApplication] delegate] window] rootViewController];
        while (currentViewController.presentedViewController)
        {
            currentViewController = currentViewController.presentedViewController;
        }
    
        // Display alert.
        [currentViewController presentViewController:alertController animated:YES completion:nil];
    
    }
    

Swift

  1. 将文件“ClientManager.swift”与以下内容一起添加。 用 Azure 移动应用后端的 URL 替换 %AppUrl%

    class ClientManager {
        static let sharedClient = MSClient(applicationURLString: "%AppUrl%")
    }
    
  2. ToDoTableViewController.swift 中,用以下行替换用于初始化 MSClientlet client 行:

    let client = ClientManager.sharedClient
    
  3. AppDelegate.swift 中,如下所示替换 func application 的正文:

    func application(application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
        application.registerUserNotificationSettings(
            UIUserNotificationSettings(forTypes: [.Alert, .Badge, .Sound],
                categories: nil))
        application.registerForRemoteNotifications()
        return true
    }
    
  4. AppDelegate.swift 中,添加以下处理程序方法。 应用现已更新,可支持推送通知。

    func application(application: UIApplication,
        didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
        ClientManager.sharedClient.push?.registerDeviceToken(deviceToken) { error in
            print("Error registering for notifications: ", error?.description)
        }
    }
    
    func application(application: UIApplication,
        didFailToRegisterForRemoteNotificationsWithError error: NSError) {
        print("Failed to register for remote notifications: ", error.description)
    }
    
    func application(application: UIApplication,
        didReceiveRemoteNotification userInfo: [NSObject: AnyObject]) {
    
        print(userInfo)
    
        let apsNotification = userInfo["aps"] as? NSDictionary
        let apsString       = apsNotification?["alert"] as? String
    
        let alert = UIAlertController(title: "Alert", message: apsString, preferredStyle: .Alert)
        let okAction = UIAlertAction(title: "OK", style: .Default) { _ in
            print("OK")
        }
        let cancelAction = UIAlertAction(title: "Cancel", style: .Default) { _ in
            print("Cancel")
        }
    
        alert.addAction(okAction)
        alert.addAction(cancelAction)
    
        var currentViewController = self.window?.rootViewController
        while currentViewController?.presentedViewController != nil {
            currentViewController = currentViewController?.presentedViewController
        }
    
        currentViewController?.presentViewController(alert, animated: true) {}
    
    }
    

测试推送通知

  • 在 Xcode 中,按“运行”并在 iOS 设备上启动应用(请注意,无法在模拟器中执行推送)。 单击“确定”接受推送通知;此请求只会在首次运行应用时出现。
  • 在应用中,添加新项并单击“+”。
  • 检查是否已收到通知,并单击“确定”以取消通知 。 现在,已成功完成本教程。

更多