자습서: Azure Notification Hubs를 사용하여 특정 Windows Phone 디바이스에 알림 푸시Tutorial: Push notifications to specific Windows Phone devices by using Azure Notification Hubs

이 자습서에서는 Azure Notification Hubs를 사용하여 특정 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.

참고

Notification Hubs Windows Phone SDK에서는 Windows Phone 8.1 Silverlight 앱에서의 WNS(Windows 푸시 알림 서비스) 사용을 지원하지 않습니다.The Notification Hubs Windows Phone SDK does not support using the Windows Push Notification Service (WNS) with Windows Phone 8.1 Silverlight apps. Windows Phone 8.1 Silverlight 앱에서 MPNS 대신 WNS를 사용하려면 REST API를 사용하는 [Notification Hubs - 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 Notification Hubs를 사용하여 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 파일을 연 다음, TitlePanelContentPanel이라는 Grid 요소를 다음 코드로 바꿉니다.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. <hub name><connection string with listen access> 자리 표시자를 알림 허브 이름과 앞서 얻었던 DefaultListenSharedAccessSignature의 연결 문자열로 바꿉니다.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>");
    

    참고

    클라이언트 앱과 함께 배포되는 자격 증명은 일반적으로 안전하지 않기 때문에 클라이언트 앱과 함께 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를 통해 앱에서 알림을 등록할 수 있지만, 기존 등록을 수정할 수 없으며 알림을 전송할 수도 없습니다.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.

참고

MPNS(Microsoft 푸시 알림 서비스)에서 할당하는 채널 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 메서드에 추가하고 Notification Hubs 시작에서 추가한 Notification Hubs 등록 코드를 다음 코드로 바꿉니다.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 Notification Hubs 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);
        }
    }
    

    이 코드는 문자열 배열에 있는 6개의 각 태그에 대한 템플릿 알림을 보냅니다.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. 위의 코드에서 <hub name><connection string with full access> 자리 표시자를 알림 허브 이름과 알림 허브의 대시보드에서 얻은 DefaultFullSharedAccessSignature의 연결 문자열로 바꿔야 합니다.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: