基于Java的 iOS 多线程推送通报
基于Java的 iOS 多线程推送通知
一,iOS 推荐原理
4. Provider 到 APNS 的可信任连接
一,iOS 推荐原理
iOS 上的远程通知推荐机制,在官方的开发文档 《 Local and Push Notification Programming Guide》上已经有很清楚的描述。
下面再复习下这份指引的上的图,清晰下概念。
1. 消息流图
1.1 Provider 发送通知到 APNS (Apple Push Notification Server,苹果推送通知服务器)
1.2 APNS 发送通知到具体的 iOS 设备
1.3 iOS系统,通知到具体应用。
其中,Provider 是APP服务端的消息发出端,这部分是需要用户实现的事情,也是用户唯一可控的地方,其它流程完全在于苹果构建的系统的效率。
2. 总体消息流
从上面可以看到 APNS 的角色,是管理了 APNS 到每一个具体设备的长连接,而不是每个 Provider 到 每个 app 的长连接。这种方式的设计是基于 iOS 设备上的资源使用考虑,只要保留一个网络长连接就好,所有的 App 的通知都是通过这个长连接来推送通知。另一个方面,则是简化了整个流程的设计难度。
3. 设备到 APNS 的可信任长连接
4. Provider 到 APNS 的可信任连接
5. Token 的注册
注意到:已经安装的 APP, 在 APNS 注册到 Token 之后,是要有发送到 APP Provider 即,App 自己的服务器上,见下面一点:
6. Token 流
二,本文前提
1. 已经在 Provider 上已经记录了所安装的 APP 已经注册的设备的 Token
2. 相关的密钥,权限方面已经配置好
3. Provider 是基于 JavaPNS 的实现, JavaPNS 项目位于: http://code.google.com/p/javapns
三,代码
package com.zhenian.app.service; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.FutureTask; import javapns.Push; import javapns.communication.exceptions.CommunicationException; import javapns.communication.exceptions.KeystoreException; import javapns.notification.PushedNotification; import javapns.notification.ResponsePacket; import org.springframework.stereotype.Service; @Service public class NotificationEngine { // 10 个线程在后台发送通知 public static final int EXCE_THREAD_POOL_SIZE = 10; private void shutdownEngine(){ System.out.println("------------shutdownEngine-----------------------------"); // 关闭 ExecutorService if(!exec.isShutdown()){ exec.shutdown(); } } public void init(){ // 注册 jvm 关闭时操作 Runtime.getRuntime().addShutdownHook(new Thread(){ public void run() { .NotificationEnginethis.shutdownEngine(); } }); } public void destroy(){ Thread t = new Thread(){ public void run() { NotificationEngine.this.shutdownEngine(); } }; t.start(); } private ExecutorService exec = Executors.newFixedThreadPool(EXCE_THREAD_POOL_SIZE); private FutureTask<List<PushedNotification>> doSendNotificationList(final String message, final int badge, final String sound, final String keystore, final String password, final boolean production, final List<String> tokens){ // 带返回结果发送动作 FutureTask<List<PushedNotification>> future = new FutureTask<List<PushedNotification>>( new Callable<List<PushedNotification>>() { public List<PushedNotification> call() { List<PushedNotification> notifications = null; try { notifications = Push.combined(message,badge,sound,keystore,password,production,tokens); } catch (CommunicationException e) { e.printStackTrace(); } catch (KeystoreException e) { e.printStackTrace(); } return notifications; } }); // 提交到执行框架执行 exec.submit(future); return future; } public void sendNotificationList(final String message, final int badge, final String sound, final String keystore, final String password, final boolean production, final List<String> tokens){ FutureTask<List<PushedNotification>> futrue = doSendNotificationList(message, badge,sound,keystore,password,production,tokens); try { // 阻塞至接收到返回结果。 List<PushedNotification> list = futrue.get(); for (PushedNotification notification : list) { if (notification.isSuccessful()) { /* Apple accepted the notification and should deliver it */ System.out.println("Push notification sent successfully to: " + notification.getDevice().getToken()); /* Still need to query the Feedback Service regularly */ } else { String invalidToken = notification.getDevice().getToken(); /* Add code here to remove invalidToken from your database */ /* Find out more about what the problem was */ Exception theProblem = notification.getException(); //theProblem.printStackTrace(); log.error(theProblem.toString()); /* If the problem was an error-response packet returned by Apple, get it */ ResponsePacket theErrorResponse = notification.getResponse(); if (theErrorResponse != null) { log.error(theErrorResponse.getMessage()); } } } } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } } }
四,说明
1. 可以集成到 Java EE 应用之中
2. 也可以建立一个后台服务执行
3. JavaPNS 请参考相关文档。
THE END