dp_push -- Erlang библиотека для работы с Apple Push Notification Service
24 июля 2012
Библиотека для работы с APNs от dieselpuppet.com.
APNs -- что это и зачем
Допустим, у вас проект с клиент-серверной архитектурой, где в роли клиента выступает приложение на iOS устройстве. Ваш замечательный сервер прекрасно общается с вашим замечательным приложением, пока оно активно.
Но вот пользователь запустил другое приложение, или положил девайс в карман, или оказался где-то, где нет WiFi. И увы, связи между сервером и вашим приложением больше нет. А серверу нужно доставить какие-то данные, или уведомить о каком-то событии.
Для такого случая существует Apple Push Notification Service.
Вместо того, чтобы отправлять сообщение клиентскому приложению, ваш сервер может отправить сообщение на APNs. А APNs доставит его на iOS устройство, если оно доступно. Устройство покажет сообщение пользователю, и по его требованию активирует нужное приложение.
Как это работает
Ваш сервер соединяется через SSL сокет с APNs и передает сообщение в определенном формате. Сообщение содержит payload -- собственно данные, которые нужно передать, и device token -- идентификатор iOS устройства, которому адресовано сообщение.
Однако сообщение адресовано не просто какому-то устройству, но еще и какому-то приложению, установленному на нем. Для этого при установке SSL соединения с APNs используется такой же сертификат, как тот, которым подписано ваше клиентское приложение.
APNs имеет хорошую документацию, где описаны все подробности.
Так же рекомендую замечательный тутор, который дает хороший старт. И, в частности, раскрывает непростую тему сертификатов :)
dp_push -- что это и зачем
Поскольку работать с APNs нужно практически в каждом нашем проекте, решено это унифицировать и вынести в отдельную библиотеку Diesel Puppet push. Никаких тайных секретов в этом функционале нет, нужно просто аккуратно его реализовать. Посему мы смело выкладываем модуль в open source, под MIT лицензией.
Реализация довольно простая, и представляет собой OTP-приложение из 4х модулей.
dp_push.erl Главный модуль, запускает приложение и является фасадом к функциям библиотеки.
dp_push_sup.erl Супервизор, запускает dp_push_sender и следит, что бы он не падал :)
dp_push_sender.erl gen_server, выполняет send запросы и работает с feedback сервисом (о котором ниже).
dp_push_apns.erl Содержит набор низкоуровневых функций для формирования пакетов, установки SSL соединения, отправки данных.
Приложение требует кое-каких настроек. Они, впрочем, довольно очевидные -- куда конектится, какой сертификат использовать, и настройки для feedback сервиса (о котором ниже).
device token
Немного подробнее о токене. iOS устройство получает токен у APNs сервера (подробности в документации). Потом ваше клиентское приложение должно передать его вашему серверу. А сервер будет использовать для отправки сообщений.
Токен имеет размер 32 байта, и выглядит примерно так:
8253de13 f71d310d 05a13135 e09e09b6 32c478d5 32313723 1f04a7c7 b5de947d
Работая с ним в Erlang, нужно иметь в виду, что это не строка и не binary. Вот так не правильно:
DeviceToken = "8253de13 f71d310d 05a13135 e09e09b6 32c478d5 32313723 1f04a7c7 b5de947d" DeviceToken = "8253de13f71d310d05a13135e09e09b632c478d5323137231f04a7c7b5de947d" DeviceToken = <<"8253de13f71d310d05a13135e09e09b632c478d5323137231f04a7c7b5de947d">>
Это 16-ти разрядное число. Вот так правильно:
DeviceToken = 16#8253de13f71d310d05a13135e09e09b632c478d5323137231f04a7c7b5de947d
feedback сервис
Все чутка сложнее, чем сперва казалось :) Бывает такое, что ваше приложение было удалено с девайса, а вы продолжаете присылать ему сообщения. Apple не очень хотят, чтобы APNs нагружали ненужными сообщениями, поэтому они настоятельно просят периодически обращаться к их feedback сервису, получать оттуда список таких девайсов, хранить список у себя и не посылать им сообщения.
Эта функциональность тоже реализована в dp_push_sender.erl. Модуль опрашивает feedback сервис с заданной частотой и хранит токены в DETS.
Если немного подумать, то все еще немножко сложнее, чем сперва казалось :) Бывает такое, что после того, как ваше приложение было удалено с девайса, оно было опять на него установлено :) Поэтому должен быть способ удалить токен из DETS. И соответствующий метод предусмотрен в API библиотеки.
У меня еще есть mock_feedback_service.erl. Это заглушка, которая использовалась для отладки работы с feedback service. Ибо делать такую отладку, постоянно устанавливая и удаляя приложение с девайса очень уж неудобно.
Как подключить dp_push к проекту и как использовать
Подключаем как зависимость в rebar.config:
{deps, [ {dp_push, ".*", {git, "https://github.com/yzh44yzh/dp-push.git", "v1.0"}} ]}.
Запускаем приложение:
main() -> ssl:start(), application:start(dp_push),
И вызываем API методы:
dp_push:send(Msg, DeviceToken),
Как можно dp_push развивать дальше
Запросы к APNs могут быть двух видов: simple и enchanced. На simple запросы сервис ничего не отвечает, а на enchanced отвечает. Можно принимать эти ответы и, например, как-то обрабатывать ошибки.
Можно сделать dp_push не подключаемой библиотекой, а отдельным сервером (TCP и/или Web). В этом случае он может обслуживать сразу несколько приложений. Правда ему нужно будет иметь сертификаты для каждого приложения и выбирать нужный сертификат при отправке сообщения.
Можно добавить сбор какой-нибудь статистики и средства мониторинга.
comments powered by Disqus