教程:使用 Azure 通知中心向 Windows 应用推送本地化通知

概述

本教程介绍如何将本地化通知推送到已注册到通知中心服务的移动设备。 在本教程中,请更新在教程:向特定设备(通用 Windows 平台)发送通知中创建的应用程序,使之支持以下方案:

  • Windows 应用商店应用允许客户端设备指定一种语言并订阅不同的突发新闻类别。
  • 后端应用使用 Azure 通知中心的标记模板功能来广播通知。

完成本教程后,即可通过移动应用程序注册感兴趣的类别,并指定接收通知的语言。 后端应用程序可发送按语言和设备本地化的通知。

本教程介绍如何执行下列操作:

  • 更新 Windows 应用,使之支持区域设置信息
  • 更新后端应用,以便发送本地化通知
  • 测试应用程序

先决条件

完成教程:向特定设备(通用 Windows 平台)发送通知

教程:向特定设备(通用 Windows 平台)发送通知中,已开发一个使用标记订阅不同新闻类别通知的应用。 在本教程中,请使用通知中心的模板功能轻松传递本地化突发新闻通知。

在高级别,模板是指定特定设备接收通知的格式的一种方法。 模板通过引用作为应用程序后端所发消息的一部分的属性,指定确切的负载格式。 在本教程中,后端应用程序会发送一条与区域设置无关的消息,其中包含所有支持的语言:

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

设备注册到引用正确属性的模板。 例如,要接收英文 toast 消息的 Windows 应用商店应用会注册以下包含任何相应标记的模板:

<toast>
    <visual>
    <binding template=\"ToastText01\">
        <text id=\"1\">$(News_English)</text>
    </binding>
    </visual>
</toast>

若要详细了解模板,请参阅模板一文。

更新 Windows 应用,使之支持区域设置信息

  1. 打开为教程:向特定设备(通用 Windows 平台)发送通知创建的 Visual Studio 解决方案。
  2. 更新 MainPage.xaml,使之包含区域设置组合框:

    <Grid Margin="120, 58, 120, 80"  
            Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
            <RowDefinition />
            <RowDefinition />
            <RowDefinition />
            <RowDefinition />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <TextBlock Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2"  TextWrapping="Wrap" Text="Breaking News" FontSize="42" VerticalAlignment="Top"/>
        <ComboBox Name="Locale" HorizontalAlignment="Left" VerticalAlignment="Center" Width="200" Grid.Row="1" Grid.Column="0">
            <x:String>English</x:String>
            <x:String>French</x:String>
            <x:String>Mandarin</x:String>
        </ComboBox>
        <ToggleSwitch Header="World" Name="WorldToggle" Grid.Row="2" Grid.Column="0"/>
        <ToggleSwitch Header="Politics" Name="PoliticsToggle" Grid.Row="3" Grid.Column="0"/>
        <ToggleSwitch Header="Business" Name="BusinessToggle" Grid.Row="4" Grid.Column="0"/>
        <ToggleSwitch Header="Technology" Name="TechnologyToggle" Grid.Row="2" Grid.Column="1"/>
        <ToggleSwitch Header="Science" Name="ScienceToggle" Grid.Row="3" Grid.Column="1"/>
        <ToggleSwitch Header="Sports" Name="SportsToggle" Grid.Row="4" Grid.Column="1"/>
        <Button Content="Subscribe" HorizontalAlignment="Center" Grid.Row="5" Grid.Column="0" Grid.ColumnSpan="2" Click="SubscribeButton_Click" />
    </Grid>
    
  3. Notifications 类中,将一个区域设置参数添加到 StoreCategoriesAndSubscribeSubscribeToCateories 方法。

    public async Task<Registration> StoreCategoriesAndSubscribe(string locale, IEnumerable<string> categories)
    {
        ApplicationData.Current.LocalSettings.Values["categories"] = string.Join(",", categories);
        ApplicationData.Current.LocalSettings.Values["locale"] = locale;
        return await SubscribeToCategories(categories);
    }
    
    public async Task<Registration> SubscribeToCategories(string locale, IEnumerable<string> categories = null)
    {
        var channel = await PushNotificationChannelManager.CreatePushNotificationChannelForApplicationAsync();
    
        if (categories == null)
        {
            categories = RetrieveCategories();
        }
    
        // Using a template registration. This makes supporting notifications across other platforms much easier.
        // Using the localized tags based on locale selected.
        string templateBodyWNS = String.Format("<toast><visual><binding template=\"ToastText01\"><text id=\"1\">$(News_{0})</text></binding></visual></toast>", locale);
    
        return await hub.RegisterTemplateAsync(channel.Uri, templateBodyWNS, "localizedWNSTemplateExample", categories);
    }
    

    请调用 RegisterTemplateAsync 而非 RegisterNativeAsync 方法。 请注册一个具体的通知格式,采用此通知格式的模板依赖于区域设置。 另请提供模板名称(“localizedWNSTemplateExample”),因为可能需要注册多个模板(例如,一个模板用于 toast 通知,另一个模板用于磁贴)。 另外,为了便于更新或删除,也需要为其命名。

    如果一个设备使用同一标记注册多个模板,针对该标记的传入消息会导致多个通知发送到设备(一个通知对应一个模板)。 当同一逻辑消息必须导致多个可视通知时,此行为很有用,例如在 Windows 应用商店应用程序显示徽章和 toast。

  4. 添加以下方法来检索存储的区域设置:

    public string RetrieveLocale()
    {
        var locale = (string) ApplicationData.Current.LocalSettings.Values["locale"];
        return locale != null ? locale : "English";
    }
    
  5. MainPage.xaml.cs 中,通过检索“区域设置”组合框的当前值并将它提供给对 Notifications 类的调用,更新按钮单击处理程序,如下所示:

    private async void SubscribeButton_Click(object sender, RoutedEventArgs e)
    {
        var locale = (string)Locale.SelectedItem;
    
        var categories = new HashSet<string>();
        if (WorldToggle.IsOn) categories.Add("World");
        if (PoliticsToggle.IsOn) categories.Add("Politics");
        if (BusinessToggle.IsOn) categories.Add("Business");
        if (TechnologyToggle.IsOn) categories.Add("Technology");
        if (ScienceToggle.IsOn) categories.Add("Science");
        if (SportsToggle.IsOn) categories.Add("Sports");
    
        var result = await ((App)Application.Current).notifications.StoreCategoriesAndSubscribe(locale,
                categories);
    
        var dialog = new MessageDialog("Locale: " + locale + " Subscribed to: " + 
            string.Join(",", categories) + " on registration Id: " + result.RegistrationId);
        dialog.Commands.Add(new UICommand("OK"));
        await dialog.ShowAsync();
    }
    
  6. 最后,在 App.xaml.cs 文件中,确保更新 InitNotificationsAsync 方法以检索区域设置,并在订阅时使用该区域设置:

    private async void InitNotificationsAsync()
    {
        var result = await notifications.SubscribeToCategories(notifications.RetrieveLocale());
    
        // Displays the registration ID so you know it was successful
        if (result.RegistrationId != null)
        {
            var dialog = new MessageDialog("Registration successful: " + result.RegistrationId);
            dialog.Commands.Add(new UICommand("OK"));
            await dialog.ShowAsync();
        }
    }
    

从后端发送本地化的通知

发送模板通知时,只需提供一组属性。在本教程中,后端应用程序发送一组包含当前新闻的本地化版本的属性,例如:

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

在本部分,请在解决方案中更新控制台应用程序项目。 使用以下代码修改前面创建的控制台应用中的 SendTemplateNotificationAsync 方法:

Important

在代码中指定通知中心的名称和具有完全访问权限的连接字符串。

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

不管平台如何,此简单调用都会将本地化的新闻片段传送到所有设备,因为通知中心会生成正确的本机有效负载并将其传送到已订阅特定标记的所有设备。

测试应用程序

  1. 运行通用 Windows 应用商店应用程序。 等待“注册成功”消息出现。

    移动应用程序和注册

  2. 选择类别区域设置,然后单击“订阅”。 应用程序将所选类别转换为标签并针对所选标签从通知中心请求注册新设备。

    移动应用程序

  3. 此时会看到有关订阅确认消息。

    订阅消息

  4. 在收到确认后,请运行控制台应用,以发送每个类别和每种支持语言的通知。 验证是否仅接收已订阅类别的通知,以及消息是否对应于所选区域设置。

    通知消息

后续步骤

本教程介绍了如何向其标记与注册相关联的特定设备推送本地化通知。 若要了解如何向可能会使用多个设备的特定用户推送通知,请转到以下教程: