前言

      移动Push推送是移动互联网最基础的需求之一,用于满足移动互联环境下消息到达App客户端。以转转(58赶集旗下真实个人的闲置交易平台)为例,当买家下单后,我们通过移动Push推送消息告诉卖家,当卖家已经发货时,我们通过移动Push消息告诉买家,让买卖双方及时掌握二手商品交易的实时订单动态。

实现推送功能的方案有许多,具体可以看《程序员》的一篇文章http://geek.csdn.net/news/detail/58738,这里也详解了IOS与Android接受推送的机制不同。

本文主要讲的是利用第三方平台来开发个推功能的API,使用的个推平台:http://www.getui.com/

具体的使用流程,如何绑定APP在官网的官方文档里已经详细给出,这个都是操作问题,不涉及到后台的开发。官方文档里已经给出了API介绍,但是使用的需求API提供的信息远远超出了API介绍的范围。下面我将从设计的角度给出一个DEMO。

DEMO

需求:web端/APP端给指定群体用户发送一条通知,使用客户端登录APP的指定用户都能收到通知(支持多终端登录),在菜单栏显示通知,点击通知转到APP内(透传)显示通知详情(无论APP离线还是在线);

设计:
类:
loginUserPojo(用户类)
NotificationPojo(通知类)--属性见数据库设计信息表
                   
数据库表的设计:
user_login(user_id,user_name,password....)
nofitication(notification_id,title,content,createDt,creator_user_id....)
user_device(user_id,client_id,device_token)(ios个推信息通过device_id发送,andorid通过client_id发送)
个推API设计:
1.基本配置信息类
public class GeXinBaseInfo {//以下三个属性每个APP不同static String appId = "VAn4M36ciG9mGBEQwuDxV5";static String appkey = "HSlKLGNZ8e6RChB3JCIop9";static String master = "CUEIVtxSdL6wO9GfRxFoZ1";//host是固定的作为个推的服务器static String host = "http://sdk.open.api.igexin.com/serviceex";static long offExpireTime = 24 * 1000 * 3600;//透传消息设置,1为强制启动应用,客户端接收到消息后就会立即启动应用;2为等待应用启动static int TYPE_LAUNCH_APP = 1;static int TYPE_WAIT_FOR_CLICK = 2;
}
2.安卓端接收信息类(点击通知后,app端根据ID信息获取通知详情)
public class TransimissionContentPojo implements Serializable{//通知的idprivate String contentId;//其它属性。。。//private ...public String getContentId() {return contentId;}public void setContentId(String contentId) {this.contentId = contentId;}
}

3.创建通知信息的工厂类

public class NotiTemplateFactory {//andoridpublic static NotificationTemplate produceNotiFromNoti(NotificationPojo notificationPojo){NotificationTemplate template = getBaseTemplate();template.setTitle("移动校园");template.setText(notificationPojo.getTitle());template.setTransmissionType(1);TransimissionContentPojo pojo = new TransimissionContentPojo();pojo.setContentId(notificationPojo.getNotificationId());template.setTransmissionContent(new Gson().toJson(pojo));return template;}//iospublic static APNPayload.DictionaryAlertMsg getDictionaryAlertMsg(String title, NotificationPojo nPojo){APNPayload.DictionaryAlertMsg alertMsg = new APNPayload.DictionaryAlertMsg();alertMsg.setBody(title);alertMsg.setTitle("移动校园");alertMsg.setTitleLocKey("ccccc");alertMsg.setActionLocKey("移动校园");return alertMsg;}
}

4.个推发送信息工具类

public class GeXinMPushUtil {private static GeXinMPushUtil instance;private static ExecutorService executorService;private List<Target> convertToTargets(List<String> cidList) {List<Target> targetList = new ArrayList<>();for (String cid : cidList) {Target target = new Target();target.setAppId(GeXinBaseInfo.appId);target.setClientId(cid);
//          target.setAlias(cid);targetList.add(target);}return targetList;}protected IGtPush push;public GeXinMPushUtil() {push = new IGtPush(GeXinBaseInfo.host, GeXinBaseInfo.appkey, GeXinBaseInfo.master);executorService = Executors.newCachedThreadPool();}public static GeXinMPushUtil getInstance() {if (instance == null) {instance = new GeXinMPushUtil();}return instance;}//andorid有通知public void push(final NotificationTemplate notificationTemplate, final List<String> cidList) {executorService.submit(new Runnable() {@Overridepublic void run() {ListMessage message = new ListMessage();message.setData(notificationTemplate);message.setOffline(true);message.setOfflineExpireTime(GeXinBaseInfo.offExpireTime);String taskId = push.getContentId(message);IPushResult ret = push.pushMessageToList(taskId, convertToTargets(cidList));System.out.println(ret.getResponse().toString());}});}//andorid透传,无通知public void push(final TransmissionTemplate transmissionTemplate, final List<String> cidList) {executorService.submit(new Runnable() {@Overridepublic void run() {ListMessage message = new ListMessage();message.setData(transmissionTemplate);message.setOffline(false);message.setOfflineExpireTime(GeXinBaseInfo.offExpireTime);String taskId = push.getContentId(message);IPushResult ret = push.pushMessageToList(taskId, convertToTargets(cidList));System.out.println(ret.getResponse().toString());}});}//将用户ID与client_id绑定记录在个推服务上public boolean bind(String alias, String cid){IAliasResult bindSCid = push.bindAlias(GeXinBaseInfo.appId, alias, cid);return bindSCid.getResult();}//解绑public boolean unBind(String alias, String cid){IAliasResult unBindSCid = push.unBindAlias(GeXinBaseInfo.appId, alias, cid);return unBindSCid.getResult();}//ios推送public void pushAPN(final APNPayload.DictionaryAlertMsg alertMsg, final List<String> deviceTokens, String content){IGtPush push = new IGtPush(GeXinBaseInfo.host,GeXinBaseInfo.appkey, GeXinBaseInfo.master);APNTemplate t = new APNTemplate();APNPayload apnpayload = new APNPayload();apnpayload.setSound("");apnpayload.setAlertMsg(alertMsg);//传送的附加信息,用于解析apnpayload.addCustomMsg("info",content);t.setAPNInfo(apnpayload);ListMessage message = new ListMessage();message.setData(t);IPushResult ret = push.pushAPNMessageToList(GeXinBaseInfo.appId, contentId, deviceTokens);System.out.println(ret.getResponse());}
}

逻辑设计:

用户登录andorid携带client_id,iOS端携带device_token,检查user_device中是否有记录user_id与 client_id或user_id与device_token的组合,如果没有插入组合,并且绑定这组信息
public UserInfoJson login(HttpServletRequest request,HttpServletResponse response) {String userName = request.getParameter("userName");String password = request.getParameter("passWord");String clientId = request.getParameter("clientId");String deviceId = request.getParameter("deviceToken");LoginUserPojo user = loginUserService.findByUserCode(userName);if (user == null) {return new UserInfoJson();} else {UserInfoJson userJson = getUserJson(user);//绑定用户与硬件if (clientId != null && !clientId.trim().equals("")) {userJson.setClientId(clientId);int count = loginUserService.selectDeviceByClientId(user.getUserId(), clientId);if (count == 0) {GeXinMPushUtil.getInstance().bind(user.getUserId(), clientId);loginUserService.insertDeviceByClientId(user.getUserId(), clientId);}}if (deviceId != null && !deviceId.trim().equals("")) {userJson.setDeviceId(deviceId);int count = loginUserService.selectDeviceByDeviceId(user.getUserId(), deviceId);if (count == 0) {loginUserService.insertDeviceByDeviceId(user.getUserId(), deviceId);}}String encPassword = new SimpleHash("md5", password, new SimpleByteSourceFix(user.getSalt()), 2).toHex();if (!encPassword.equals(user.getPassword())) {return new UserInfoJson();} else {userJson.setToken(encPassword);return userJson;}}}
注销登录:
public boolean loginOut(HttpServletRequest request,HttpServletResponse response) {String userId = request.getParameter("userId");String clientId = request.getParameter("clientId");String deviceId = request.getParameter("deviceToken");boolean result = false;//取消绑定
if (clientId != null && !clientId.trim().equals(""))loginUserService.deleteDeviceByClientId(userId, deviceId);result = GeXinMPushUtil.getInstance().unBind(userId, clientId);if (deviceId != null) {try {loginUserService.deleteDeviceByDeviceId(userId, deviceId);result = true;} catch (Exception e){result = false;e.printStackTrace();}}return result;}
在发送通知的方法中,加入推送的代码:
..............前面的代码用户获取NotificationPojo nPojo(通知内容),List<String> sendUsers(发送的用户ID)List<String> listAlias = new ArrayList<>();if (sendUsers != null && !sendUsers.isEmpty()) {for (LoginUserPojo userPojo : sendUsers) {// TODO: 16/1/26 getui these userslistAlias.add(userPojo.getUserId());}}List<String> deviceTokens = new ArrayList<>();List<String> clientIds = new ArrayList<>();if (listAlias != null && !listAlias.isEmpty() && listAlias.size() != 0) {deviceTokens = loginUserService.selectDeviceTokens(listAlias);clientIds = loginUserService.selectClientIds(listAlias);}TransimissionContentPojo pojo = new TransimissionContentPojo(TransimissionContentPojo.TYPE_NOTI);pojo.setContentId(notificationPojo.getNotificationId());NotificationTemplate template = NotiTemplateFactory.produceNotiFromNoti(notificationPojo);if (clientIds.size() != 0 && !clientIds.isEmpty())GeXinMPushUtil.getInstance().push(template, clientIds);APNPayload.DictionaryAlertMsg alertMsg = NotiTemplateFactory.getDictionaryAlertMsg(notificationPojo.getTitle(),notificationPojo);if (deviceTokens.size() != 0 && !deviceTokens.isEmpty())GeXinMPushUtil.getInstance().pushAPN(alertMsg, deviceTokens,new Gson().toJson(pojo));.................这样就可以将推送信息发送出去了

其中

selectDeviceTokens(List<String>  alias)的mybatis代码如下:
(使用MyBatis的sql如下<select id="selectDeviceTokens" resultType="java.lang.String">select device_idfrom user_devicewhere device_id is not null and user_id in<foreach collection="userIds" item="userId" index="index"open="(" close=")" separator=",">#{userId}</foreach></select>)

对于附加信息,contentId的发送,app的获取,安卓端的获取凡事:msg.content-------此内容为new Gson().toJson(pojo)的Json字符串,可以解析获取contentId的内容,然后更具contentId获取Notification的详情(发送一次请求,sql查询)
而IOS的处理比较复杂,msg.payload.info-----此内容为new Gson().toJson(pojo)的Json字符串,因为IOS服务端发送的是ListMessage,这是对应msg,listMessage设置了payLoad,payLoad设置了info(apnpayload.addCustomMsg("info",content);),因此提取额外信息是msg.payload.info,info这个字端是在服务器端设置的,当然也可以是其它名称。
         关注微信公众号每天学习一点程序员的职业经

个推平台API使用经验相关推荐

  1. SpringCloud工作笔记062---APP消息推送_个推平台API使用经验

    JAVA技术交流QQ群:170933152 前言       移动Push推送是移动互联网最基础的需求之一,用于满足移动互联环境下消息到达App客户端.以转转(58赶集旗下真实个人的闲置交易平台)为例 ...

  2. 沃通CA推电子签名API接口,无缝嵌入企业平台,实现快速安全签署

    [API接口简介] WoSignDoc电子签名平台API接口,是沃通独特的电子合同服务模式.通过WoSignDoc电子签名平台API接口,客户可以将电子合同签署流程无缝集成到现有业务平台中,不影响平台 ...

  3. 淘宝退款崩溃;马云预言成真;谷歌推新API | 极客头条

    「CSDN 极客头条」,是从 CSDN 网站延伸至官方微信公众号的特别栏目,专注于一天业界事报道.风里雨里,我们将每天为朋友们,播报最新鲜有料的新闻资讯,让所有技术人,时刻紧跟业界潮流. 快讯速知 淘 ...

  4. 什么是短信平台api接口?

    自从人类诞生了手机,短信便随之而来,虽然后来有了更多的即时通信工具,如QQ和微信,个人用短信的机会已经很少了,但是对于企业公司来说,短信一直是非常方便的信息传递工具. 那些带有营销性质的企业和商家会通 ...

  5. 关于淘宝API的详细说明(淘宝开放平台API揭秘)

    自淘宝开放平台Beta公测开始,陆续开放了上百次个API,这些API涵盖了淘宝基本业务,截止发日志当天开放平台API每天的调用量可是说是天文数字. 作为TOP开发者的您对 于淘宝平台-API可以信手拿 ...

  6. 神卓互联内网穿透微信公众平台 API 实现微信登录

    神卓互联是一家专注于内网穿透和互联网软件开发的公司,其提供的内网穿透服务和微信开发能够满足众多企业和个人的需求.本文将介绍神卓互联的内网传统微信开发服务. 在内网中使用微信开发具有一定的困难,因为微信 ...

  7. 执迷不悟!互联网的7宗罪!道翰天琼认知智能机器人平台API接口大脑为您揭秘。

    执迷不悟!互联网的7宗罪!道翰天琼认知智能机器人平台API接口大脑为您揭秘. 最近,网上有一篇文章<互联网是人类历史的一段弯路吗?>(以下简称"弯路") 文章很长,约4 ...

  8. 中国人又当选欧洲科学院外籍院士啦!道翰天琼认知智能机器人平台API接口大脑为您揭秘。

    中国人又当选欧洲科学院外籍院士啦!道翰天琼认知智能机器人平台API接口大脑为您揭秘. 在近日的欧洲科学院2020年院士增选中,智源研究院"自然语言处理"重大研究方向首席科学家.清华 ...

  9. 一封传话聚合推送API文档

    一封传话聚合推送API文档 前言 [一封传话]是一款聚合推送工具,提供微信公众号.飞书.钉钉.企业微信群机器人.企微通知应用.邮件.自定义Webhook消息推送API.主要API只有一个,必传参数也只 ...

最新文章

  1. 收藏 | 多目标跟踪(MOT)入门
  2. [公告]博客园新服务器照片
  3. Linux 动态库的显示调用
  4. 前端学习(3179):ant-design介绍2
  5. Android官方开发文档Training系列课程中文版:数据存储之文件存储
  6. pycharm 怎么快速生成文件夹结构_为什么Python代码能运行但是PyCharm给我画红线?...
  7. android动态渐变button,Android--自定义Button的样式以及动态渐变效果
  8. 察颜观色保无忧—存储卡选购之四法则
  9. django动态HTML转PDF方法
  10. 海南可以禁燃油辆,东北不可以,因为冬天温度
  11. linux 光盘本地yum源,小凡带你搭建本地的光盘yum源
  12. 喜大普奔!GitHub 官方 App 正式版首发!
  13. Spring Boot入门系列(十八)整合mybatis,使用注解的方式实现增删改查
  14. win7如何解除锁定计算机,Win7电脑键盘数字键被锁了怎么解锁(图文)
  15. Flink DataStream API 介绍
  16. freemarker遍历list处理第一个、最后一个元素
  17. 通道结构体_超账结构中系统通道和应用程序通道上的配置更新
  18. 推荐一篇好文《佛教真像大家所认为的那样消极吗?》
  19. SRGAN模型——pytorch实现
  20. 【汇编语言】转移指令循环指令

热门文章

  1. HCIA网络基础18-PPPoE
  2. Python数据分析-时间序列预测法
  3. C语言实现画爱心(两种方式画法)
  4. 运维监控软件的选择对比----Zabbix vs Prometheus
  5. 计算机系统系统时间不准,windows7系统时间不对怎么办_windows7系统时间不准如何恢复-win7之家...
  6. java后台将数据导出到Excel表格
  7. git clone加速(实测推荐)
  8. C# Dictionary多线程安全访问问题
  9. Unity | 基础逻辑
  10. 2021-08-30-全排列-逆序数-排列的奇偶性