Поделиться через


Руководство. Отправка push-уведомлений на определенные устройства iOS с помощью Центров уведомлений Azure

Обзор

В этом руководстве показано, как использовать Центры уведомлений Azure для трансляции уведомлений о критических новостях в приложение iOS. По завершении вы можете зарегистрироваться для категорий критических новостей, которые вас интересуют, и получать только push-уведомления для этих категорий. Этот сценарий является общим шаблоном для многих приложений, где уведомления должны отправляться группам пользователей, которые ранее объявили им интерес, например RSS-читатель, приложения для музыкальных поклонников и т. д.

Сценарии трансляции включены путем включения одного или нескольких тегов при создании регистрации в центре уведомлений. Когда уведомления отправляются в тег, устройства, зарегистрированные для тега, получают уведомление. Так как теги являются просто строками, они не должны быть подготовлены заранее. Дополнительные сведения о тегах см. в статье "Маршрутизация и выражения тегов центров уведомлений".

При работе с этим руководством вы выполните следующие задачи:

  • Добавление выбора категории в приложение
  • Отправка помеченных уведомлений
  • Отправка уведомлений с устройства
  • Запуск приложения и создание уведомлений

Предпосылки

В этом разделе предстоит продолжить разработку приложения, созданного по Руководству: Push-уведомления в iOS-приложения с помощью Azure Notification Hubs. Перед началом работы с этим руководством необходимо выполнить инструкции по отправке push-уведомлений в приложения iOS с помощью Центров уведомлений Azure.

Добавление выбора категории в приложение

Первым шагом является добавление элементов пользовательского интерфейса в существующую раскадровку, которая позволяет пользователю выбирать категории, чтобы зарегистрироваться. Категории, выбранные пользователем, хранятся на устройстве. При запуске приложения в центре уведомлений создается регистрация устройства с выбранными категориями в виде тегов.

  1. В MainStoryboard_iPhone.storyboard добавьте следующие компоненты из библиотеки объектов:

    • Метка с текстом "Критические новости",

    • Метки с текстами категорий "Мир", "Политика", "Бизнес", "Технология", "Наука", "Спорт",

    • По одному переключателю на каждую категорию, задайте состояние каждого переключателя на Выключено по умолчанию.

    • Одна кнопка с меткой "Подписаться"

      Раскадровка должна выглядеть следующим образом:

      Построитель интерфейсов Xcode

  2. В редакторе помощника создайте выходы для всех переключателей и назовите их "WorldSwitch", "PoliticsSwitch", "BusinessSwitch", "TechnologySwitch", "ScienceSwitch", "SportsSwitch".

  3. Создайте действие для вашей кнопки под названием subscribe; ViewController.h должен содержать следующий код:

    @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. Создайте новый Cocoa Touch класс под названием Notifications. Скопируйте следующий код в разделе интерфейса файла 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 <WindowsAzureMessaging/WindowsAzureMessaging.h>
    
  6. Скопируйте следующий код в разделе реализации файла 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
    {
        NSString* templateBodyAPNS = @"{\"aps\":{\"alert\":\"$(messageParam)\"}}";
    
        [hub registerTemplateWithDeviceToken:self.deviceToken name:@"simpleAPNSTemplate" 
            jsonBodyTemplate:templateBodyAPNS expiryTemplate:@"0" tags:categories completion:completion];
    }
    

    Этот класс использует локальное хранилище для хранения и получения категорий новостей, получаемых этим устройством. Кроме того, он содержит метод регистрации для этих категорий с помощью регистрации шаблона .

  7. В файле AppDelegate.h добавьте оператор импорта для Notifications.h и добавьте свойство для экземпляра класса Notifications.

    #import "Notifications.h"
    
    @property (nonatomic) Notifications* notifications;
    
  8. В методе didFinishLaunchingWithOptions в AppDelegate.m добавьте код для инициализации экземпляра уведомлений в начале метода.
    HUBNAME и HUBLISTENACCESS (определены в hubinfo.h) должны были уже быть заменены заполнителями именем концентратора уведомлений <hub name> и строкой подключения <connection string with listen access> для DefaultListenSharedAccessSignature, полученной ранее.

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

    Примечание.

    Поскольку учетные данные, поставляемые с клиентским приложением, обычно не защищены, следует распространять ключ только для доступа к прослушиванию с клиентским приложением. Доступ на прослушивание позволяет приложению регистрировать уведомления, но существующие регистрации не могут быть изменены и уведомления не могут быть отправлены. Полный ключ доступа используется в защищенной серверной службе для отправки уведомлений и изменения существующих регистраций.

  9. В методе didRegisterForRemoteNotificationsWithDeviceToken замените код в методе AppDelegate.mследующим кодом, чтобы передать маркер notifications устройства в класс. Класс notifications выполняет регистрацию для уведомлений с категориями. Если пользователь изменяет выбранные категории, вызовите subscribeWithCategories метод в ответ на кнопку подписки , чтобы обновить их.

    Примечание.

    Так как маркер устройства, назначенный службой push-уведомлений Apple (APNS), может изменяться в любое время, следует часто регистрировать уведомления, чтобы избежать сбоев уведомлений. В этом примере регистрируется получение уведомлений каждый раз при запуске приложения. Для приложений, которые выполняются часто, более одного раза в день, можно пропустить регистрацию, чтобы сохранить пропускную способность, если с момента предыдущей регистрации прошло менее одного дня.

    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.

  10. Следующие методы уже должны присутствовать в AppDelegate.m из завершения руководства Начало работы с Центрами уведомлений. В противном случае добавьте их.

    - (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.

  11. В ViewController.m добавьте инструкцию для AppDelegate.h, а затем скопируйте следующий код в метод subscribe, созданный Xcode. Этот код обновляет регистрацию уведомлений, чтобы использовать новые теги категорий, выбранные пользователем в пользовательском интерфейсе.

    #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 класс для хранения списка в локальном хранилище и регистрирует соответствующие теги в центре уведомлений. При изменении категорий регистрация создается заново с новыми категориями.

  12. В ViewController.m добавьте следующий код в метод viewDidLoad, чтобы задать пользовательский интерфейс на основе ранее сохраненных категорий.

    // 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;
    

Теперь приложение может хранить набор категорий в локальном хранилище устройства, используемом для регистрации в центре уведомлений при запуске приложения. Пользователь может изменить выбор категорий во время выполнения и вызвать метод subscribe, чтобы обновить данные регистрации устройства. Затем вы обновите приложение, чтобы отправить уведомления о критических новостях непосредственно в самом приложении.

(необязательно) Отправка помеченных уведомлений

Если у вас нет доступа к Visual Studio, вы можете перейти к следующему разделу и отправить уведомления из самого приложения. Вы также можете отправить соответствующее уведомление шаблона на портале Azure с помощью вкладки отладки для центра уведомлений.

В этом разделе вы отправляете срочные новости как уведомления с тегами из консольного приложения .NET.

  1. В Visual Studio создайте консольное приложение Visual C#:

    1. В меню выберите "Файл>нового>проекта".
    2. В разделе "Создание проекта" выберите консольное приложение (.NET Framework) для C# в списке шаблонов и нажмите кнопку "Далее".
    3. Введите название приложения.
    4. Для решения выберите "Добавить в решение" и нажмите кнопку "Создать ", чтобы создать проект.
  2. \Выберите Сервис\\>\Диспетчер пакетов NuGet\\>\Консоль диспетчера пакетов\, а затем в окне консоли выполните следующую команду:

    Install-Package Microsoft.Azure.NotificationHubs
    

    Это действие добавляет ссылку на SDK Azure Notification Hubs, используя пакет Microsoft.Azure.NotificationHubs.

  3. Откройте файл Program.cs и добавьте следующую using инструкцию:

    using Microsoft.Azure.NotificationHubs;
    
  4. Program В классе добавьте следующий метод или замените его, если оно уже существует:

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

    Этот код отправляет уведомление шаблона для каждого из шести тегов в массиве строк. Использование тегов гарантирует, что устройства получают уведомления только для зарегистрированных категорий.

  5. В приведенном выше коде замените заполнители <hub name> и <connection string with full access> именем центра уведомлений и строкой подключения для DefaultFullSharedAccessSignature на панели вашего центра уведомлений.

  6. В методе Main() добавьте следующие строки:

     SendTemplateNotificationAsync();
     Console.ReadLine();
    
  7. Создайте консольное приложение.

(необязательно) Отправка уведомлений с устройства

Обычно уведомления отправляются серверной службой, но вы можете отправлять уведомления о критических новостях непосредственно из приложения. Для этого обновите метод, определенный SendNotificationRESTAPI в руководстве по началу работы с Центрами уведомлений .

  1. В ViewController.m, обновите SendNotificationRESTAPI метод следующим образом, чтобы он принял параметр для тега категории и отправил уведомление соответствующего шаблона.

    - (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, как показано в коде ниже. Таким образом, он отправляет уведомления, используя каждый тег по отдельности, и отправляет их на несколько платформ.

    - (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. Перестройте проект и убедитесь, что у вас нет ошибок сборки.

Запуск приложения и создание уведомлений

  1. Нажмите кнопку "Выполнить", чтобы создать проект и запустить приложение. Выберите некоторые критически важные параметры новостей, чтобы подписаться, а затем нажмите кнопку "Подписаться ". Должно появиться диалоговое окно, показывающее, что уведомления были подписаны.

    Пример уведомления в iOS

    При выборе подписки приложение преобразует выбранные категории в теги и запрашивает новую регистрацию устройства для выбранных тегов из центра уведомлений.

  2. Введите сообщение, которое будет отправлено в качестве критических новостей, а затем нажмите кнопку "Отправить уведомление ". Кроме того, запустите консольное приложение .NET для создания уведомлений.

    Изменение настроек уведомлений в iOS

  3. Каждое устройство, подписанное на критические новости, получает уведомления о критических новостях, которые вы только что отправили.

Дальнейшие действия

В этом руководстве вы отправили широковещательные уведомления определенным устройствам iOS, зарегистрированным для категорий. Чтобы узнать, как отправлять локализованные уведомления, перейдите к следующему руководству: