Java后台服务— JPush 实现

 随着App开发的普及,推送功能在App应用中也越来越重要。我们知道ios有自己的推送服务,但是Android并没有自己的原生推送机制,通常采用的是基于XMPP协议的推送。 这种开发很麻烦,因此市场上有很多第三方的推送服务,比如友盟、极光、亚马逊、百度云等等。我们在项目中用到的是极光推送。


Android 推送原理一般如下:

  •  短信服务方式(SMS)推送: 即服务器端向手机端发送短信,手机监听短信广播,然后将拦截的短信信息进行显示。
  • 轮询方式推送(polling): 即定时去服务器上查询数据。
  • 长连接(Tcp connect) : 即手机跟服务器之间维护一个TCP长连接,当服务器有数据,实时推送到客户端。 极光推送采用的就是这种方式。 
极光推送是一个整合了Android推送、IOS推送的统一推送平台。我主要负责java后台服务,下面介绍的主要是java后台使用极光实现消息推送应用。

业务场景:验票设置,工作人员将自己任务安排进行设置,后台通过获取该影城提前验票时间,与当前时间进行对比,如果有场次到该检票了,即发送工作提示推送给工作人员。

关键步骤点:

  1.   首先到极光推送官网注册应用,获取AppKey、Master Secret
  2.   环境搭建,导入依赖的jar包,本项目采用maven 方式


    cn.jpush.api
    jpush-client
    3.2.9

jar包方式:请到Release 页面下载相应版本的发布包

依赖包

  • slf4j / log4j (Logger)
  • gson (Google JSON Utils)

其中 slf4j 可以与 logback, log4j, commons-logging等日志框架一起工作,可根据你的需要配置使用。

示例代码:

a. 构建JpushUtil

			/**
			 * 极光推送工具类 https://github.com/
			 * 
			 * @author houjp
			 *
			 */
			public class JPushUtil {
				/**
				 * 所有平台,所有设备,内容为 content 的通知
				 * 
				 * @param content
				 * @return
				 */
				public static PushPayload buildPushObject_all_all_alert(String content) {
					return PushPayload.alertAll(content);
				}
			
				/**
				 * 根据 设备终端ID 推送消息
				 * 
				 * @param regesterIds
				 *            设备终端ID集合
				 * @param content
				 *            内容
				 * @return
				 */
				public static PushPayload buildPushObject_all_all_regesterIds(List regesterIds, String content) {
					return PushPayload.newBuilder().setPlatform(Platform.all())
							.setAudience(Audience.registrationId(regesterIds))
							.setNotification(Notification.alert(content))
							.build();
			
				}
				
				
				/**
				 * 所有平台,推送目标是别名为 "alias",通知内容为 TEST
				 * 
				 * @param alias
				 * @param content
				 * @return
				 */
				public static PushPayload buildPushObject_all_alias_alert(String alias, String content) {
					return PushPayload.newBuilder().setPlatform(Platform.all()).setAudience(Audience.alias(alias))
							.setNotification(Notification.alert(content)).build();
				}

可以看到,此处用到了Jpush的两个接口,一个是为所有平台推送消息内容,一个是为指定的设备推送消息内容。Audience设置为All代表所有用户)   

b.    具体业务逻辑代码

			@Service("jpushMessageService")                                       
			public class JpushMessageServiceImpl implements JpushMessageService{
			
				private final static String appKey = "334becb6acbf04bf81a578f1";
			
				private final static String masterSecret = "3a99e6e0f69a3abcf6a53fcb";
				/**
				 * 保存离线的时长。秒为单位。最多支持10天(864000秒)。 0 表示该消息不保存离线。即:用户在线马上发出,当前不在线用户将不会收到此消息。
				 * 此参数不设置则表示默认,默认为保存1天的离线消息(86400秒)。
				 */
				private static long timeToLive = 60 * 60 * 24;
			
				private static JPushClient jPushClient = null;
			
				private static final Logger logger = Logger.getLogger(JpushMessageServiceImpl.class);
				@Override
				public  boolean sendPushAll() {
					jPushClient = new JPushClient(masterSecret, appKey, (int)timeToLive);
					boolean flag = false;
					try {
						String title = "推送测试"; 
						PushPayload payload = JPushUtil.buildPushObject_all_all_alert(title);
						System.out.println("服务器返回数据:" + payload.toString());
			
						PushResult result = jPushClient.sendPush(payload);
						if (null != result) {
							logger.info("Get resul ---" + result);
							flag = true; 
						}
					} catch (APIConnectionException e) {
						logger.error("Connection error. Should retry later. ", e);
						flag = false; 
					} catch (APIRequestException e) {
						logger.error("Error response from JPush server. Should review and fix it. ", e);
						logger.info("HTTP Status: " + e.getStatus());
						logger.info("Error Code: " + e.getErrorCode());
						logger.info("Error Message: " + e.getErrorMessage());
						logger.info("Msg ID: " + e.getMsgId());
						flag = false; 
					}
					return flag;
					
				}
				@Override
				public  boolean  senPushByRegesterId(List regeSterIds,String msgContent) {
					jPushClient = new JPushClient(masterSecret, appKey);
					boolean flag = false;
			//		String content = "多个ID测试";
					try {
						PushPayload payload = JPushUtil.buildPushObject_all_all_regesterIds(regeSterIds,msgContent);
						System.out.println("服务器返回数据:" + payload.toString());
						PushResult result = jPushClient.sendPush(payload);
						if (null != result) {
							logger.info("Get result ----" + result);
							flag = true;
						}
					} catch (APIConnectionException e) {
						logger.error("Connection error. Should retry later. ", e);
						flag = false; 
					} catch (APIRequestException e) {
						logger.error("Error response from JPush server. Should review and fix it. ", e);
						logger.info("HTTP Status: " + e.getStatus());
						logger.info("Error Code: " + e.getErrorCode());
						logger.info("Error Message: " + e.getErrorMessage());
						logger.info("Msg ID: " + e.getMsgId());
						flag = false; 
					}
			
					return flag;
				}
				
  • 创建JpushClient  : jPushClient = newJPushClient(masterSecret, appKey);
              这里的key 和 masterSecret  即为我们在官网创建应用所对应的值。Andriod 和 ios客户端的key必须和此处的key对应。 
  •  推送消息:             
               PushResult result=jpushClient.sendPush(payload);

               参数:PushPayload 推送对象

               返回值: PushResult 表示服务端推送结果

c.   监听消息类:此业务场景是跟redis队列结合使用,即监听redis队列,判断是否到检票时间,若是即发送推送消息,可根据自己的业务需求定义controller。

		/**
		 * 定时检测验票时间
		 * 
		 * @author zhuhuoyun
		 * @date 2016年6月1日
		 */
		
		public class TShowScheduleTimer extends TimerTask {
			@Resource
			private TShowScheduleServices tshowScheduleServices;
			@Resource
			private OCheckTimeService oCheckTimeService;
			@Resource
			private JpushMessageService jpushMessageService;
			private static final Logger logger = Logger.getLogger(TShowScheduleTimer.class);
		
			@Override
			public void run() {
				delayTshow();
			}
		
			public void delayTshow() {
				logger.info("每隔一分钟监听队列消息,判断是否到验票时间!!!");
				List showList = tshowScheduleServices.ObtainTShowsFromRedisQueue();
				if (showList != null && showList.size() > 0) {
					// 获取即将要检票的场次
					for (String str : showList) {
						String a[] = str.split("-");
						String obdId = a[0];
						String cinemaId = a[1];
						String showId = a[2];
						String showTime = a[3];
						String message = a[4];
						OCheckTimeModel oCheckTimeModel = new OCheckTimeModel();
						oCheckTimeModel.setCinemaid(cinemaId);
						List checkTimes = oCheckTimeService.selectBySelective(oCheckTimeModel);
						if (checkTimes != null && checkTimes.size() > 0) {
							// 获取开场前几分钟
							int preTime = checkTimes.get(0).getStartEntrance();
							// 判断是否到检票时间
							if (DateUtil.getTimeRangeAfterHM(showTime) <= preTime) {
								List obdIds = new ArrayList();
								obdIds.add(obdId);
								jpushMessageService.senPushByRegesterId(obdIds, message);
								tshowScheduleServices.deleteTShowFromRedisQueue(showId);
							}
						}
					}
				} else {
					logger.info("showList is null !");
				}
			}
		}
可通过极光后台查看消息是否推送成功:

Java后台服务— JPush 实现_第1张图片

Jpush 相关概念:

Jpush 给我们提供了很多钟推送方式,我们可以选择某一平台进行推送,可以全部推送。可以针对某个特别的用户设置别名(alisa ) 进行推送,也可以针对特别的群体设置(tags) 进行推送,可以设置推送保留的时间,即只要在有效时间内上线就可以收到推送消息,可以根据指定多个设备ID(regestionId) 进行推送。

 1.  别名 alias :

 为安装应用程序的用户指定别名来标识,以后给用户push消息时,就可以用此别名来指定。

一个用户只能指定一个别名,一个别名可以多个用户,当指定多个用户时,若通过别名推送消息时,服务器端API会同时给多个用户发送消息。

 2.  标签 tag

为安装应用程序的用户打上标签,目的是为了批量下发Push消息。

可为每个用户打多个标签

不同程序,不同用户可以打同样的标签。

3.  通知vs自定义 消息:

通知,消息展示到手机的通知栏,简单的填写纯文本内容,由Jpush SDK 做通知展示处理。自定义消息是原始消息,Jpush SDK不做处理,由客户端展现App自己来做。

Jpush 关键字:

Java后台服务— JPush 实现_第2张图片


具体可参照push官方文档。

http://docs.jpush.io/server/rest_api_v3_push/


你可能感兴趣的:(【Java杂项】)