教學課程:使用 Azure 通知中樞將通知推播至特定 iOS 裝置Tutorial: Push notifications to specific iOS devices using Azure Notification Hubs

總覽Overview

本教學課程說明如何使用 Azure 通知中樞將即時新聞通知廣播至 iOS 應用程式。This tutorial shows you how to use Azure Notification Hubs to broadcast breaking news notifications to an iOS app. 完成時,您將能夠註冊自己所感興趣的即時新聞類別,並僅接收那些類別的推播通知。When complete, you are able to register for breaking news categories you are interested in, and receive only push notifications for those categories. 此情況為適用於許多應用程式的常見模式,其中必須將通知傳送給先前宣告對該通知感興趣的使用者群組,例如 RSS 閱讀程式、供樂迷使用的應用程式等等。This scenario is a common pattern for many apps where notifications have to be sent to groups of users that have previously declared interest in them, for example, RSS reader, apps for music fans, etc.

在通知中樞內建立註冊時,您可以透過包含一或多個 tags 來啟用廣播案例。Broadcast scenarios are enabled by including one or more tags when creating a registration in the notification hub. 當通知傳送至標記時,已註冊該標記的裝置都會收到該通知。When notifications are sent to a tag, devices that have registered for the tag receive the notification. 由於標籤只是簡單的字串而已,您無需預先佈建標籤。Because tags are simply strings, they do not have to be provisioned in advance. 如需標記的詳細資訊,請參閱通知中樞路由與標記運算式For more information about tags, see Notification Hubs Routing and Tag Expressions.

在本教學課程中,您會執行下列步驟:In this tutorial, you take the following steps:

  • 在應用程式中新增類別選項Add a category selection to the app
  • 傳送加註標記的通知Send tagged notifications
  • 從裝置傳送通知Send notifications from the device
  • 執行應用程式並產生通知Run the app and generate notifications

必要條件Prerequisites

本主題以您在以下教學課程中建立的應用程式為基礎:教學課程:使用 Azure 通知中樞將通知推送至 iOS 應用程式。This topic builds on the app you created in Tutorial: Push notifications to iOS apps using Azure Notification Hubs. 開始本教學課程之前,您必須已完成教學課程:使用 Azure 通知中樞將通知推送至 iOS 應用程式。Before starting this tutorial, you must have already completed Tutorial: Push notifications to iOS apps using Azure Notification Hubs.

在應用程式中新增類別選項Add category selection to the app

第一個步驟是在您現有的腳本上新增 UI 元素,以便使用者選取要註冊的類別。The first step is to add the UI elements to your existing storyboard that enable the user to select categories to register. 使用者所選取的類別會儲存在裝置上。The categories selected by a user are stored on the device. 啟動應用程式時,您的通知中心內會建立以所選取類別作為標籤的裝置註冊。When the app starts, a device registration is created in your notification hub with the selected categories as tags.

  1. 在您的 MainStoryboard_iPhone.storyboard 中,從物件程式庫新增下列元件:In your MainStoryboard_iPhone.storyboard add the following components from the object library:

    • 具有「即時新聞」文字的標籤,A label with "Breaking News" text,

    • 具有「世界」、「政治」、「商業」、「技術」、「科學」、「體育」等類別文字的標籤,Labels with category texts "World", "Politics", "Business", "Technology", "Science", "Sports",

    • 六個參數 (一個類別一個),預設會將每個參數 [狀態] 設為 [關閉]。Six switches, one per category, set each switch State to be Off by default.

    • 一個標示為「訂閱」的按鈕One button labeled "Subscribe"

      您的腳本應如下所示:Your storyboard should look as follows:

      Xcode 介面產生器

  2. 在輔助編輯器中,建立所有參數的出口,並將其命名為 "WorldSwitch"、"PoliticsSwitch"、"BusinessSwitch"、"TechnologySwitch"、"ScienceSwitch"、"SportsSwitch"In the assistant editor, create outlets for all the switches and call them "WorldSwitch", "PoliticsSwitch", "BusinessSwitch", "TechnologySwitch", "ScienceSwitch", "SportsSwitch"

  3. 為按鈕建立名為 subscribe 的動作;您的 ViewController.h 應包含下列程式碼:Create an Action for your button called subscribe; your ViewController.h should contain the following code:

    @property (weak, nonatomic) IBOutlet UISwitch *WorldSwitch;
    @property (weak, nonatomic) IBOutlet UISwitch *PoliticsSwitch;
    @property (weak, nonatomic) IBOutlet UISwitch *BusinessSwitch;
    @property (weak, nonatomic) IBOutlet UISwitch *TechnologySwitch;
    @property (weak, nonatomic) IBOutlet UISwitch *ScienceSwitch;
    @property (weak, nonatomic) IBOutlet UISwitch *SportsSwitch;
    
    - (IBAction)subscribe:(id)sender;
    
  4. 建立稱為 Notifications 的新 Cocoa Touch 類別Create a new Cocoa Touch Class called Notifications. 在 Notifications.h 的介面區段中複製下列程式碼:Copy the following code in the interface section of the file Notifications.h:

    @property NSData* deviceToken;
    
    - (id)initWithConnectionString:(NSString*)listenConnectionString HubName:(NSString*)hubName;
    
    - (void)storeCategoriesAndSubscribeWithCategories:(NSArray*)categories
                completion:(void (^)(NSError* error))completion;
    
    - (NSSet*)retrieveCategories;
    
    - (void)subscribeWithCategories:(NSSet*)categories completion:(void (^)(NSError *))completion;
    
  5. 在 Notifications.m 中新增下列 import 指示詞:Add the following import directive to Notifications.m:

    #import <WindowsAzureMessaging/WindowsAzureMessaging.h>
    
  6. 複製 Notifications.m 檔案實作區段中的下列程式碼:Copy the following code in the implementation section of the file Notifications.m.

    SBNotificationHub* hub;
    
    - (id)initWithConnectionString:(NSString*)listenConnectionString HubName:(NSString*)hubName{
    
        hub = [[SBNotificationHub alloc] initWithConnectionString:listenConnectionString
                                    notificationHubPath:hubName];
    
        return self;
    }
    
    - (void)storeCategoriesAndSubscribeWithCategories:(NSSet *)categories completion:(void (^)(NSError *))completion {
        NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
        [defaults setValue:[categories allObjects] forKey:@"BreakingNewsCategories"];
    
        [self subscribeWithCategories:categories completion:completion];
    }
    
    - (NSSet*)retrieveCategories {
        NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
    
        NSArray* categories = [defaults stringArrayForKey:@"BreakingNewsCategories"];
    
        if (!categories) return [[NSSet alloc] init];
        return [[NSSet alloc] initWithArray:categories];
    }
    
    - (void)subscribeWithCategories:(NSSet *)categories completion:(void (^)(NSError *))completion
    {
        //[hub registerNativeWithDeviceToken:self.deviceToken tags:categories completion: completion];
    
        NSString* templateBodyAPNS = @"{\"aps\":{\"alert\":\"$(messageParam)\"}}";
    
        [hub registerTemplateWithDeviceToken:self.deviceToken name:@"simpleAPNSTemplate" 
            jsonBodyTemplate:templateBodyAPNS expiryTemplate:@"0" tags:categories completion:completion];
    }
    

    此類別會使用本機儲存體來儲存和擷取此裝置接收到的新聞類別。This class uses local storage to store and retrieve the categories of news that this device receives. 此外,它也包含使用 範本 註冊來註冊這些類別的方法。Also, it contains a method to register for these categories using a Template registration.

  7. AppDelegate.h 檔案中,新增 Notifications.h 的匯入陳述式,並新增 Notifications 類別執行個體的屬性:In the AppDelegate.h file, add an import statement for Notifications.h and add a property for an instance of the Notifications class:

    #import "Notifications.h"
    
    @property (nonatomic) Notifications* notifications;
    
  8. AppDelegate.mdidFinishLaunchingWithOptions 方法中,於方法的開頭處加入程式碼來初始化通知執行個體。In the didFinishLaunchingWithOptions method in AppDelegate.m, add the code to initialize the notifications instance at the beginning of the method.
    HUBNAMEHUBLISTENACCESS (定義於 hubinfo.h 中) 的 <hub name><connection string with listen access> 預留位置,應已用稍早取得的 DefaultListenSharedAccessSignature 的通知中樞名稱與連接字串所取代HUBNAME and HUBLISTENACCESS (defined in hubinfo.h) should already have the <hub name> and <connection string with listen access> placeholders replaced with your notification hub name and the connection string for DefaultListenSharedAccessSignature that you obtained earlier

    self.notifications = [[Notifications alloc] initWithConnectionString:HUBLISTENACCESS HubName:HUBNAME];
    

    注意

    因為隨用戶端應用程式散佈的憑證通常不安全,您應只將接聽存取權的金鑰隨用戶端應用程式散佈。Because credentials that are distributed with a client app are not generally secure, you should only distribute the key for listen access with your client app. 您的應用程式可透過接聽存取權來註冊通知,但無法修改現有的註冊或無法傳送通知。Listen access enables your app to register for notifications, but existing registrations cannot be modified and notifications cannot be sent. 在安全的後端服務中,會使用完整存取金鑰來傳送通知和變更現有的註冊。The full access key is used in a secured backend service for sending notifications and changing existing registrations.

  9. AppDelegate.mdidRegisterForRemoteNotificationsWithDeviceToken 方法中,使用下列程式碼來取代方法中的程式碼,以將裝置權杖傳遞給 notifications 類別。In the didRegisterForRemoteNotificationsWithDeviceToken method in AppDelegate.m, replace the code in the method with the following code to pass the device token to the notifications class. notifications 類別會為通知執行與類別之間的註冊。The notifications class performs the registering for notifications with the categories. 如果使用者變更類別選取項目,則可以呼叫 subscribeWithCategories 方法以回應 [subscribe] (訂閱) 按鈕來更新它們。If the user changes category selections, call the subscribeWithCategories method in response to the subscribe button to update them.

    注意

    由於 Apple 推播通知服務 (APNS) 所指派的裝置權杖可能隨時會變更,因此您應經常註冊通知以避免通知失敗。Because the device token assigned by the Apple Push Notification Service (APNS) can chance at any time, you should register for notifications frequently to avoid notification failures. 此範例會在應用程式每次啟動時註冊通知。This example registers for notification every time that the app starts. 若是經常執行 (一天多次) 的應用程式,如果距離上次註冊的時間不到一天,則您可能可以略過註冊以保留頻寬。For apps that are run frequently, more than once a day, you can probably skip registration to preserve bandwidth if less than a day has passed since the previous registration.

    self.notifications.deviceToken = deviceToken;
    
    // Retrieves the categories from local storage and requests a registration for these categories
    // each time the app starts and performs a registration.
    
    NSSet* categories = [self.notifications retrieveCategories];
    [self.notifications subscribeWithCategories:categories completion:^(NSError* error) {
        if (error != nil) {
            NSLog(@"Error registering for notifications: %@", error);
        }
    }];
    

    此時,didRegisterForRemoteNotificationsWithDeviceToken 方法中不應有任何其他程式碼。At this point, there should be no other code in the didRegisterForRemoteNotificationsWithDeviceToken method.

  10. 完成開始使用通知中樞教學課程之前, AppDelegate.m下列方法應該已出現在中。The following methods should already be present in AppDelegate.m from completing the Get started with Notification Hubs tutorial. 否則,請予以新增。If not, add them.

    - (void)MessageBox:(NSString *)title message:(NSString *)messageText
    {
    
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title message:messageText delegate:self
            cancelButtonTitle:@"OK" otherButtonTitles: nil];
        [alert show];
    }
    
    - (void)application:(UIApplication *)application didReceiveRemoteNotification:
       (NSDictionary *)userInfo {
       NSLog(@"%@", userInfo);
       [self MessageBox:@"Notification" message:[[userInfo objectForKey:@"aps"] valueForKey:@"alert"]];
     }
    

    此方法會顯示簡易 UIAlert,以處理應用程式執行時接收到的通知。This method handles notifications received when the app is running by displaying a simple UIAlert.

  11. ViewController.m 中,新增 AppDelegate.himport 陳述式,並將下列程式碼複製到 XCode 所產生的 subscribe 方法中。In ViewController.m, add an import statement for AppDelegate.h and copy the following code into the XCode-generated subscribe method. 此程式碼會更新通知註冊,以使用使用者在使用者介面中所選擇的新類別標記。This code updates the notification registration to use the new category tags the user has chosen in the user interface.

    #import "Notifications.h"
    
    NSMutableArray* categories = [[NSMutableArray alloc] init];
    
    if (self.WorldSwitch.isOn) [categories addObject:@"World"];
    if (self.PoliticsSwitch.isOn) [categories addObject:@"Politics"];
    if (self.BusinessSwitch.isOn) [categories addObject:@"Business"];
    if (self.TechnologySwitch.isOn) [categories addObject:@"Technology"];
    if (self.ScienceSwitch.isOn) [categories addObject:@"Science"];
    if (self.SportsSwitch.isOn) [categories addObject:@"Sports"];
    
    Notifications* notifications = [(AppDelegate*)[[UIApplication sharedApplication]delegate] notifications];
    
    [notifications storeCategoriesAndSubscribeWithCategories:categories completion: ^(NSError* error) {
        if (!error) {
            UIAlertView *alert = [[UIAlertView alloc] initWithTitle:"Notification" message:"Subscribed" delegate:self
            cancelButtonTitle:@"OK" otherButtonTitles: nil];
            [alert show];
        } else {
            NSLog(@"Error subscribing: %@", error);
        }
    }];
    

    此方法會建立類別的 NSMutableArray,並使用 Notifications 類別在本機儲存體中儲存清單,並在通知中心註冊對應標記。This method creates an NSMutableArray of categories and uses the Notifications class to store the list in the local storage and registers the corresponding tags with your notification hub. 變更類別時,系統會使用新類別重新建立註冊。When categories are changed, the registration is recreated with the new categories.

  12. ViewController.m 中,於 viewDidLoad 方法中新增下列程式碼,以根據先前儲存的類別來設定使用者介面。In ViewController.m, add the following code in the viewDidLoad method to set the user interface based on the previously saved categories.

    // This updates the UI on startup based on the status of previously saved categories.
    
    Notifications* notifications = [(AppDelegate*)[[UIApplication sharedApplication]delegate] notifications];
    
    NSSet* categories = [notifications retrieveCategories];
    
    if ([categories containsObject:@"World"]) self.WorldSwitch.on = true;
    if ([categories containsObject:@"Politics"]) self.PoliticsSwitch.on = true;
    if ([categories containsObject:@"Business"]) self.BusinessSwitch.on = true;
    if ([categories containsObject:@"Technology"]) self.TechnologySwitch.on = true;
    if ([categories containsObject:@"Science"]) self.ScienceSwitch.on = true;
    if ([categories containsObject:@"Sports"]) self.SportsSwitch.on = true;
    

應用程式現在可以在裝置本機儲存體中儲存一組類別,以用來在每次應用程式啟動時於通知中樞註冊。The app can now store a set of categories in the device local storage used to register with the notification hub whenever the app starts. 使用者可以在執行階段變更選取的類別,然後按一下 subscribe 方法來更新裝置的註冊。The user can change the selection of categories at runtime and click the subscribe method to update the registration for the device. 接下來,您會更新應用程式,以直接在應用程式本身傳送即時新聞通知。Next, you update the app to send the breaking news notifications directly in the app itself.

(選擇性) 傳送加註標記的通知(optional) Send tagged notifications

如果您無法存取 Visual Studio,可以跳到下一節,並從應用程式本身傳送通知。If you don't have access to Visual Studio, you can skip to the next section and send notifications from the app itself. 您也可以使用通知中樞的 [偵錯] 索引標籤,從 Azure 入口網站 傳送正確的範本通知。You can also send the proper template notification from the Azure portal using the debug tab for your notification hub.

在本節中,您會從 .NET 主控台應用程式將即時新聞以加註標記的範本通知形式傳送。In this section, you send breaking news as tagged template notifications from a .NET console app.

  1. 在 Visual Studio 中,建立新的 Visual C# 主控台應用程式:In Visual Studio, create a new Visual C# console application:

    1. 在主功能表上,選取 [檔案] > [新增] > [專案] 。On the menu, select File > New > Project.
    2. 在 [建立新專案] 中,針對 C# 在範本清單中選取 [主控台應用程式 (.NET Framework)] ,接著選取 [下一步] 。In Create a new project, select Console App (.NET Framework) for C# in the list of templates, and select Next.
    3. 輸入應用程式的名稱。Enter a name for the app.
    4. 在 [解決方案] 中,選擇 [新增到解決方案] ,再選取 [建立] 以建立專案。For Solution, choose Add to solution, and select Create to create the project.
  2. 選取 [工具] > [NuGet 套件管理員] > [套件管理員主控台] ,然後在主控台視窗中執行下列命令:Select Tools > NuGet Package Manager > Package Manager Console and then, in the console window, run the following command:

    Install-Package Microsoft.Azure.NotificationHubs
    

    此動作會使用 Microsoft.Azure.NotificationHubs 套件來新增對 Azure 通知中樞 SDK 的參考。This action adds a reference to the Azure Notification Hubs SDK by using the Microsoft.Azure.NotificationHubs package.

  3. 開啟 Program.cs 檔案,並新增下列 using 陳述式:Open the Program.cs file, and add the following using statement:

    using Microsoft.Azure.NotificationHubs;
    
  4. Program 類別中,新增或取代 (如果方法已存在) 下列方法:In the Program class, add the following method, or replace it if it already exists:

    private static async void SendTemplateNotificationAsync()
    {
        // Define the notification hub.
        NotificationHubClient hub = NotificationHubClient.CreateClientFromConnectionString("<connection string with full access>", "<hub name>");
    
        // Create an array of breaking news categories.
        var categories = new string[] { "World", "Politics", "Business", "Technology", "Science", "Sports"};
    
        // Send the notification as a template notification. All template registrations that contain
        // "messageParam" and the proper tags will receive the notifications.
        // This includes APNS, GCM, WNS, and MPNS template registrations.
    
        Dictionary<string, string> templateParams = new Dictionary<string, string>();
    
        foreach (var category in categories)
        {
            templateParams["messageParam"] = "Breaking " + category + " News!";
            await hub.SendTemplateNotificationAsync(templateParams, category);
        }
    }
    

    此程式碼會分別將範本通知傳送給字串陣列中的六個標籤。This code sends a template notification for each of the six tags in the string array. 使用標籤可確保裝置只會收到已登錄類別的通知。The use of tags ensures that devices receive notifications only for the registered categories.

  5. 在上述程式碼中,請使用您的通知中樞名稱及通知中樞儀表板的 DefaultFullSharedAccessSignature 連接字串,來取代 <hub name><connection string with full access> 預留位置。In the preceding code, replace the <hub name> and <connection string with full access> placeholders with your notification hub name and the connection string for DefaultFullSharedAccessSignature from the dashboard of your notification hub.

  6. Main() 方法中新增下列程式碼行:In the Main() method, add the following lines:

     SendTemplateNotificationAsync();
     Console.ReadLine();
    
  7. 建置主控台應用程式。Build the console app.

(選擇性) 從裝置傳送通知(optional) Send notifications from the device

通知通常會由後端服務傳送,但您可直接從應用程式傳送即時新聞通知。Normally notifications would be sent by a backend service but, you can send breaking news notifications directly from the app. 若要這麼做,請更新SendNotificationRESTAPI您在開始使用通知中樞教學課程中所定義的方法。To do so, you update the SendNotificationRESTAPI method that you defined in the Get started with Notification Hubs tutorial.

  1. ViewController.m 中,以下列方式更新 SendNotificationRESTAPI 方法,使其接受參數作為類別標記,並會傳送正確的範本通知。In ViewController.m, update the SendNotificationRESTAPI method as follows so that it accepts a parameter for the category tag and sends the proper template notification.

    - (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 : %@\"}",
                categoryTag, self.notificationMessage.text];
    
        // 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];
    }
    
  2. ViewController.m 中更新 Send Notification 動作,如下列程式碼所示。In ViewController.m, update the Send Notification action as shown in the code that follows. 這會使它個別使用每個標記來傳送通知,並傳送至多個平台。So that it sends the notifications using each tag individually and sends to multiple platforms.

    - (IBAction)SendNotificationMessage:(id)sender
    {
        self.sendResults.text = @"";
    
        NSArray* categories = [NSArray arrayWithObjects: @"World", @"Politics", @"Business",
                                @"Technology", @"Science", @"Sports", nil];
    
        // Lets send the message as breaking news for each category to WNS, FCM, and APNS
        // using a template.
        for(NSString* category in categories)
        {
            [self SendNotificationRESTAPI:category];
        }
    }
    
  3. 重新建置專案,並確定您沒有建置錯誤。Rebuild your project and make sure you have no build errors.

執行應用程式並產生通知Run the app and generate notifications

  1. 按 [執行] 按鈕,以建置專案並啟動應用程式。Press the Run button to build the project and start the app. 選取要訂閱的一些即時新聞選項,然後按 [訂閱] 按鈕。Select some breaking news options to subscribe to and then press the Subscribe button. 您應該會看到一個對話方塊,表示已訂閱通知。You should see a dialog indicating the notifications have been subscribed to.

    iOS 上的範例通知

    當您選擇 [訂閱]時,應用程式會將選取的類別轉換成標籤,並在通知中心內為選取的標籤要求新裝置註冊。When you choose Subscribe, the app converts the selected categories into tags and requests a new device registration for the selected tags from the notification hub.

  2. 輸入要以即時新聞形式傳送的訊息,然後按下 [傳送通知] 按鈕。Enter a message to be sent as breaking news then press the Send Notification button. 或者,執行.NET 主控台應用程式來產生通知。Alternatively, run the .NET console app to generate notifications.

    在 iOS 中變更通知喜好設定

  3. 每個訂閱即時新聞的裝置都會收到您剛剛傳送的即時新聞通知。Each device subscribed to breaking news receives the breaking news notifications you just sent.

後續步驟Next steps

在本教學課程中,您已將廣播通知傳送至註冊相關類別的特定 iOS 裝置。In this tutorial, you sent broadcast notifications to specific iOS devices that have registered for the categories. 若要了解如何推送當地語系化的通知,請繼續進行下列教學課程:To learn how to push localized notifications, advance to the following tutorial: