Теплым летним вечером, в процессе разработки очередного преложения для iOS, у меня совпало два фактора — возникла необходимость реализации Apple Push Notification (APN) и желание попробовать что-то совсем новое для меня. Идти проторенной дорогой через один из множества сервисов, предлагающих отправку APN не хотелось.
Для изобретения велосипеда был вабран Amazon Simple Notification Service (Amazon SNS). Amazon SNS — это сервис, который позволяет вам отправлять сообщения-нотификации, посредством разнообразных механизмов (APN, GCM, e-mail, SMS и т.д.).
О том, как это работает и более подробную информацию можно прочитать в документации Amazon. Я расскажу совсем немного, чтобы определиться с дальнейшей терменологией. У SNS есть два типа клиентов — публикаторы (publishers) и подписчики (subscribers). Публикаторы с подписчиками асинхрнно обмениваются сообщениями (messages), которые доставляются подписчикам, посредствам разнообразных механизмов. Для отправки груповых сообщений подписчики могут быть сгруппированы по темам (topics). Тогда все подписчики, подписанные на тему, получат сообщение в эту тему отправленное.
Картинка из документации Amazon:
Поскольку тема данной статьи — работа с сервисом SNS из iOS, подробно на бекенде останавливаться не будем. Скажу несколько предложений.
В рамках изобретения велосипеда бекенд был написан с использованием следующих технологий:
- Java 1.8;
- Spring Boot 1.2.4;
- Maven 3.3;
- AWS SDK for Java 1.10.1.
Я являюсь програмистом на Objective C/Swift, поэтому все это добро, включая Java, я в этом проекте использовал можно сказать впервые. Проект PushSnsSender выложил на GitHub. Во-первых, может кому-нибудь пригодится; а во-вторых, был бы очень рад push-реквестам.
Данный код поднимает веб-сервис, который на ваш POST-запрос вида:
{"topic": "arn:aws:sns:YOUR-TOPIC", "message": "Hooray!", "badge": 0, "sound": "bingbong.aiff", "isDebug": false }
Отправит APN “Hooray!” на SNS-тему “YOUR-TOPIC”.
Как бы то ни было, не ради бекенда я затевал эту статью. Все дело в том, что механизм подписки на топик из iOS приложения несправедливо обойден вниманием в документации Amazon, а именно на нем я хочу остановиться. Возможно кому-то это съэкономит драгоценные часы времени.
Перед тем как приступить к программированию, в консоли AWS нужно выполнить следующие действия:
- активация сервиса AWS SNS;
- активация сервиса AWS Cognito;
- создание Platform Application в сервисе SNS и привязка ключей Apple для работы с APN;
- создание новой темы для сервиса SNS;
- создание Identity Pool и привязанной к нему роли для сервиса Cognito.
Я не буду описывать перечисленные выше шаги, чтобы не повторять множество уже написанных статей. Кроме того, документация Amazon по каждому сервису действительно очень подробна и хороша — разобраться не составляет труда. Приведу несколько скриншотов для общего представления.
Окно создания Platform Application:
Окно создания новой темы:
Окно создания нового Identity Pool:
Немного задержимся на сервисе Cognito. Что это и зачем он нужен?
Как вы понимаете, с вашим уютным AWS не должено быть разрешено работать кому попало. За строгую авторизацию в AWS отвечает сервис Identity and Access Management, который каждому пользователю выдает ключи авторизации. Ключи авторизации, состоящие из Access Key Id и Secret Access Key — очень интимная штука, попавшая в неправильные руки может причинить вашему аккаунту AWS и вашему кошельку много-много бед. Поэтому никогда и не прикаких обстоятельствах не садитись в машину к незнакомым дядям не отдавайте ключи AWS.
Вместе с этим ваше iOS приложение на телефонах пользователей должно как-то авторизовываться в AWS, чтобы подписаться на тему. Тут на помощь нам приходит сервис AWS Cognito — одной из функций которого является аутентификация пользователей и назначение им определенной роли. Работать с сервисом достаточно просто. После создания нового Identity Pool, сервис сам сгенерит вам код, который надо использовать в вашем iOS приложении.
Окно нового Identity Pool и сгенерированного кода:
Вводные операции закончены и наконец можно перейти к любимой части — написанию кода.
Для работы с сервисами Amazon из нашего iOS приложения нам потребуется AWS SDK for iOS, а точнее три компонента оттуда: AWSCore; AWSSNS и AWSCognito. Для установки воспользуемся любимым менеджером пакетов, например для CocoaPods это будет выглядить так:
pod 'AWSCore', '~> 2.2' pod 'AWSSNS', '~> 2.2' pod 'AWSCognito', '~> 2.2'
Настало время самого интересного — ответа на вопрос: “Как из нашего iOS приложения подписаться на тему SNS?” Документация Amazon предложит нам решение в виде регистрации отдельного устройство и отправки сообщения на него, что для массовой рассылки абсолютно не подходит. Поэтому после авторизации с помощью кода, сгенеренного сервисом Cognito, мы просто вызовим API сервиса SNS и подпишемся на тему вручную.
Код вызова приведен ниже:
- (void)subscribeToPushTopicWithDeviceToken:(NSData *)deviceToken { AWSSNS *sns = [AWSSNS defaultSNS]; AWSSNSCreatePlatformEndpointInput *endpointRequest = [AWSSNSCreatePlatformEndpointInput new]; //get some device's IDs NSString *userDeviceName = [[UIDevice currentDevice] name]; NSString *userDevicePlatform = [[UIDevice currentDevice] model]; //get SNS settings self.myPlatformApplicationArn = @"arn:aws:sns:us-east-1:XXXXXXXXXXXXX:app/APNS/XXXXXXXXXXXXX"; self.myTopicArn = @"arn:aws:sns:us-east-1:XXXXXXXXXXXXX:XXXXXXXXXXXXX"; endpointRequest.platformApplicationArn = self.myPlatformApplicationArn; endpointRequest.token = [self deviceTokenAsString:deviceToken]; endpointRequest.customUserData = [NSString stringWithFormat:@"%@ - %@", userDevicePlatform, userDeviceName]; [[[sns createPlatformEndpoint:endpointRequest] continueWithSuccessBlock:^id(AWSTask *task) { AWSSNSCreateEndpointResponse *response = task.result; AWSSNSSubscribeInput *subscribeRequest = [AWSSNSSubscribeInput new]; subscribeRequest.endpoint = response.endpointArn; subscribeRequest.protocols = @"application"; subscribeRequest.topicArn = self.myTopicArn; return [sns subscribe:subscribeRequest]; }] continueWithBlock:^id(AWSTask *task) { if (task.cancelled) { NSLog(@"AWS SNS Task cancelled!"); } else if (task.error) { NSLog(@"%s file: %s line: %d - AWS SNS Error occurred: [%@]", __FUNCTION__, __FILE__, __LINE__, task.error); } else { NSLog(@"AWS SNS Task Success."); } return nil; }]; }
Вот и все. После успешного запуска приложения в консоли AWS вы увидите одно авторизованное устройство в Identity Pool сервиса Cognito и ваше устройство в качестве подписчика на тему:
Экран с отоброжением устройства, подписанного на тему:
Обратите внимание на различие ключей Apple для работы с APN в среде разработки и продуктивной среде.
Файлы Objective C:
BGMAwsSnsProvider.h
BGMAwsSnsProvider.m
Спасибо за внимание. Надеюсь, данная статья съэкономила вам хоть сколько-нибудь времени и подтолкнула обратить внимание на такой замечательный сервис как Amazon SNS.
ссылка на оригинал статьи http://habrahabr.ru/post/269963/
Добавить комментарий