教程:使用 Azure 通知中心向 iOS 设备推送本地化通知Tutorial: Push localized notifications to iOS devices using Azure Notification Hubs

本教程介绍如何使用 Azure 通知中心的模板功能广播已按语言和设备本地化的突发新闻通知。This tutorial shows you how to use the templates feature of Azure Notification Hubs to broadcast breaking news notifications that have been localized by language and device. 在本教程中,从在使用通知中心发送突发新闻中创建的 iOS 应用开始操作。In this tutorial, you start with the iOS app created in Use Notification Hubs to send breaking news. 完成后,可注册感兴趣的突发新闻类别,指定要接收通知的语言并仅接收采用该语言的所选类别的推送通知。When complete, you can register for categories you are interested in, specify a language in which to receive the notifications, and receive only push notifications for the selected categories in that language.

此方案包含两个部分:There are two parts to this scenario:

  • iOS 应用程序允许客户端设备指定一种语言并订阅不同的突发新闻类别;iOS app allows client devices to specify a language, and to subscribe to different breaking news categories;
  • 后端使用 Azure 通知中心的“标记”和“模板”功能广播通知 。The back-end broadcasts the notifications, using the tag and template features of Azure Notification Hubs.

在本教程中,会执行以下步骤:In this tutorial, you take the following steps:

  • 更新应用用户界面Update the app user interface
  • 生成 iOS 应用Build the iOS app
  • 通过 .NET 控制台应用发送本地化模板通知Send localized template notifications from .NET console app
  • 通过设备发送本地化模板通知Send localized template notifications from the device

概述Overview

使用通知中心发送突发新闻中,构建了一个使用标记订阅不同新闻类别通知的应用。In Use Notification Hubs to send breaking news, you built an app that used tags to subscribe to notifications for different news categories. 但是,很多应用程序针对多个市场,需要本地化。Many apps, however, target multiple markets and require localization. 这意味着通知内容本身必须本地化且传递到正确的设备组。It means that the content of the notifications themselves have to be localized and delivered to the correct set of devices. 本教程介绍如何使用通知中心的“模板”功能轻松传递本地化突发新闻通知 。This tutorial shows you how to use the template feature of Notification Hubs to easily deliver localized breaking news notifications.

Note

发送本地化通知的一种方式是创建每个标签的多个版本。One way to send localized notifications is to create multiple versions of each tag. 例如,要支持英语、法语和汉语,需要对世界新闻使用三种不同的标签:“world_en”、“world_fr”和“world_ch”。For instance, to support English, French, and Mandarin, you would need three different tags for world news: "world_en", "world_fr", and "world_ch". 然后必须将本地化版本的世界新闻分别发送到这些标签。You would then have to send a localized version of the world news to each of these tags. 在本主题中,会使用模板来避免增生标签和发送多个消息的要求。In this topic, you use templates to avoid the proliferation of tags and the requirement of sending multiple messages.

模板是指定特定设备应如何接收通知的一种方法。Templates are a way to specify how a specific device should receive a notification. 模板通过引用作为应用程序后端所发消息的一部分的属性,指定确切的负载格式。The template specifies the exact payload format by referring to properties that are part of the message sent by your app back-end. 在此示例中,将发送包含所有支持语言的区域设置未知的消息:In your case, you send a locale-agnostic message containing all supported languages:

{
    "News_English": "...",
    "News_French": "...",
    "News_Mandarin": "..."
}

然后确保设备注册到引用正确属性的模板。Then you ensure that devices register with a template that refers to the correct property. 例如,要注册法语新闻的 iOS 应用会使用以下语法注册:For instance, an iOS app that wants to register for French news registers using the following syntax:

{
    aps: {
        alert: "$(News_French)"
    }
}

有关模板的详细信息,请参阅模板一文。For more information on templates, see Templates article.

先决条件Prerequisites

更新应用用户界面Update the app user interface

本部分会修改在使用通知中心发送突发新闻主题中创建的“突发新闻”应用,以便使用模板发送本地化突发新闻。In this section, you modify the Breaking News app that you created in the topic Use Notification Hubs to send breaking news to send localized breaking news using templates.

MainStoryboard_iPhone.storyboard 中,使用以下三种语言添加分段控件:英语、法语和国语。In your MainStoryboard_iPhone.storyboard, add a Segmented Control with the three languages: English, French, and Mandarin.

创建 iOS UI 情节提要

然后确保在 ViewController.h 中添加 IBOutlet,如下图所示:Then make sure to add an IBOutlet in your ViewController.h as shown in the following image:

为开关创建插座

生成 iOS 应用Build the iOS app

  1. Notification.h 中,添加 retrieveLocale 方法,并修改 store 和 subscribe 方法,如以下代码中所示:In your Notification.h, add the retrieveLocale method, and modify the store and subscribe methods as shown in the following code:

    - (void) storeCategoriesAndSubscribeWithLocale:(int) locale categories:(NSSet*) categories completion: (void (^)(NSError* error))completion;
    
    - (void) subscribeWithLocale:(int) locale categories:(NSSet*) categories completion:(void (^)(NSError *))completion;
    
    - (NSSet*) retrieveCategories;
    
    - (int) retrieveLocale;
    

    Notification.m 中,通过添加 locale 参数并将其存储在用户默认值中来修改 storeCategoriesAndSubscribe 方法:In your Notification.m, modify the storeCategoriesAndSubscribe method, by adding the locale parameter and storing it in the user defaults:

    - (void) storeCategoriesAndSubscribeWithLocale:(int) locale categories:(NSSet *)categories completion:(void (^)(NSError *))completion {
        NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
        [defaults setValue:[categories allObjects] forKey:@"BreakingNewsCategories"];
        [defaults setInteger:locale forKey:@"BreakingNewsLocale"];
        [defaults synchronize];
    
        [self subscribeWithLocale: locale categories:categories completion:completion];
    }
    

    然后修改 subscribe 方法以包括该区域设置:Then modify the subscribe method to include the locale:

    - (void) subscribeWithLocale: (int) locale categories:(NSSet *)categories completion:(void (^)(NSError *))completion{
        SBNotificationHub* hub = [[SBNotificationHub alloc] initWithConnectionString:@"<connection string>" notificationHubPath:@"<hub name>"];
    
        NSString* localeString;
        switch (locale) {
            case 0:
                localeString = @"English";
                break;
            case 1:
                localeString = @"French";
                break;
            case 2:
                localeString = @"Mandarin";
                break;
        }
    
        NSString* template = [NSString stringWithFormat:@"{\"aps\":{\"alert\":\"$(News_%@)\"},\"inAppMessage\":\"$(News_%@)\"}", localeString, localeString];
    
        [hub registerTemplateWithDeviceToken:self.deviceToken name:@"localizednewsTemplate" jsonBodyTemplate:template expiryTemplate:@"0" tags:categories completion:completion];
    }
    

    使用方法 registerTemplateWithDeviceToken,而不是 registerNativeWithDeviceTokenYou use the method registerTemplateWithDeviceToken, instead of registerNativeWithDeviceToken. 注册一个模板时,必须提供 json 模板并指定其名称(因为应用可能需要注册不同的模板)。When you register for a template, you have to provide the json template and also a name for the template (as the app might want to register different templates). 确保将类别注册为标记,因为要确保接收有关这些新闻的通知。Make sure to register your categories as tags, as you want to make sure to receive the notifications for those news.

    添加一个方法以从用户默认设置中检索区域设置:Add a method to retrieve the locale from the user default settings:

    - (int) retrieveLocale {
        NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
    
        int locale = [defaults integerForKey:@"BreakingNewsLocale"];
    
        return locale < 0?0:locale;
    }
    
  2. 现在,修改 Notifications 类,必须确保 ViewController 使用新的 UISegmentControlNow that you modified the Notifications class, you have to make sure that the ViewController makes use of the new UISegmentControl. viewDidLoad 方法中添加以下行,以确保显示当前选择的区域设置:Add the following line in the viewDidLoad method to make sure to show the locale that is currently selected:

    self.Locale.selectedSegmentIndex = [notifications retrieveLocale];
    

    然后,在 subscribe 方法中,将对 storeCategoriesAndSubscribe 的调用更改为以下代码:Then, in your subscribe method, change your call to the storeCategoriesAndSubscribe to the following code:

    [notifications storeCategoriesAndSubscribeWithLocale: self.Locale.selectedSegmentIndex categories:[NSSet setWithArray:categories] completion: ^(NSError* error) {
        if (!error) {
            UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Notification" message:
                                    @"Subscribed!" delegate:nil cancelButtonTitle:
                                    @"OK" otherButtonTitles:nil, nil];
            [alert show];
        } else {
            NSLog(@"Error subscribing: %@", error);
        }
    }];
    
  3. 最后,必须在 AppDelegate.m 中更新 didRegisterForRemoteNotificationsWithDeviceToken 方法,以便在应用启动时正确刷新注册信息。Finally, you have to update the didRegisterForRemoteNotificationsWithDeviceToken method in your AppDelegate.m, so that you can correctly refresh your registration when your app starts. 将对通知的 subscribe 方法的调用更改为以下代码:Change your call to the subscribe method of notifications with the following code:

    NSSet* categories = [self.notifications retrieveCategories];
    int locale = [self.notifications retrieveLocale];
    [self.notifications subscribeWithLocale: locale categories:categories completion:^(NSError* error) {
        if (error != nil) {
            NSLog(@"Error registering for notifications: %@", error);
        }
    }];
    

(可选)通过 .NET 控制台应用发送本地化模板通知(optional) Send localized template notifications from .NET console app

发送模板通知时,只需提供一组属性。When you send template notifications, you only need to provide a set of properties. 在此方案中,这组属性包含当前新闻的本地化版本。In this scenario, the set of properties contain the localized version of the current news.

{
    "News_English": "World News in English!",
    "News_French": "World News in French!",
    "News_Mandarin": "World News in Mandarin!"
}

使用 C# 控制台应用发送通知Send notifications using a C# console app

本部分演示如何使用控制台应用发送通知。This section shows how to send notifications using a console app. 代码向 Windows 应用商店和 iOS 设备广播通知。The code broadcasts notifications to both Windows Store and iOS devices. 使用以下代码修改前面创建的控制台应用中的 SendTemplateNotificationAsync 方法:Modify the SendTemplateNotificationAsync method in the console app you previously created with the following code:

private static async void SendTemplateNotificationAsync()
{
    // Define the notification hub.
    NotificationHubClient hub = 
        NotificationHubClient.CreateClientFromConnectionString(
            "<connection string with full access>", "<hub name>");

    // Sending the notification as a template notification. All template registrations that contain 
    // "messageParam" or "News_<local selected>" and the proper tags will receive the notifications. 
    // This includes APNS, WNS, and MPNS template registrations.
    Dictionary<string, string> templateParams = new Dictionary<string, string>();

    // Create an array of breaking news categories.
    var categories = new string[] { "World", "Politics", "Business", "Technology", "Science", "Sports"};
    var locales = new string[] { "English", "French", "Mandarin" };

    foreach (var category in categories)
    {
        templateParams["messageParam"] = "Breaking " + category + " News!";

        // Sending localized News for each tag too...
        foreach( var locale in locales)
        {
            string key = "News_" + locale;

            // Your real localized news content would go here.
            templateParams[key] = "Breaking " + category + " News in " + locale + "!";
        }

        await hub.SendTemplateNotificationAsync(templateParams, category);
    }
}

无论使用何种平台,SendTemplateNotificationAsync 方法都会将本地化新闻传送到所有设备 。The SendTemplateNotificationAsync method delivers the localized piece of news to all your devices, irrespective of the platform. 通知中心生成正确的本机有效负载并将其传送到已订阅特定标记的所有设备。Your notification hub builds and delivers the correct native payload to all the devices subscribed to a specific tag.

使用移动服务发送通知Sending notification with Mobile Services

在移动服务计划程序中,使用以下脚本:In your Mobile Services scheduler, use the following script:

var azure = require('azure');
var notificationHubService = azure.createNotificationHubService('<hub name>', '<connection string with full access>');
var notification = {
        "News_English": "World News in English!",
        "News_French": "World News in French!",
        "News_Mandarin", "World News in Mandarin!"
}
notificationHubService.send('World', notification, function(error) {
    if (!error) {
        console.warn("Notification successful");
    }
});

(可选)通过设备发送本地化的模板通知(optional) Send localized template notifications from the device

如果无权访问 Visual Studio,或者只是想要试一试直接从设备上的应用发送本地化的模板通知。If you don't have access to Visual Studio, or want to just test sending the localized template notifications directly from the app on the device. 那么,可将本地化模板参数添加到在前一教程中定义的 SendNotificationRESTAPI 方法。You can add the localized template parameters to the SendNotificationRESTAPI method you defined in the previous tutorial.

- (void)SendNotificationRESTAPI:(NSString*)categoryTag
{
    NSURLSession* session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration
                                defaultSessionConfiguration] delegate:nil delegateQueue:nil];

    NSString *json;

    // Construct the messages REST endpoint
    NSURL* url = [NSURL URLWithString:[NSString stringWithFormat:@"%@%@/messages/%@", HubEndpoint,
                                        HUBNAME, API_VERSION]];

    // Generated the token to be used in the authorization header.
    NSString* authorizationToken = [self generateSasToken:[url absoluteString]];

    //Create the request to add the template notification message to the hub
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    [request setHTTPMethod:@"POST"];

    // Add the category as a tag
    [request setValue:categoryTag forHTTPHeaderField:@"ServiceBusNotification-Tags"];

    // Template notification
    json = [NSString stringWithFormat:@"{\"messageParam\":\"Breaking %@ News : %@\","
            \"News_English\":\"Breaking %@ News in English : %@\","
            \"News_French\":\"Breaking %@ News in French : %@\","
            \"News_Mandarin\":\"Breaking %@ News in Mandarin : %@\","
            categoryTag, self.notificationMessage.text,
            categoryTag, self.notificationMessage.text,  // insert English localized news here
            categoryTag, self.notificationMessage.text,  // insert French localized news here
            categoryTag, self.notificationMessage.text]; // insert Mandarin localized news here

    // Signify template notification format
    [request setValue:@"template" forHTTPHeaderField:@"ServiceBusNotification-Format"];

    // JSON Content-Type
    [request setValue:@"application/json;charset=utf-8" forHTTPHeaderField:@"Content-Type"];

    //Authenticate the notification message POST request with the SaS token
    [request setValue:authorizationToken forHTTPHeaderField:@"Authorization"];

    //Add the notification message body
    [request setHTTPBody:[json dataUsingEncoding:NSUTF8StringEncoding]];

    // Send the REST request
    NSURLSessionDataTask* dataTask = [session dataTaskWithRequest:request
                completionHandler:^(NSData *data, NSURLResponse *response, NSError *error)
        {
        NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*) response;
            if (error || httpResponse.statusCode != 200)
            {
                NSLog(@"\nError status: %d\nError: %@", httpResponse.statusCode, error);
            }
            if (data != NULL)
            {
                //xmlParser = [[NSXMLParser alloc] initWithData:data];
                //[xmlParser setDelegate:self];
                //[xmlParser parse];
            }
        }];

    [dataTask resume];
}

后续步骤Next steps

在本教程中,会向 iOS 设备发送本地化通知。In this tutorial, you sent localized notifications to iOS devices. 若要了解如何向特定的 iOS 应用用户推送通知,请转到以下教程:To learn how to push notifications to specific users of iOS apps, advance to the following tutorial:

[使用通知中心通知用户:ASP.NET]: notification-hubs-aspnet-backend-ios-apple-apns-notification.md [使用通知中心通知用户:移动服务]: notification-hubs-aspnet-backend-windows-dotnet-wns-notification.md [Notify users with Notification Hubs: ASP.NET]: notification-hubs-aspnet-backend-ios-apple-apns-notification.md [Notify users with Notification Hubs: Mobile Services]: notification-hubs-aspnet-backend-windows-dotnet-wns-notification.md

[wns 对象]: https://go.microsoft.com/fwlink/p/?LinkId=260591 [通知中心指南]: https://msdn.microsoft.com/library/jj927170.aspx [适用于 iOS 的通知中心操作指南]: https://msdn.microsoft.com/library/jj927168.aspx [wns object]: https://go.microsoft.com/fwlink/p/?LinkId=260591 [Notification Hubs Guidance]: https://msdn.microsoft.com/library/jj927170.aspx [Notification Hubs How-To for iOS]: https://msdn.microsoft.com/library/jj927168.aspx