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

本教學課程說明如何使用 Azure 通知中樞將推播通知傳送至特定 Windows Phone 8 或 Windows Phone 8.1 裝置。This tutorial shows you how to use Azure Notification Hubs to send push notifications to specific Windows Phone 8 or Windows Phone 8.1 devices. 如果您的目標是 Windows Phone 8.1 (非 Silverlight),請參閱本教學課程的 Windows 通用版本。If you are targeting Windows Phone 8.1 (non-Silverlight), see the Windows Universal version of this tutorial.

您可以透過在通知中樞內建立註冊時包含一或多個標記,來啟用此案例。You enable this scenario by including one or more tags when creating a registration in the notification hub. 當標籤收到通知時,所有已註冊此標籤的裝置都會收到通知。When notifications are sent to a tag, all devices that have registered for the tag receive the notification. 如需標記的詳細資訊,請參閱註冊中的標記For more information about tags, see Tags in registrations.

注意

通知中樞 Windows Phone SDK 不支援將 Windows 推播通知服務 (WNS) 與 Windows Phone 8.1 Silverlight app 搭配使用。The Notification Hubs Windows Phone SDK does not support using the Windows Push Notification Service (WNS) with Windows Phone 8.1 Silverlight apps. 若要將 WNS (而非 MPNS) 與 Windows Phone 8.1 Silverlight 應用程式搭配使用,請遵循使用 REST API 的 [通知中樞 - Windows Phone Silverlight 教學課程]。To use WNS (instead of MPNS) with Windows Phone 8.1 Silverlight apps, follow the [Notification Hubs - Windows Phone Silverlight tutorial], which uses REST APIs.

在本教學課程中,您會了解如何:In this tutorial, you learn how to:

  • 在行動應用程式中新增類別選項Add category selection to the mobile app
  • 註冊附有標記的通知Register for notifications with tags
  • 傳送加註標記的通知Send tagged notifications
  • 測試應用程式Test the app

必要條件Prerequisites

在開始進行本教學課程之前,請先完成教學課程:使用 Azure 通知中樞將通知推送至 Windows Phone 應用程式Complete the Tutorial: Push notifications to Windows Phone apps by using Azure Notification Hubs. 在本教學課程中,您會更新行動應用程式,以便能夠註冊您所感興趣的即時新聞類別,並僅接收這些類別的推播通知。In this tutorial, you update the mobile application so that you can register for breaking news categories you are interested in, and receive only push notifications for those categories.

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

第一個步驟是在您的現有主頁面上新增 UI 元素,以便使用者選取要註冊的類別。The first step is to add the UI elements to your existing main page 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. 開啟 MainPage.xaml 檔案,然後使用下列程式碼來取代名為 TitlePanelContentPanelGrid 元素:Open the MainPage.xaml file, then replace the Grid elements named TitlePanel and ContentPanel with the following code:

    <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
        <TextBlock Text="Breaking News" Style="{StaticResource PhoneTextNormalStyle}" Margin="12,0"/>
        <TextBlock Text="Categories" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
    </StackPanel>
    
    <Grid Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
        <Grid.RowDefinitions>
            <RowDefinition Height="auto"/>
            <RowDefinition Height="auto" />
            <RowDefinition Height="auto" />
            <RowDefinition Height="auto" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <CheckBox Name="WorldCheckBox" Grid.Row="0" Grid.Column="0">World</CheckBox>
        <CheckBox Name="PoliticsCheckBox" Grid.Row="1" Grid.Column="0">Politics</CheckBox>
        <CheckBox Name="BusinessCheckBox" Grid.Row="2" Grid.Column="0">Business</CheckBox>
        <CheckBox Name="TechnologyCheckBox" Grid.Row="0" Grid.Column="1">Technology</CheckBox>
        <CheckBox Name="ScienceCheckBox" Grid.Row="1" Grid.Column="1">Science</CheckBox>
        <CheckBox Name="SportsCheckBox" Grid.Row="2" Grid.Column="1">Sports</CheckBox>
        <Button Name="SubscribeButton" Content="Subscribe" HorizontalAlignment="Center" Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2" Click="SubscribeButton_Click" />
    </Grid>
    
  2. 將名為 Notifications 的類別新增至專案。Add a class named Notifications to the project. public 修飾詞新增至類別定義。Add the public modifier to the class definition. 然後,將下列 using 陳述式新增到新檔案:Then, add the following using statements to the new file:

    using Microsoft.Phone.Notification;
    using Microsoft.WindowsAzure.Messaging;
    using System.IO.IsolatedStorage;
    using System.Windows;
    
  3. 將下列程式碼複製到新的 Notifications 類別中:Copy the following code into the new Notifications class:

    private NotificationHub hub;
    
    // Registration task to complete registration in the ChannelUriUpdated event handler
    private TaskCompletionSource<Registration> registrationTask;
    
    public Notifications(string hubName, string listenConnectionString)
    {
        hub = new NotificationHub(hubName, listenConnectionString);
    }
    
    public IEnumerable<string> RetrieveCategories()
    {
        var categories = (string)IsolatedStorageSettings.ApplicationSettings["categories"];
        return categories != null ? categories.Split(',') : new string[0];
    }
    
    public async Task<Registration> StoreCategoriesAndSubscribe(IEnumerable<string> categories)
    {
        var categoriesAsString = string.Join(",", categories);
        var settings = IsolatedStorageSettings.ApplicationSettings;
        if (!settings.Contains("categories"))
        {
            settings.Add("categories", categoriesAsString);
        }
        else
        {
            settings["categories"] = categoriesAsString;
        }
        settings.Save();
    
        return await SubscribeToCategories();
    }
    
    public async Task<Registration> SubscribeToCategories()
    {
        registrationTask = new TaskCompletionSource<Registration>();
    
        var channel = HttpNotificationChannel.Find("MyPushChannel");
    
        if (channel == null)
        {
            channel = new HttpNotificationChannel("MyPushChannel");
            channel.Open();
            channel.BindToShellToast();
            channel.ChannelUriUpdated += channel_ChannelUriUpdated;
    
            // This is optional, used to receive notifications while the app is running.
            channel.ShellToastNotificationReceived += channel_ShellToastNotificationReceived;
        }
    
        // If channel.ChannelUri is not null, complete the registrationTask here.  
        // If it is null, the registrationTask will be completed in the ChannelUriUpdated event handler.
        if (channel.ChannelUri != null)
        {
            await RegisterTemplate(channel.ChannelUri);
        }
    
        return await registrationTask.Task;
    }
    
    async void channel_ChannelUriUpdated(object sender, NotificationChannelUriEventArgs e)
    {
        await RegisterTemplate(e.ChannelUri);
    }
    
    async Task<Registration> RegisterTemplate(Uri channelUri)
    {
        // Using a template registration to support notifications across platforms.
        // Any template notifications that contain messageParam and a corresponding tag expression
        // will be delivered for this registration.
    
        const string templateBodyMPNS = "<wp:Notification xmlns:wp=\"WPNotification\">" +
                                            "<wp:Toast>" +
                                                "<wp:Text1>$(messageParam)</wp:Text1>" +
                                            "</wp:Toast>" +
                                        "</wp:Notification>";
    
        // The stored categories tags are passed with the template registration.
    
        registrationTask.SetResult(await hub.RegisterTemplateAsync(channelUri.ToString(),
            templateBodyMPNS, "simpleMPNSTemplateExample", this.RetrieveCategories()));
    
        return await registrationTask.Task;
    }
    
    // This is optional. It is used to receive notifications while the app is running.
    void channel_ShellToastNotificationReceived(object sender, NotificationEventArgs e)
    {
        StringBuilder message = new StringBuilder();
        string relativeUri = string.Empty;
    
        message.AppendFormat("Received Toast {0}:\n", DateTime.Now.ToShortTimeString());
    
        // Parse out the information that was part of the message.
        foreach (string key in e.Collection.Keys)
        {
            message.AppendFormat("{0}: {1}\n", key, e.Collection[key]);
    
            if (string.Compare(
                key,
                "wp:Param",
                System.Globalization.CultureInfo.InvariantCulture,
                System.Globalization.CompareOptions.IgnoreCase) == 0)
            {
                relativeUri = e.Collection[key];
            }
        }
    
        // Display a dialog of all the fields in the toast.
        System.Windows.Deployment.Current.Dispatcher.BeginInvoke(() =>
        {
            MessageBox.Show(message.ToString());
        });
    }
    

    本類別使用獨立儲存體,來儲存此裝置接收的新聞類別。This class uses the isolated storage to store the categories of news that this device is to receive. 它也包含使用 範本 通知來註冊這些類別的方法。It also contains methods to register for these categories using a template notification registration.

  4. App.xaml.cs 專案檔案中,新增下列屬性至 App 類別。In the App.xaml.cs project file, add the following property to the App class. 以您的通知中樞名稱與先前取得的 DefaultListenSharedAccessSignature 連接字串,取代 <hub name><connection string with listen access> 預留位置。Replace the <hub name> and <connection string with listen access> placeholders with your notification hub name and the connection string for DefaultListenSharedAccessSignature that you obtained earlier.

    public Notifications notifications = new Notifications("<hub name>", "<connection string with listen access>");
    

    注意

    因為隨用戶端應用程式散佈的憑證通常不安全,您應只將接聽存取權的金鑰隨用戶端應用程式散佈。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.

  5. MainPage.xaml.cs 中新增以下這一行:In the MainPage.xaml.cs, add the following line:

    using Windows.UI.Popups;
    
  6. 在 MainPage.xaml.cs 專案檔案中新增下列方法:In the MainPage.xaml.cs project file, add the following method:

    private async void SubscribeButton_Click(object sender, RoutedEventArgs e)
    {
        var categories = new HashSet<string>();
        if (WorldCheckBox.IsChecked == true) categories.Add("World");
        if (PoliticsCheckBox.IsChecked == true) categories.Add("Politics");
        if (BusinessCheckBox.IsChecked == true) categories.Add("Business");
        if (TechnologyCheckBox.IsChecked == true) categories.Add("Technology");
        if (ScienceCheckBox.IsChecked == true) categories.Add("Science");
        if (SportsCheckBox.IsChecked == true) categories.Add("Sports");
    
        var result = await ((App)Application.Current).notifications.StoreCategoriesAndSubscribe(categories);
    
        MessageBox.Show("Subscribed to: " + string.Join(",", categories) + " on registration id : " +
            result.RegistrationId);
    }
    

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

您的應用程式現在可以在裝置上的本機儲存體中儲存一組類別,並在使用者每次變更類別選項時在通知中心註冊。Your app is now able to store a set of categories in local storage on the device and register with the notification hub whenever the user changes the selection of categories.

註冊通知Register for notifications

這些步驟會在啟動時,使用已儲存在本機儲存體中的類別在通知中心註冊。These steps register with the notification hub on startup using the categories that have been stored in local storage.

注意

由於 Microsoft 推播通知服務 (WPNS) 所指派的通道 URI 可能隨時會變更,因此您應經常註冊通知以避免通知失敗。Because the channel URI assigned by the Microsoft Push Notification Service (MPNS) can change at any time, you should register for notifications frequently to avoid notification failures. 此範例會在應用程式每次啟動時註冊通知。This example registers for notifications 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.

  1. 開啟 App.xaml.cs 檔案,將 async 修飾詞新增至 Application_Launching 方法,並使用以下程式碼取代您在開始使用通知中樞中新增的通知中樞註冊碼:Open the App.xaml.cs file and add the async modifier to Application_Launching method and replace the Notification Hubs registration code that you added in Get started with Notification Hubs with the following code:

    private async void Application_Launching(object sender, LaunchingEventArgs e)
    {
        var result = await notifications.SubscribeToCategories();
    
        if (result != null)
            System.Windows.Deployment.Current.Dispatcher.BeginInvoke(() =>
            {
                MessageBox.Show("Registration Id :" + result.RegistrationId, "Registered", MessageBoxButton.OK);
            });
    }
    

    此程式碼可確保應用程式每次啟動時都會從本機儲存體擷取類別,並要求這些類別的註冊。This code makes sure that every time the app starts it retrieves the categories from local storage and requests a registration for these categories.

  2. 在 MainPage.xaml.cs 專案檔案中,新增下列實作 OnNavigatedTo 方法的程式碼:In the MainPage.xaml.cs project file, add the following code that implements the OnNavigatedTo method:

    protected override void OnNavigatedTo(NavigationEventArgs e)
    {
        var categories = ((App)Application.Current).notifications.RetrieveCategories();
    
        if (categories.Contains("World")) WorldCheckBox.IsChecked = true;
        if (categories.Contains("Politics")) PoliticsCheckBox.IsChecked = true;
        if (categories.Contains("Business")) BusinessCheckBox.IsChecked = true;
        if (categories.Contains("Technology")) TechnologyCheckBox.IsChecked = true;
        if (categories.Contains("Science")) ScienceCheckBox.IsChecked = true;
        if (categories.Contains("Sports")) SportsCheckBox.IsChecked = true;
    }
    

    此程式碼會根據先前儲存之類別的狀態來更新主頁面。This code updates the main page based on the status of previously saved categories.

現在已完成此應用程式,且可在裝置本機儲存體中儲存一組類別,以供每次使用者變更類別選項在通知中心註冊時使用。The app is now complete and can store a set of categories in the device local storage used to register with the notification hub whenever the user changes the selection of categories. 接著,定義可將類別通知傳送至此應用程式的後端。Next, define a backend that can send category notifications to this app.

傳送加註標記的通知Send tagged notifications

在本節中,您會從 .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>");
    
        // Apple requires the apns-push-type header for all requests
        var headers = new Dictionary<string, string> {{"apns-push-type", "alert"}};
    
        // 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/FCM, 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.

測試應用程式Test the app

  1. 在 Visual Studio 中,按 F5 以編譯並啟動應用程式。In Visual Studio, press F5 to compile and start the app.

    具有類別的行動應用程式

    應用程式 UI 提供一組切換,可讓您選擇要訂閱的類別。The app UI provides a set of toggles that lets you choose the categories to subscribe to.

  2. 啟用一或多個類別切換,然後按一下 [訂閱] 。Enable one or more categories toggles, then click Subscribe.

    應用程式會將選取的類別轉換成標籤,並在通知中心內為選取的標籤要求新裝置註冊。The app converts the selected categories into tags and requests a new device registration for the selected tags from the notification hub. 系統會傳回已註冊類別並顯示在對話方塊中。The registered categories are returned and displayed in a dialog.

    已訂閱的訊息

  3. 收到您各項類別的訂閱已完成的確認後,請執行主控台應用程式,以傳送各種類別的通知。After receiving a confirmation that your categories were subscription completed, run the console app to send notifications for each category. 請確認您只會收到所訂閱類別的通知。Verify you only receive a notification for the categories you have subscribed to.

    通知訊息

後續步驟Next steps

在本教學課程中,您已了解如何將通知推送至具有與其註冊相關聯之標記的特定裝置。In this tutorial, you learned how to push notifications to specific devices that have tags associated with their registrations. 若要了解如何將通知推送給可能使用多項裝置的特定使用者,請繼續進行下列教學課程:To learn how to push notifications to specific users who may be using multiple devices, advance to the following tutorial: