Задача отправки уведомлений (Push Notifications) на iOS-устройства (iPhone, iPad и iPod Touch)
Наше web-приложение работает на сервере Google App Engine (GAE). До версии GAE 1.7.7 отправка уведомлений на iOS было проблемой, потому что оно осуществляется через сокеты которые стали доступны только с версии 1.7.7 . Теперь можно отправлять используя сокеты. Для отправки необходимо подключить к проекту библиотеку java-apns (библиотека доступна на github https://github.com/notnoop/java-apns)
Maven dependency для подключения библиотеки к проекту
https://github.com/notnoop/java-apns/wiki/Installation
http://mvnrepository.com/artifact/com.notnoop.apns/apns/0.2.3
Для реализации отправки уведомлений на iOS необходимо сделать следующее
1. Метод, который будет регистрировать iOS устройство
2. Метод, который будет удалять регистрационную ифнормацию об iOS-устройстве
3. Метод, который будет отправлять push notifications на мобильное устройство
deviceToken который будет присылаться с iOS-устройства пользователя (например при логине в приложение)
Например, при выходе из приложения у пользователя удаляется deviceToken, чтобы если пользователь вышел из приложения, то ему не присылались уведомления
С помощью классов gae создаем очередь задач, в которую будут добавляться задачи отправки уведомлений пользователям
В ресурсе пишем
В менеджере пишем
Создадим класс, в который вынесем метод общий для всех других классов. Метод будет отправлять notification на iOS-устройство. Если у пользователя есть deviceToken, то ему будет отправляться сообщение. Создаем тело уведомления (payload) и отправляем уведомление пользователю с помощью метода push
Создаем объект класса ApnsService
здесь вызываем метод родительского, класса в который передаем apns service пользователя и сообщение
После того как уведомления отправлены всем пользователям можно остановить сервис
Наше web-приложение работает на сервере Google App Engine (GAE). До версии GAE 1.7.7 отправка уведомлений на iOS было проблемой, потому что оно осуществляется через сокеты которые стали доступны только с версии 1.7.7 . Теперь можно отправлять используя сокеты. Для отправки необходимо подключить к проекту библиотеку java-apns (библиотека доступна на github https://github.com/notnoop/java-apns)
Maven dependency для подключения библиотеки к проекту
https://github.com/notnoop/java-apns/wiki/Installation
http://mvnrepository.com/artifact/com.notnoop.apns/apns/0.2.3
Для реализации отправки уведомлений на iOS необходимо сделать следующее
1. Метод, который будет регистрировать iOS устройство
2. Метод, который будет удалять регистрационную ифнормацию об iOS-устройстве
3. Метод, который будет отправлять push notifications на мобильное устройство
Метод для регистрации iOS-устройства на сервере
deviceToken который будет присылаться с iOS-устройства пользователя (например при логине в приложение)
deviceToken - это UDID –
это уникальный идентификатор устройства, состоящий из 40 символов. Он уникален у
каждого iPhone, iPad или iPod Touch, как паспорт. У пользователя есть поле
deviceToken без него уведомления не смогут отправляться
@GET @Path("/regIosDevice") @Produces({ MediaType.APPLICATION_JSON }) public Response regIosDevice(@QueryParam("deviceToken") String deviceToken, @QueryParam("userId") Long userId) { User user = manager.retrieve(userId); if (user != null && !deviceToken.equals(user.getDeviceToken())) { user.setDeviceToken(deviceToken); manager.save(user); } return Response.ok().build(); }
Метод для удаления зарегистрированного iOS-устройства
Например, при выходе из приложения у пользователя удаляется deviceToken, чтобы если пользователь вышел из приложения, то ему не присылались уведомления
@GET @Path("/unregIosDevice") @Produces({ MediaType.APPLICATION_JSON }) public Response unregIosDevice(@QueryParam("deviceToken") String deviceToken, @QueryParam("userId") Long userId) { if (deviceToken != null && !deviceToken.isEmpty()) { User user = manager.retrieve(userId); if (user != null) { user.setDeviceToken(null); manager.save(user); } } return Response.ok().build(); }
Методы для очереди
С помощью классов gae создаем очередь задач, в которую будут добавляться задачи отправки уведомлений пользователям
В ресурсе пишем
@POST @Path("/createCargo") @Consumes(MediaType.APPLICATION_JSON) @Produces({ MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN }) public Response createCargo(CargoDTO entity) { ... if (manager.isUserConfirmedEmailAndPhone(Long.parseLong(userId))) { cargoManager.sendPushNotification(edited); } ... }
В менеджере пишем
public void sendPushNotification(Cargo created) { Queue queue = QueueFactory.getDefaultQueue(); queue.add(TaskOptions.Builder.withRetryOptions( RetryOptions.Builder.withTaskRetryLimit(3)).payload( new NewCargoPushNotificationsTask(created))); }
Метод для отправки Push Notifications на iOS-устройство
Создадим класс, в который вынесем метод общий для всех других классов. Метод будет отправлять notification на iOS-устройство. Если у пользователя есть deviceToken, то ему будет отправляться сообщение. Создаем тело уведомления (payload) и отправляем уведомление пользователю с помощью метода push
PayloadBuilder payloadBuilder = APNS.newPayload(); payloadBuilder.alertBody(message); apnsService.push(deviceToken, payloadBuilder.build());
public abstract class BaseSendPushNotificationTask implements DeferredTask { private static final Logger log = Logger .getLogger(BaseSendPushNotificationTask.class.getName()); private static final long serialVersionUID = 4666909051310909540L; protected void sendMessageToIos(ApnsService apnsService, User user, String message) { if (user.getDeviceToken() != null) { String deviceToken = user.getDeviceToken(); try { PayloadBuilder payloadBuilder = APNS.newPayload(); payloadBuilder.alertBody(message); apnsService.push(deviceToken, payloadBuilder.build()); } catch (Exception e) { log.log(Level.WARNING, e.getMessage(), e); } } } }
Создадим класс наследник
Для этого понадобится сгенерированный на mac файл сертификата с расширением .p12 и пароль к нему На основании этого файла создаем объект ApnsServiceBuilder
Для тестирования с сертификатом разработчика необходимо
использовать
Для тестирования в режиме Ad Hoc и для продакш релиза надо использовать
String certFilePath = url.getFile(); String certPassword = "your password here"; ApnsServiceBuilder serviceBuilder = APNS.newService() .withCert(certFilePath, certPassword) .withNoErrorDetection();
Для тестирования с сертификатом разработчика необходимо
использовать
serviceBuilder.withSandboxDestination();
Для тестирования в режиме Ad Hoc и для продакш релиза надо использовать
serviceBuilder.withProductionDestination();
Создаем объект класса ApnsService
apnsService = serviceBuilder.build();
здесь вызываем метод родительского, класса в который передаем apns service пользователя и сообщение
После того как уведомления отправлены всем пользователям можно остановить сервис
apnsService.stop();
public class NewCargoPushNotificationsTask extends BaseSendPushNotificationTask { private static final long serialVersionUID = 7979661993088302683L; private Cargo cargo; private ApnsService apnsService; public NewCargoPushNotificationsTask(Cargo cargo) { super(); this.cargo = cargo; } @Override public void run() { // get cargoDto ... // send push notifications // service for push notification to ios URL url = this.getClass() .getResource("/path to apple certificate file .p12"); String certFilePath = url.getFile(); String certPassword = "your password here"; ApnsServiceBuilder serviceBuilder = APNS.newService() .withCert(certFilePath, certPassword) .withNoErrorDetection(); // for production and for ad hoc testing serviceBuilder.withProductionDestination(); // don't delete it's for test on device // serviceBuilder.withSandboxDestination(); apnsService = serviceBuilder.build(); String message = "Новые заявки на перевозку"; List<User> users = UserManager.getInstance() .retrieveDriversByTruckCategoryAndLocation( cargo.getTruckCategory(), cargo.getDispatchLocation()); for (User user : users) { sendMessageToIos(apnsService, user, message); } if (apnsService != null) { apnsService.stop(); } } }
Комментариев нет:
Отправить комментарий