Использование push-уведомлений

Push-уведомления позволяют удаленным поставщикам уведомлений отправлять уведомления приложениям, работающим на мобильных устройствах. В AIR 3.4 поддержка push-уведомлений для устройств iOS обеспечивается службой Apple Push Notification Service (APNs).

Примечание. Чтобы включить push-уведомления в AIR для приложений Android, используйте соответствующее расширение в машинном коде, например as3c2dm, разработанное специалистом Adobe по пропагандированию технологий Петром Вальчижином (Piotr Walczyszyn).

В оставшейся части данного раздела описано, как включить push-уведомления в AIR для приложений iOS.

Примечание. Предполагается, что читатель располагает идентификатором разработчика Apple и знаком с общим процессом разработки для ОС iOS, а также имеет опыт развертывания хотя бы одного приложения на устройстве iOS.

Обзор push-уведомлений

Служба Apple Push Notification Service (APNs) позволяет удаленным поставщикам уведомлений отправлять уведомления приложениям, работающим на устройствах iOS. APNs поддерживает следующие типы уведомлений:

  • Предупреждения

  • Значки

  • Звуки

Дополнительные сведения об APNs см. на сайте developer.apple.com.

При использовании в приложениях push-уведомлений выделяются следующие функциональные компоненты:

  • Клиентская программа. Регистрируется для получения уведомлений и поддерживает связь с удаленными поставщиками уведомлений и получает push-уведомления.

  • ОС iOS. Управляет взаимодействием клиентской программы и службы APNs.

  • Служба APNs. Предоставляет клиентской программе в момент регистрации идентификатор tokenId и передает в iOS уведомления от удаленных поставщиков уведомлений.

  • Удаленный поставщик уведомлений. Хранит информацию, связанную с идентификаторами клиентских программ tokenId и рассылает push-уведомления службам APNs.

Процесс регистрации

Ниже приведена диаграмма процесса регистрации на сервере для получения push-уведомлений:

  1. Клиентская программа посылает запрос ОС iOS на включение push-уведомлений.

  2. ОС iOS перенаправляет запрос службе APNs.

  3. Сервер APNs возвращает ОС iOS идентификатор tokenId.

  4. ОС iOS передает tokenId клиентской программе.

  5. Клиентская программа, используя собственные механизмы, предоставляет tokenId удаленному поставщику уведомлений, который сохраняет его для использования при рассылке push-уведомлений.

Процесс отправки и получения уведомления

Ниже приведена диаграмма процесса отправки и получения уведомления

  1. Удаленный поставщик уведомлений генерирует уведомление и передает пакет данных, дополненный идентификатором tokenId, службе APNs.

  2. Служба APNs перенаправляет уведомление ОС iOS на устройстве.

  3. ОС iOS передает содержимое push-уведомления программе.

Прикладной интерфейс push-уведомлений

В AIR 3.4 были добавлены прикладные программные интерфейсы (API) с поддержкой push-уведомлений iOS. Эти интерфейсы API находятся в пакете flash.notifications и включают следующие классы:

  • NotificationStyle — определяет константы для типов уведомлений: ALERT (предупреждение), BADGE (значок) и SOUND (звук).

  • RemoteNotifier — служит для создания и прекращения подписок на push-уведомления.

  • RemoteNotifierSubscribeOptions — позволяет выбрать типы принимаемых уведомлений. С помощью свойства notificationStyles можно определить вектор строковых значений, задающих регистрацию нескольких типов уведомлений.

В AIR 3.4 также включено событие flash.events.RemoteNotificationEvent, которое генерируется объектом RemoteNotifier в следующих случаях:

  • приложение успешно подписано на уведомление, и от службы APNs получен новый идентификатор tokenId;

  • получено новое удаленное уведомление.

Помимо этого, объект RemoteNotifier генерирует событие flash.events.StatusEvent в случае, если в процессе подписки произошла ошибка.

Управление push-уведомлениями из приложения

Чтобы зарегистрировать приложение в качестве получателя push-уведомлений, выполните следующие действия.

  • Добавьте в приложение код, создающий подписку на push-уведомления.

  • Включите push-уведомления в файле XML приложения.

  • Создайте профиль выделения ресурсов и сертификат, которые разрешают использование служб push-уведомлений iOS (iOS Push Services).

Следующий пример кода с примечаниями иллюстрирует процесс подписки на push-уведомления и обработки поступающих push-уведомлений:

package 
                        { 
                        import flash.display.Sprite; 
                        import flash.display.StageAlign; 
                        import flash.display.StageScaleMode; 
                        import flash.events.*; 
                        import flash.events.Event; 
                        import flash.events.IOErrorEvent; 
                        import flash.events.MouseEvent; 
                        import flash.net.*; 
                        import flash.text.TextField; 
                        import flash.text.TextFormat; 
                        import flash.ui.Multitouch; 
                        import flash.ui.MultitouchInputMode; 
                        // Required packages for push notifications 
                        import flash.notifications.NotificationStyle; 
                        import flash.notifications.RemoteNotifier; 
                        import flash.notifications.RemoteNotifierSubscribeOptions; 
                        import flash.events.RemoteNotificationEvent; 
                        import flash.events.StatusEvent; 
                        [SWF(width="1280", height="752", frameRate="60")] 

                        public class TestPushNotifications extends Sprite 
                        { 
                        private var notiStyles:Vector.<String> = new Vector.<String>;; 
                        private var tt:TextField = new TextField(); 
                        private var tf:TextFormat = new TextFormat(); 
                        // Contains the notification styles that your app wants to receive 
                        private var preferredStyles:Vector.<String> = new Vector.<String>(); 
                        private var subscribeOptions:RemoteNotifierSubscribeOptions = new RemoteNotifierSubscribeOptions(); 
                        private var remoteNot:RemoteNotifier = new RemoteNotifier(); 

                        private var subsButton:CustomButton = new CustomButton("Subscribe"); 
                        private var unSubsButton:CustomButton = new CustomButton("UnSubscribe"); 
                        private var clearButton:CustomButton = new CustomButton("clearText"); 

                        private var urlreq:URLRequest; 
                        private var urlLoad:URLLoader = new URLLoader(); 
                        private var urlString:String; 

                        public function TestPushNotifications() 
                        { 
                        super(); 

                        Multitouch.inputMode = MultitouchInputMode.TOUCH_POINT; 
                        stage.align = StageAlign.TOP_LEFT; 
                        stage.scaleMode = StageScaleMode.NO_SCALE; 

                        tf.size = 20; 
                        tf.bold = true; 


                        tt.x=0; 
                        tt.y =150; 
                        tt.height = stage.stageHeight; 
                        tt.width = stage.stageWidth; 
                        tt.border = true; 
                        tt.defaultTextFormat = tf; 

                        addChild(tt); 

                        subsButton.x = 150; 
                        subsButton.y=10; 
                        subsButton.addEventListener(MouseEvent.CLICK,subsButtonHandler); 
                        stage.addChild(subsButton); 

                        unSubsButton.x = 300; 
                        unSubsButton.y=10; 
                        unSubsButton.addEventListener(MouseEvent.CLICK,unSubsButtonHandler); 
                        stage.addChild(unSubsButton); 

                        clearButton.x = 450; 
                        clearButton.y=10; 
                        clearButton.addEventListener(MouseEvent.CLICK,clearButtonHandler); 
                        stage.addChild(clearButton); 

                        // 
                        tt.text += "\n SupportedNotification Styles: " + RemoteNotifier.supportedNotificationStyles.toString() + "\n"; 

                        tt.text += "\n Before Preferred notificationStyles: " + subscribeOptions.notificationStyles.toString() + "\n"; 

                        // Subscribe to all three styles of push notifications: 
                        // ALERT, BADGE, and SOUND. 
                        preferredStyles.push(NotificationStyle.ALERT ,NotificationStyle.BADGE,NotificationStyle.SOUND ); 

                        subscribeOptions.notificationStyles= preferredStyles; 

                        tt.text += "\n After Preferred notificationStyles:" + subscribeOptions.notificationStyles.toString() + "\n"; 


                        remoteNot.addEventListener(RemoteNotificationEvent.TOKEN,tokenHandler); 
                        remoteNot.addEventListener(RemoteNotificationEvent.NOTIFICATION,notificationHandler); 
                        remoteNot.addEventListener(StatusEvent.STATUS,statusHandler); 

                        this.stage.addEventListener(Event.ACTIVATE,activateHandler); 


                        } 
                        // Apple recommends that each time an app activates, it subscribe for 
                        // push notifications. 
                        public function activateHandler(e:Event):void{ 
                        // Before subscribing to push notifications, ensure the device supports it. 
                        // supportedNotificationStyles returns the types of notifications 
                        // that the OS platform supports 
                        if(RemoteNotifier.supportedNotificationStyles.toString() != "") 
                        {     
                        remoteNot.subscribe(subscribeOptions); 
                        } 
                        else{ 
                        tt.appendText("\n Remote Notifications not supported on this Platform !"); 
                        } 
                        } 
                        public function subsButtonHandler(e:MouseEvent):void{ 
                        remoteNot.subscribe(subscribeOptions); 
                        } 
                        // Optionally unsubscribe from push notfications at runtime. 
                        public function unSubsButtonHandler(e:MouseEvent):void{ 
                        remoteNot.unsubscribe(); 
                        tt.text +="\n UNSUBSCRIBED"; 
                        } 

                        public function clearButtonHandler(e:MouseEvent):void{ 
                        tt.text = " "; 
                        } 
                        // Receive notification payload data and use it in your app 
                        public function notificationHandler(e:RemoteNotificationEvent):void{ 
                        tt.appendText("\nRemoteNotificationEvent type: " + e.type + 
                        "\nbubbles: "+ e.bubbles + "\ncancelable " +e.cancelable); 

                        for (var x:String in e.data) { 
                        tt.text += "\n"+ x + ":  " + e.data[x]; 
                        } 
                        } 
                        // If the subscribe() request succeeds, a RemoteNotificationEvent of 
                        // type TOKEN is received, from which you retrieve e.tokenId, 
                        // which you use to register with the server provider (urbanairship, in 
                        // this example. 
                        public function tokenHandler(e:RemoteNotificationEvent):void 
                        { 
                        tt.appendText("\nRemoteNotificationEvent type: "+e.type +"\nBubbles: "+ e.bubbles + "\ncancelable " +e.cancelable +"\ntokenID:\n"+ e.tokenId +"\n"); 

                        urlString = new String("https://go.urbanairship.com/api/device_tokens/" + 
                        e.tokenId); 
                        urlreq = new URLRequest(urlString); 

                        urlreq.authenticate = true; 
                        urlreq.method = URLRequestMethod.PUT; 

                        URLRequestDefaults.setLoginCredentialsForHost 
                        ("go.urbanairship.com", 
                        "1ssB2iV_RL6_UBLiYMQVfg","t-kZlzXGQ6-yU8T3iHiSyQ"); 

                        urlLoad.load(urlreq); 
                        urlLoad.addEventListener(IOErrorEvent.IO_ERROR,iohandler); 
                        urlLoad.addEventListener(Event.COMPLETE,compHandler); 
                        urlLoad.addEventListener(HTTPStatusEvent.HTTP_STATUS,httpHandler); 

                        } 

                        private function iohandler(e:IOErrorEvent):void 
                        { 
                        tt.appendText("\n In IOError handler" + e.errorID +" " +e.type); 

                        } 
                        private function compHandler(e:Event):void{ 
                        tt.appendText("\n In Complete handler,"+"status: " +e.type + "\n"); 
                        } 

                        private function httpHandler(e:HTTPStatusEvent):void{ 
                        tt.appendText("\n in httpstatus handler,"+ "Status: " + e.status); 
                        } 

                        // If the subscription request fails, StatusEvent is dispatched with 
                        // error level and code. 
                        public function statusHandler(e:StatusEvent):void{ 
                        tt.appendText("\n statusHandler"); 
                        tt.appendText("event Level" + e.level +"\nevent code " + 
                        e.code + "\ne.currentTarget: " + e.currentTarget.toString()); 
                        } 
                        } 
                        }

Включение push-уведомлений в файле XML приложения

Чтобы использовать push-уведомления в своем приложении, введите следующее содержимое в элемент Entitlements (находящийся внутри элемента iphone):

<iphone> 
                            ... 
                               <Entitlements> 
                                  <![CDATA[ 
                                     <key>aps-environment</key> 
                                     <string>development</string> 
                                  ]]> 
                               </Entitlements> 
                            </iphone>

Перед непосредственной отправкой приложения в App Store измените содержимое элемента <string> с development на production:

      <string>production</string>

Если ваше приложение поддерживает локализованные строки, укажите соответствующие языки в элементе supportedLanguages, расположенном под элементом intialWindow, как в следующем примере:

<supportedLanguages>en de cs es fr it ja ko nl pl pt</supportedLanguages>

Создайте профиль выделения ресурсов и сертификат, которые разрешают использование служб push-уведомлений iOS (iOS Push Services)

Чтобы приложение могло связываться со службой APNs, необходимо включить в пакет приложения профиль выделения ресурсов и сертификат, разрешающие службу iOS Push Services:

  1. Войдите в учетную запись разработчика Apple.

  2. Перейдите на страницу Provisioning Portal (Центр выделения ресурсов).

  3. Откройте вкладку App IDs (Идентификаторы приложений).

  4. Нажмите кнопку New App ID (Новый идентификатор приложения).

  5. Введите описание и укажите идентификатор группы (в этом поле нельзя использовать *).

  6. Нажмите кнопку Submit (Отправить). Центр выделения ресурсов сгенерирует идентификатор программы, после чего снова откроется страница App IDs (Идентификаторы приложений).

  7. Нажмите кнопку Configure (Настроить), расположенную справа от идентификатора приложения. Откроется страница Configure App ID (Настройка идентификатора приложения).

  8. Установите флажок Enable for Apple Push Notification (Разрешить Push-уведомления Apple). Обратите внимание на то, что существует два типа сертификатов SSL, используемых для push-уведомлений: один для разработки и тестирования программ, а другой — для распространения программ.

  9. Нажмите кнопку Configure (Настроить), расположенную справа от строки Development Push SSL Certificate (Сертификат SSL уровня разработки для push-уведомлений). Откроется страница Generate Certificate Signing Request (Создать запрос на подпись сертификата).

  10. Сгенерируйте запрос на подпись сертификата с помощью утилиты Keychain Access (Связка ключей), как описано на странице.

  11. Сгенерируйте сертификат SSL.

  12. Загрузите и установите сертификат SSL.

  13. (Необязательно) Повторите пп. 9–12 для пункта Production Push SSL Certificate (Сертификат SSL уровня распространения для push-уведомлений).

  14. Нажмите Done (Готово). Откроется страница Configure App ID (Настройка идентификатора приложения).

  15. Нажмите Done (Готово). После этого отобразится страница App IDs (Идентификаторы приложений). Обратите внимание на зеленый кружок напротив строки Push Notification для вашего идентификатора приложения.

  16. Обязательно сохраните все созданные сертификаты SSL, поскольку они понадобятся в дальнейшем для обеспечения взаимодействия приложения и поставщика уведомлений.

  17. Откройте вкладку Provisioning (Выделение ресурсов), чтобы отобразить страницу Provisioning Profiles (Профили выделения ресурсов).

  18. Создайте новый профиль выделения ресурсов для нового идентификатора приложения и загрузите его на свой компьютер.

  19. Откройте вкладку Certificates (Сертификаты) и загрузите новый сертификат для нового профиля выделения ресурсов.

Использование звуковых push-уведомлений

Чтобы разрешить звуковые push-уведомления в вашем приложении, добавьте звуковые файлы к нему аналогично любым другим ресурсам, однако разместите их в той же папке, что и SWF-файлы и файлы app-xml. Например:

Build/adt -package -target ipa-app-store -provisioning-profile _-_.mobileprovision -storetype pkcs12 -keystore _-_.p12 test.ipa test-app.xml test.swf sound.caf sound1.caf

Устройства Apple поддерживают следующие форматы аудио (в файлах aiff, waf или caf):

  • Линейный PCM

  • MA4 (IMA/ADPCM)

  • uLaw

  • aLaw

Использование локализованных предупреждений

Чтобы использовать в приложении локализованные версии уведомлений-предупреждений, добавьте локализованные строки в виде папок lproj. Например, для поддержки предупреждений на русском языке, сделайте следующее.

  1. Создайте в проекте папку ru.lproj на том же уровне, на котором находится файл app-xml.

  2. В папке ru.lproj создайте текстовый файл с именем Localizable.Strings.

  3. Откройте файл Localizable.Strings в текстовом редакторе и добавьте ключи сообщений и соответствующие им локализованные строки. Например:

    "PokeMessageFormat" = "La notificación de alertas en español."
  4. Сохраните файл.

  5. Если в качестве языка устройства выбран «Русский», то при получении приложением предупреждения с заданным значением ключа, будет отображен локализованный вариант текста предупреждения.

Настройка удаленного поставщика уведомлений

Чтобы приложение могло получать push-уведомления, необходим удаленный поставщик уведомлений. Данное серверное приложение работает, как поставщик, принимающий входные данные push-уведомлений и передающий уведомления службе APNs, которая в свою очередь отправляет push-уведомления клиентской программе.

Подробные сведения об отправке push-уведомлений удаленным поставщиком уведомлений см. в разделе «Связь поставщика со службой push-уведомлений Apple» библиотеки разработчика Apple.

Варианты реализации удаленного поставщика уведомлений

Допустимы следующие варианты реализации удаленного поставщика уведомлений.

  • Создание собственного поставщика на базе сервера APNS-php с открытым кодом. Для настройки PHP сервера можно воспользоваться проектом http://code.google.com/p/apns-php/. Данный проект Google Code позволяет разработать интерфейс, отвечающий требованиям конкретной задачи.

  • Использование поставщика услуг. Например, вы можете воспользоваться готовым поставщиком APNs, предлагаемым на сайте http://urbanairship.com/. После регистрации в данной службе необходимо предоставить устройству дескриптор. Это можно сделать, например, с помощью следующего кода:

    private var urlreq:URLRequest; 
                                        private var urlLoad:URLLoader = new URLLoader(); 
                                        private var urlString:String; 
    
                                        //When subscription is successful then only call the following code 
                                        urlString = new String("https://go.urbanairship.com/api/device_tokens/" + e.tokenId); 
                                        urlreq = new URLRequest(urlString); 
    
                                        urlreq.authenticate = true; 
                                        urlreq.method = URLRequestMethod.PUT; 
                                        URLRequestDefaults.setLoginCredentialsForHost("go.urbanairship.com", 
                                           "Application Key","Application Secret"); 
                                        urlLoad.load(urlreq); 
                                        urlLoad.addEventListener(IOErrorEvent.IO_ERROR,iohandler); 
                                        urlLoad.addEventListener(Event.COMPLETE,compHandler); 
                                        urlLoad.addEventListener(HTTPStatusEvent.HTTP_STATUS,httpHandler); 
    
                                        private function iohandler(e:IOErrorEvent):void{ 
                                           trace("\n In IOError handler" + e.errorID +" " +e.type); 
                                        } 
    
                                        private function compHandler(e:Event):void{ 
                                           trace("\n In Complete handler,"+"status: " +e.type + "\n"); 
                                        } 
    
                                        private function httpHandler(e:HTTPStatusEvent):void{ 
                                           tt.appendText("\n in httpstatus handler,"+ "Status: " + e.status); 
                                        }

    Затем следует отправить тестовые уведомления с помощью инструментов Urban Airship.

Сертификаты для удаленного поставщика уведомлений

Сертификат SSL и закрытый ключ (генерируемый ранее) должны быть скопированы в соответствующее место на сервере удаленного поставщика уведомлений. Обычно эти два файла объединяются в один файл .pem. Это можно сделать следующим образом:

  1. Откройте окно терминала.

  2. Создайте файл .pem из сертификата SSL, введя следующую команду:

    openssl x509 -in aps_developer_identity.cer -inform der -out TestPushDev.pem
  3. Создайте файл .pem закрытого ключа(.p12), введя следующую команду:

    openssl pkcs12 -nocerts -out TestPushPrivateKey.pem -in certificates.p12
  4. Объедините два файла .pem в один с помощью следующей команды:

    cat TestPushDev.pem TestPushPrivateKey.pem > FinalTestPush.pem
  5. Передайте комбинированный файл .pem поставщику серверных услуг во время создания серверного приложения для поддержки push-уведомлений.

Дополнительные сведения см. в разделе «Установка сертификата SSL и ключа на сервер» руководства программиста Apple по локальным и push-уведомлениям.

Обработка push-уведомлений в приложении

Обработка push-уведомлений в приложении включает следующие составляющие.

  • Установка глобальных пользовательских настроек, разрешающих push-уведомления

  • Получение от пользователя разрешения на прием конкретных уведомлений

  • Обработка push-уведомлений и пересылаемых с ними данных

Настройки, разрешающие push-уведомления

При первом запуске пользователем программы с поддержкой push-уведомлений ОС iOS отображает диалоговое окно с предупреждением: Программа «Приложение» собирается отправлять Вам push-уведомления и кнопками «Не разрешать» и «OK». Выбор варианта «OK» позволяет программе получать все типы уведомлений, на которые она подписана. Выбор варианта «Не разрешать» запретит программе получать уведомления.

Примечание. Также пользователь может открыть раздел «Настройки» > «Уведомления» и выбрать конкретные типы push-уведомлений, которые программа сможет получать от поставщика.

Рекомендации компании Apple заключаются в том, что программа должна подписываться на push-обновления при каждой активации. Когда приложение вызывает метод RemoteNotifier.subscribe(), оно получает событие RemoteNotificationEvent типа token (дескриптор), содержащее a уникальный 32-байтный идентификатор tokenId для заданного приложения на устройстве.

Когда устройство получает push-уведомление, на его экране отображается всплывающее окно с кнопками «Закрыть» и «Запустить». При нажатии кнопки «Закрыть» не выполняется никаких действий. При нажатии кнопки «Запустить» ОС iOS запускает приложение и оно получает событие flash.events.RemoteNotificationEvent типа notification (уведомление), как описано ниже.

Обработка push-уведомлений и пересылаемых с ними данных

Когда удаленный поставщик уведомлений отправляет уведомление на устройство (используя идентификатор tokenID), ваше приложение получает событие flash.events.RemoteNotificationEvent типа notification (уведомление), независимо от того, запущено оно или нет. В этот момент приложение выполняет специфическую для нее обработку полученного уведомления. Если приложению требуется доступ к данным уведомления, они могут быть получены через свойство RemoteNotificationEvent.data в формате JSON.