Руководство: отправка push-уведомлений на определенные устройства iOS с помощью службы Центры уведомлений Azure
Обзор
В этом руководстве показано, как использовать службу "Центры уведомлений Azure" для рассылки уведомлений об экстренных новостях в приложение iOS. По завершении вы сможете зарегистрироваться в интересующих вас категориях экстренных новостей и получать push-уведомления только для этих категорий. Этот сценарий часто используется во многих приложениях, которые отправляют уведомления определенным группам пользователей, подтвердившим интерес к этим уведомлениям. Типичные примеры: средства чтения RSS, приложения для любителей музыки и т. д.
Широковещательные сценарии реализуются путем включения одного или нескольких тегов при создании регистрации в концентраторе уведомлений. Если уведомления отправляются по тегу, то их получают устройства, зарегистрированные для данного тега. Поскольку теги представляют собой обычные строки, их не нужно подготавливать заранее. Дополнительные сведения о тегах см. в статье Маршрутизация и выражения тегов.
При работе с этим руководством вы выполните следующие задачи:
- добавление возможности выбора категорий в приложение;
- Отправка уведомлений с тегами
- отправка уведомлений с устройства;
- Запуск приложения и создание уведомлений
Предварительные условия
В этом разделе используется приложение, созданное при выполнении заданий в статье Руководство по отправке push-уведомлений в приложения iOS с помощью Центров уведомлений Azure. Прежде чем приступить к этому руководству, вы должны изучить раздел Руководство по отправке push-уведомлений в приложения iOS с помощью Центров уведомлений Azure.
Добавление возможности выбора категорий в приложение
Прежде всего, необходимо добавить элементы пользовательского интерфейса для имеющейся раскадровки, позволяющие пользователю выбирать категории для регистрации. Выбранные пользователем категории хранятся на устройстве. При запуске приложения в концентраторе уведомлений создается регистрация устройства с выбранными категориями, представленными в форме тегов.
В вашем MainStoryboard_iPhone.storyboard добавьте следующие компоненты из библиотеки объектов:
метка с текстом "Экстренные новости";
метки с текстами категории "Мир", "Политика", "Бизнес", "Технология", "Наука", "Спорт";
Шесть переключателей, по одному в каждой категории. Задайте для каждого переключателя Состояние по умолчанию Off (Откл.).
Одна кнопка с надписью «Подписка».
Раскадровка должна выглядеть следующим образом:
В редакторе помощника создайте выходы для всех переключателей и назовите их WorldSwitch, PoliticsSwitch, BusinessSwitch, TechnologySwitch, ScienceSwitch, SportsSwitch.
Создайте действие для кнопки
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;
Создайте класс Cocoa Touch Class с именем
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;
Добавьте следующую директиву импорта в Notifications.m:
#import <WindowsAzureMessaging/WindowsAzureMessaging.h>
Скопируйте следующий код в раздел файла 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]; }
Этот класс использует локальное хранилище для хранения и извлечения категорий новостей, которые получает данное устройство. Он также содержит метод регистрации этих категорий с помощью шаблонной регистрации.
В файле
AppDelegate.h
добавьте оператор импорта дляNotifications.h
и свойство для экземпляра классаNotifications
.#import "Notifications.h" @property (nonatomic) Notifications* notifications;
В методе
didFinishLaunchingWithOptions
вAppDelegate.m
добавьте в начало метода код для инициализации экземпляра уведомления.
ВHUBNAME
иHUBLISTENACCESS
(определены вhubinfo.h
) заполнители<hub name>
и<connection string with listen access>
необходимо заменить именем центра уведомлений и строкой подключения для DefaultListenSharedAccessSignature, полученными раньше.self.notifications = [[Notifications alloc] initWithConnectionString:HUBLISTENACCESS HubName:HUBNAME];
Примечание
Так как учетные данные, которые распространяются с помощью клиентского приложения, обычно небезопасны, с помощью вашего клиентского приложения следует распространять только ключ для доступа к прослушиванию. Доступ к прослушиванию позволяет приложению регистрироваться для использования уведомлений, однако при этом нельзя изменять имеющиеся регистрации и отправлять уведомления. Для отправки уведомлений и изменения существующих регистраций используется ключ полного доступа в защищенной серверной службе.
В методе
didRegisterForRemoteNotificationsWithDeviceToken
вAppDelegate.m
замените код в методе следующим кодом, чтобы переместить маркер устройства в классnotifications
. Классnotifications
выполняет регистрацию для уведомлений с категориями. Если пользователь меняет выбранные категории, для их обновления будет вызван методsubscribeWithCategories
в ответ на действие кнопки subscribe.Примечание
Поскольку маркер устройства, назначенный службой 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
не должно быть никакого другого кода.Изучив статью Руководство по отправке push-уведомлений в приложения iOS с помощью Центров уведомлений Azure, в файле
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.
В
ViewController.m
добавьте операторimport
дляAppDelegate.h
и скопируйте следующий код в созданный с помощью XCode методsubscribe
. Этот код обновляет регистрацию уведомлений для использования тегов новой категории, которые пользователь выбрал в пользовательском интерфейсе.#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
для хранения списка в локальном хранилище и регистрации соответствующих тегов в концентраторе уведомлений. При изменении категорий регистрация создается заново с новыми категориями.В файле
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.
Создайте в Visual Studio новое консольное приложение Visual C#.
- В меню выберите Файл>Создать>Проект.
- В окне Создание проекта выберите в списке шаблонов Консольное приложение (.NET Framework) для C# и нажмите кнопку Далее.
- Введите имя приложения.
- Для параметра Решение, выберите Добавить к решению и Создать, чтобы создать проект.
Выберите Инструменты>Диспетчер пакетов NuGet>Консоль диспетчера пакетов, а затем в окне консоли выполните следующую команду:
Install-Package Microsoft.Azure.NotificationHubs
Это действие добавляет ссылку на пакет SDK для Центров уведомлений Azure с помощью пакета Microsoft.Azure.NotificationHubs.
Откройте файл Program.cs и добавьте следующий оператор
using
:using Microsoft.Azure.NotificationHubs;
В класс
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); } }
Этот код отправляет шаблонное уведомление по каждому из шести тегов в массиве строк. Использование тегов гарантирует, что устройства будут получать уведомления только зарегистрированных категорий.
В предыдущем коде замените заполнители
<hub name>
и<connection string with full access>
именем центра уведомлений и строкой подключения для DefaultFullSharedAccessSignature, полученными ранее на панели мониторинга центра уведомлений.Добавьте следующие строки в метод
Main()
:SendTemplateNotificationAsync(); Console.ReadLine();
Выполните сборку консольного приложения.
(Необязательно.) Отправка уведомлений с устройства
Как правило, уведомления отправляются серверной службой, но вы можете отправлять уведомления об экстренных новостях непосредственно из приложения. Для этого обновите метод SendNotificationRESTAPI
, определенный в руководстве по началу работы со службой "Центры уведомлений".
В файле
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]; }
В файле
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]; } }
Повторно создайте проект и убедитесь, что у вас не возникли ошибки сборки.
Запуск приложения и создание уведомлений
Нажмите кнопку Запуск для построения проекта, после чего запустите приложение. Чтобы подписаться на некоторые экстренные новости, нажмите кнопку Подписаться . В появившемся диалоговом окне отобразятся те уведомления, на которые была настроена подписка.
Если выбрано Подписка, приложение преобразует выбранные категории в теги и запрашивает у концентратора уведомлений новую регистрацию устройств для выбранных тегов.
Введите сообщение, отправляемое в качестве экстренных новостей, и нажмите кнопку Отправить уведомление . Можно также запустить консольное приложение .NET для создания уведомлений.
Каждое устройство с подпиской на экстренные новости получает отправленные вами уведомления об экстренных новостях.
Дальнейшие действия
В этом руководстве вы отправили широковещательные уведомления на конкретные устройства iOS, зарегистрированные для получения уведомлений по категориям. Чтобы узнать, как отправлять локализованные push-уведомления, перейдите к следующему руководству.