个推平台API使用经验
来源:互联网 发布:s7200cn密码破解软件 编辑:程序博客网 时间:2024/06/11 20:57
前言
移动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{ //通知的id private String contentId; //其它属性。。。 //private ... public String getContentId() { return contentId; } public void setContentId(String contentId) { this.contentId = contentId; }}
public class NotiTemplateFactory { //andorid public 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; } //ios public 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() { @Override public 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() { @Override public 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 users listAlias.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这个字端是在服务器端设置的,当然也可以是其它名称。
1 0
- 个推平台API使用经验
- 个推,手机推送api的使用
- 个推服务端api使用误区
- 个推服务端api使用误区
- android个推平台
- 第三方平台个推SDK的使用
- 个推使用总结
- 个推使用总结
- 个推服务端api初级使用手册
- 个推服务端api使用手册进阶
- 个推服务端api使用手册进阶
- 安卓推送——个推服务端api使用误区
- iOS个推的使用
- Windows Socket API 使用经验
- Windows Socket API 使用经验
- Windows Socket API 使用经验
- Windows Socket API 使用经验
- Windows Socket API 使用经验
- 计算的极限(一):所有机器的机器,与无法计算的问题
- Android 6.0 运行时权限处理完全解析
- Spring Security权限管理框架
- 【计算机】DMA原理1
- ZOJ 1420 Cashier Employment
- 个推平台API使用经验
- Css之关于块级元素水平居中
- html5动态加载图片和加载视频
- 解决Web部署 svg/woff/woff2字体 404错误
- forward与direct的区别
- 2016.03.06
- BC23&&hdoj5146&&hdoj5147
- 代码摘录
- java学习笔记-java异常处理机制