因为工作需要,甲方单位使用极光推送总是出现用户收取不到推送消息,甲方要求我们使用个推。
因为我们访问网络的时候使用的是代理,所以个推提供的接口发送接口不能使用,所以需要重新写一个支持代理的http链接。目前项目中的个推使用流程如下:
目前使用的是群推:pushToList,群推第一步使用taskid ,taskid 就是我们的消息在推送平台对应的一个映射id,通过taskid 来找这个消息。第二部是发送消息。发送消息的流程和获取taskId的流程几乎是一致的,就是在发送的过程中,gt_action 传的参数不一样,获取taskid 时传的是getContentIdAction,而推送消息的时候使用的是pushMessageToListAction。
个推的推送过程是:
http 代理代码如下:
package com.ruim.ifsp.merser.util;import com.alibaba.dubbo.common.utils.StringUtils;
import com.ruim.ifsp.log.IfspLoggerFactory;
import com.ruim.ifsp.merser.cache.CommonConstants;
import com.ruim.ifsp.utils.client.http.IfspHttpClientUtil;
import org.slf4j.Logger;import java.io.*;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.URL;
/*** 个推* @author lxw* @deprecated 个推消息推送http链接*/
public class IGtpushHttpClient extends IfspHttpClientUtil {private static Logger logger = IfspLoggerFactory.getLogger(JpushHttpClient.class);static String proxyIp = CommonConstants.getProperties("PROXY_IP");static String proxyProt = CommonConstants.getProperties("PROXY_PORT");// private static String appId = "TxzlIyCcfS9KuENjjP4ux1";
// private static String appKey = "rAnoicfrNX7915IxPocAL2";
// private static String masterSecret = "KFDNBNKAVj9bgykwvqgeA5";
// static String host = "http://sdk.open.api.igexin.com/apiex.htm";private static String appId = CommonConstants.getProperties("IGTAPP_ID");//个推appidprivate static String appKey = CommonConstants.getProperties("IGTAPP_KEY");//应用appKeyprivate static String masterSecret = CommonConstants.getProperties("IGTMASTER_SECRET");//应用证书号private static String host = CommonConstants.getProperties("IGTPUST_HOST");//个推送地址public static HttpURLConnection buildConnect(String Action) throws Exception {URL url = new URL(host);logger.info("开始初始化服务器连接...");logger.info("服务器地址:[ " + url + " ]");/**启用代理*/Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyIp, Integer.valueOf(proxyProt)));HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection(proxy);httpURLConnection.setConnectTimeout(30000);httpURLConnection.setReadTimeout(30000);httpURLConnection.setDoInput(true);httpURLConnection.setDoOutput(true);httpURLConnection.setUseCaches(false);httpURLConnection.setRequestProperty("Content-Type", "text/html;charset=UTF-8");httpURLConnection.setRequestProperty("Gt-Action", Action);httpURLConnection.setRequestMethod("POST");httpURLConnection.connect();logger.info("服务器连接完成...");return httpURLConnection;}public static void sendMsg(HttpURLConnection httpURLConnection,String message) throws Exception {logger.info("上送服务报文开始...");logger.info("上送报文:[" + message + "]");OutputStream outputStream = null;try {outputStream = httpURLConnection.getOutputStream();// 注意编码格式,防止中文乱码if (StringUtils.isNotEmpty(message)) {outputStream.write(message.getBytes("utf-8"));} else {outputStream.write("".getBytes());}if (null != outputStream)outputStream.close();logger.info("上送服务报文完成...");} catch (Exception e) {e.printStackTrace();throw e;} finally {if (null != outputStream)try {outputStream.close();} catch (IOException e) {e.printStackTrace();}}}public static String receiveMsg(HttpURLConnection httpURLConnection) throws IOException {logger.debug("接收服务器响应报文开始...");InputStream in = null;StringBuilder sb = new StringBuilder(1024);BufferedReader br = null;String temp = null;int code = httpURLConnection.getResponseCode();if (200 == code) {in = httpURLConnection.getInputStream();br = new BufferedReader(new InputStreamReader(in, "utf-8"));while (null != (temp = br.readLine())) {sb.append(temp);}} else {in = httpURLConnection.getErrorStream();br = new BufferedReader(new InputStreamReader(in, "utf-8"));while (null != (temp = br.readLine())) {sb.append(temp);}}String str1 = sb.toString();logger.info("报文: [ " + str1 + " ] ");logger.info("接收服务器响应报文完成");return str1;}
}
推送消息代码:
package com.ruim.ifsp.merser.util;import com.gexin.rp.sdk.base.IPushResult;
import com.gexin.rp.sdk.base.impl.*;
import com.gexin.rp.sdk.base.payload.APNPayload;
import com.gexin.rp.sdk.base.payload.Payload;
import com.gexin.rp.sdk.base.uitls.Base64Util;
import com.gexin.rp.sdk.base.uitls.LangUtil;
import com.gexin.rp.sdk.base.uitls.SignUtil;
import com.gexin.rp.sdk.http.IGtPush;
import com.gexin.rp.sdk.http.utils.GTConfig;
import com.gexin.rp.sdk.http.utils.ParamUtils;
import com.gexin.rp.sdk.template.LinkTemplate;
import com.gexin.rp.sdk.template.NotificationTemplate;
import com.ruim.ifsp.exception.BizException;
import com.ruim.ifsp.log.IfspLoggerFactory;
import com.ruim.ifsp.merser.cache.CommonConstants;
import com.ruim.ifsp.utils.message.IfspFastJsonUtil;
import com.ruim.ifsp.utils.verify.IfspDataVerifyUtil;
import org.slf4j.Logger;import java.net.HttpURLConnection;
import java.time.format.TextStyle;
import java.util.*;public class IGtpushThread extends Thread {private static Logger log = IfspLoggerFactory.getLogger(IGtpushThread.class);private static String appId = CommonConstants.getProperties("IGTAPP_ID");;private static String appKey = CommonConstants.getProperties("IGTAPP_KEY");private static String masterSecret = CommonConstants.getProperties("IGTMASTER_SECRET");private static String host = CommonConstants.getProperties("IGTPUST_HOST");private String alias;private String message;private String msgSendType;public IGtpushThread(String alias,String message,String msgSendType) {
// super();this.alias = alias;this.message = message;this.msgSendType = msgSendType;}/*** If this thread was constructed using a separate* <code>Runnable</code> run object, then that* <code>Runnable</code> object's <code>run</code> method is called;* otherwise, this method does nothing and returns.* <p>* Subclasses of <code>Thread</code> should override this method.** @see #start()* @see #stop()* @see #(ThreadGroup, Runnable, String)*/@Overridepublic void run() {IGTpushMsg(alias,message,msgSendType);}public void IGTpushMsg(String alias,String message,String msgSendType){String respMsg = new String();String[] arr = alias.split(",");// 通知透传模板 消息传递NotificationTemplate template = notificationTemplateDemo(message);ListMessage messages = new ListMessage();messages.setData(template);// 设置消息离线,并设置离线时间messages.setOffline(true);// 离线有效时间,单位为毫秒,可选messages.setOfflineExpireTime(24 * 1000 * 3600);// 配置推送目标List targets = new ArrayList();// taskId用于在推送时去查找对应的messagetry{String taskId = getListAppContentId(messages,null);Map<String,Object> postData = null;for (int i = 0; i < arr.length; i++) {Target target = new Target();target.setAppId(appId);target.setAlias(arr[i]);targets.add(target);//每50个别名(CID)推送一次if (arr.length>50&&targets.size()==50){postData =pushMessageToList(taskId,targets);Map<String,Object> response = httpResponse(postData);if (!"ok".equals(response.get("result"))){response = httpResponse(postData);respMsg = IfspFastJsonUtil.mapTOjson(response);log.info("个推建议值推送结果是:"+respMsg);}targets.clear();}}if (targets.size()>0){postData =pushMessageToList(taskId,targets);Map<String,Object> response = httpResponse(postData);if (!"ok".equals(response.get("result"))){response = httpResponse(postData);respMsg = IfspFastJsonUtil.mapTOjson(response);log.info("个推第二次推送结果是:"+respMsg);}}}catch (Exception e){log.error("个推推送失败,原因是:"+e.getMessage());}}public Map<String, Object> pushMessageToList(String contentId, List<Target> targetList) throws Exception{Map<String, Object> postData = new HashMap();postData.put("authToken", null);postData.put("action", "pushMessageToListAction");postData.put("appkey", appKey);postData.put("contentId", contentId);boolean needDetails = GTConfig.isPushListNeedDetails();postData.put("needDetails", needDetails);boolean async = GTConfig.isPushListAsync();postData.put("async", async);boolean needAliasDetails = GTConfig.isPushListNeedAliasDetails();postData.put("needAliasDetails", needAliasDetails);int limit;if (async && !needDetails) {limit = GTConfig.getAsyncListLimit();} else {limit = GTConfig.getSyncListLimit();}if (targetList.size() > limit) {throw new BizException("1000","target size:" + targetList.size() + " beyond the limit:" + limit);} else {List<String> clientIdList = new ArrayList();List<String> aliasList = new ArrayList();String appId = null;Iterator var12 = targetList.iterator();while(true) {Target target;do {if (!var12.hasNext()) {postData.put("appId", appId);postData.put("clientIdList", clientIdList);postData.put("aliasList", aliasList);postData.put("type", 2);return postData;}target = (Target)var12.next();String targetCid = target.getClientId();String targetAlias = target.getAlias();if (targetCid != null && !"".equals(targetCid.trim())) {clientIdList.add(targetCid);} else if (targetAlias != null && !"".equals(targetAlias.trim())) {aliasList.add(targetAlias);}} while(appId != null && !"".equals(appId.trim()));appId = target.getAppId();}}//苹果参数组装}public NotificationTemplate notificationTemplateDemo(String message) {NotificationTemplate template = new NotificationTemplate();// 设置APPID与APPKEYtemplate.setAppId(appId);template.setAppkey(appKey);// 设置通知栏标题与内容template.setTitle("");template.setText("");
// // 配置通知栏图标
// template.setLogo("icon.png");// 配置通知栏网络图标
// template.setLogoUrl("");// 设置通知是否响铃,震动,或者可清除
// template.setIsRing(true);
// template.setIsVibrate(true);
// template.setIsClearable(true);// 透传消息设置,1为强制启动应用,客户端接收到消息后就会立即启动应用;2为等待应用启动template.setTransmissionType(2);template.setTransmissionContent(message);//ios 消息推送
// APNPayload apnPayload = new APNPayload();
// APNPayload.SimpleAlertMsg alertMsg = new APNPayload.SimpleAlertMsg(message);
// apnPayload.setAlertMsg(alertMsg);
// template.setAPNInfo(apnPayload);return template;}public static void main(String[] args) throws Exception {//单推测试
// LinkTemplate template = linkTemplateDemo();
// SingleMessage message = new SingleMessage();
// message.setOffline(true);
// // 离线有效时间,单位为毫秒,可选
// message.setOfflineExpireTime(24 * 3600 * 1000);
// message.setData(template);
// // 可选,1为wifi,0为不限制网络环境。根据手机处于的网络情况,决定是否下发
// message.setPushNetWorkType(0);
// Target target = new Target();
// target.setAppId(appId);
// target.setAlias("201006700000010_18611111116");
// IPushResult ret = null;
// Map<String,Object> reqMap = getSingleMessagePostData(message,target,null);
// String requestMsg = IfspFastJsonUtil.mapTOjson(reqMap);
// long startTime=System.currentTimeMillis();HttpURLConnection client = null;
// try {
// HttpURLConnection client = null;
// client = IGtpushHttpClient.buildConnect(reqMap.get("action").toString());
// IGtpushHttpClient.sendMsg(client, requestMsg);
// String respMsg =IGtpushHttpClient.receiveMsg(client);
// client.disconnect();
// Map<String,Object> responseDate = (Map<String, Object>) IfspFastJsonUtil.jsonTOmap(respMsg);
// if ("sign_error".equals(responseDate.get("result"))){
// Map<String,Object> post = new HashMap<>();
// long timeStamp = System.currentTimeMillis();
// String sign = SignUtil.getSign(appKey, masterSecret, timeStamp);
// post.put("action", "connect");
// post.put("appkey", appKey);
// post.put("timeStamp", timeStamp);
// post.put("sign", sign);
// post.put("version", GTConfig.getSDKVersion());
// client = IGtpushHttpClient.buildConnect(post.get("action").toString());
// IGtpushHttpClient.sendMsg(client, IfspFastJsonUtil.mapTOjson(post).toString());
// String resp = IGtpushHttpClient.receiveMsg(client);
// Map<String,Object> respDate = (Map<String, Object>) IfspFastJsonUtil.jsonTOmap(resp);
// reqMap.put("authToken",respDate.get("authtoken"));
// client.disconnect();
// }
// client = IGtpushHttpClient.buildConnect(reqMap.get("action").toString());client.setRequestProperty("Gt-Action",reqMap.get("action").toString());
// String reqMsg = IfspFastJsonUtil.mapTOjson(reqMap);
// IGtpushHttpClient.sendMsg(client, reqMsg);
// String respMseeage =IGtpushHttpClient.receiveMsg(client);
//
// } catch (Exception e) {
//try {client = IGtpushHttpClient.buildConnect();IGtpushHttpClient.sendMsg(client, requestMsg);IGtpushHttpClient.receiveMsg(client);} catch (Exception e1) {
// e.printStackTrace();}
// }finally {if(client != null){client.disconnect();}
// }
// long endTime=System.currentTimeMillis();
// }
// 群推测试// 通知透传模板
// NotificationTemplate template = notificationTemplateDemo();
// ListMessage message = new ListMessage();
// message.setData(template);
// // 设置消息离线,并设置离线时间
// message.setOffline(true);
// // 离线有效时间,单位为毫秒,可选
// message.setOfflineExpireTime(24 * 1000 * 3600);
// // 配置推送目标
// List targets = new ArrayList();
// Target target1 = new Target();
// Target target2 = new Target();
// target1.setAppId(appId);
// target1.setAlias("201006700000010_18611111116");
// targets.add(target1);
// // taskId用于在推送时去查找对应的message
// String taskId = getListAppContentId(message,null);
// Map<String, Object> ret = pushMessageToList(taskId, targets);String requestMsg = IfspFastJsonUtil.mapTOjson(ret);
// long startTime=System.currentTimeMillis();
// HttpURLConnection client = null;
// try {
// ret.put("version", GTConfig.getSDKVersion());
// ret.put("authToken",null);
// String requestMsg = IfspFastJsonUtil.mapTOjson(ret);
// client = IGtpushHttpClient.buildConnect(ret.get("action").toString());
// IGtpushHttpClient.sendMsg(client, requestMsg);
// String response = IGtpushHttpClient.receiveMsg(client);
// client.disconnect();
// Map<String,Object> responseDate = (Map<String, Object>) IfspFastJsonUtil.jsonTOmap(response);
// if ("sign_error".equals(responseDate.get("result"))){
// Map<String,Object> post = new HashMap<>();
// long timeStamp = System.currentTimeMillis();
// String sign = SignUtil.getSign(appKey, masterSecret, timeStamp);
// post.put("action", "connect");
// post.put("appkey", appKey);
// post.put("timeStamp", timeStamp);
// post.put("sign", sign);
// post.put("version", GTConfig.getSDKVersion());
// client = IGtpushHttpClient.buildConnect(post.get("action").toString());
// IGtpushHttpClient.sendMsg(client, IfspFastJsonUtil.mapTOjson(post).toString());
// String resp = IGtpushHttpClient.receiveMsg(client);
// Map<String,Object> respDate = (Map<String, Object>) IfspFastJsonUtil.jsonTOmap(resp);
// ret.put("authToken",respDate.get("authtoken"));
// client.disconnect();
// }
// client = IGtpushHttpClient.buildConnect(ret.get("action").toString());
// String reqMsg = IfspFastJsonUtil.mapTOjson(ret);
// IGtpushHttpClient.sendMsg(client, reqMsg);
// String respMseeage =IGtpushHttpClient.receiveMsg(client);
// System.out.println(respMseeage);
// } catch (Exception e) {
// e.printStackTrace();
// }finally {
// if(client != null){
// client.disconnect();
// }
// }}private String getListAppContentId(Message message, String taskGroupName) {Map<String, Object> postData = new HashMap();Map<String, Object> response = null;if (taskGroupName != null) {postData.put("taskGroupName", taskGroupName);}postData.put("action", "getContentIdAction");postData.put("appkey", appKey);postData.put("clientData", Base64Util.getBASE64(message.getData().getTransparent().toByteArray()));postData.put("transmissionContent", message.getData().getTransmissionContent());postData.put("isOffline", message.isOffline());postData.put("offlineExpireTime", message.getOfflineExpireTime());postData.put("pushType", message.getData().getPushType());postData.put("type", 2);if (message instanceof ListMessage) {postData.put("contentType", 1);} else if (message instanceof AppMessage) {postData.put("contentType", 2);AppMessage appMessage = (AppMessage) message;ParamUtils.checkAppid(message, appMessage.getAppIdList());postData.put("appIdList", appMessage.getAppIdList());List<String> phoneTypeList = null;List<String> provinceList = null;List<String> tagList = null;new ArrayList();if (appMessage.getConditions() == null) {phoneTypeList = appMessage.getPhoneTypeList();provinceList = appMessage.getProvinceList();tagList = appMessage.getTagList();postData.put("phoneTypeList", phoneTypeList);postData.put("provinceList", provinceList);postData.put("tagList", tagList);} else {List<Map<String, Object>> conditions = appMessage.getConditions().getCondition();}postData.put("speed", appMessage.getSpeed());String pushTime = appMessage.getPushTime();if (pushTime != null && !pushTime.isEmpty()) {postData.put("pushTime", pushTime);}}postData.put("pushNetWorkType", message.getPushNetWorkType());//调用个推 获取绑定的个推平台信息绑定的idresponse = httpResponse(postData);String result = LangUtil.parseString(response.get("result"));String contentId = LangUtil.parseString(response.get("contentId"));if ("ok".equals(result) && contentId != null) {return contentId;} else {throw new RuntimeException("host:[" + host + "]获取contentId失败:" + result);}}/*** http 调用方法* @param postData* @return*/public Map<String,Object> httpResponse(Map<String,Object> postData){HttpURLConnection client = null;String response = null;try {postData.put("version", GTConfig.getSDKVersion());postData.put("authToken",null);client = IGtpushHttpClient.buildConnect(postData.get("action").toString());IGtpushHttpClient.sendMsg(client, IfspFastJsonUtil.mapTOjson(postData).toString());response =IGtpushHttpClient.receiveMsg(client);client.disconnect();Map<String,Object> respData =(Map<String,Object>)IfspFastJsonUtil.jsonTOmap(response);if ("ok".equals(respData.get("result"))){return respData;}if("sign_error".equals(respData.get("result"))){long timeStamp = System.currentTimeMillis();String sign = SignUtil.getSign(appKey, masterSecret, timeStamp);Map<String, Object> postData1 = new HashMap();postData1.put("action", "connect");postData1.put("appkey", appKey);postData1.put("timeStamp", timeStamp);postData1.put("sign", sign);postData1.put("version", GTConfig.getSDKVersion());client = IGtpushHttpClient.buildConnect(postData1.get("action").toString());IGtpushHttpClient.sendMsg(client, IfspFastJsonUtil.mapTOjson(postData1).toString());response =IGtpushHttpClient.receiveMsg(client);client.disconnect();Map<String,Object> respdata =(Map<String,Object>)IfspFastJsonUtil.jsonTOmap(response);//放入authToken 值postData.put("authToken",respdata.get("authtoken"));client = IGtpushHttpClient.buildConnect(postData.get("action").toString());IGtpushHttpClient.sendMsg(client, IfspFastJsonUtil.mapTOjson(postData).toString());response =IGtpushHttpClient.receiveMsg(client);client.disconnect();respData =(Map<String,Object>)IfspFastJsonUtil.jsonTOmap(response);if ("ok".equals(respData.get("result"))){return respData;}}} catch (Exception e) {e.printStackTrace();}return null;}
}
运行时需要引入个推的jar包,maven 引入时需要先将jar包上传到服务器中,然后在maven配置文件中。我是用的版本jra包是:
至于详细的文档可以参考官方提供的文档,地址:http://docs.getui.com/getui/server/java/start/
使用个推的时候如果不使用代理的话可以直接使用下载的文件中test工程中的代码,集成jra包后,可以参考单推,群推,直接使用。如果使用代理的话就需要重新写http链接。
个推的单推接口调用没有频次的限制,群推pushToList 接口调用是有频次限制的,就是每天调用200万次,每次发给用户数量建议50,pushToapp 每天不超过100次,每分钟不能超过5次。
使用官方提供的接口时:
每次初始化IGtPush这个类的时候都会去个推平台查询那些可用的推送地址。
然后推送消息的时候,步骤就如我画的流程图一样了,只不过单推pushTosigle 时没有获取TaskId这一步。
—————二更—————————
由于我是使用的服务端,不区分安卓和ios所以使用的消息模板NotificationTemplate(通知)不能够满足要求(这个模板如果添加了iOS带码的话,就不能推送安卓了)所以要将消息模板换成TransmissionTemplate(透传)这个模板,然后在模板中设置三方通知。具体的代码如下:
package com.ruim.ifsp.merser.util;import com.gexin.rp.sdk.base.impl.*;
import com.gexin.rp.sdk.base.notify.Notify;
import com.gexin.rp.sdk.base.payload.APNPayload;
import com.gexin.rp.sdk.base.uitls.Base64Util;
import com.gexin.rp.sdk.base.uitls.LangUtil;
import com.gexin.rp.sdk.base.uitls.SignUtil;
import com.gexin.rp.sdk.dto.GtReq;
import com.gexin.rp.sdk.http.utils.GTConfig;
import com.gexin.rp.sdk.http.utils.ParamUtils;
import com.gexin.rp.sdk.template.TransmissionTemplate;
import com.ruim.ifsp.exception.BizException;
import com.ruim.ifsp.log.IfspLoggerFactory;
import com.ruim.ifsp.merser.cache.CommonConstants;
import com.ruim.ifsp.utils.message.IfspFastJsonUtil;
import org.slf4j.Logger;import java.net.HttpURLConnection;
import java.util.*;public class IGtpushThread extends Thread {private static Logger log = IfspLoggerFactory.getLogger(IGtpushThread.class);private static String appId = CommonConstants.getProperties("IGTAPP_ID");private static String appKey = CommonConstants.getProperties("IGTAPP_KEY");private static String masterSecret = CommonConstants.getProperties("IGTMASTER_SECRET");private static String host = CommonConstants.getProperties("IGTPUST_HOST");private String alias;private String message;private String msgSendType;public IGtpushThread(String alias,String message,String msgSendType) {this.alias = alias;this.message = message;this.msgSendType = msgSendType;}/*** If this thread was constructed using a separate* <code>Runnable</code> run object, then that* <code>Runnable</code> object's <code>run</code> method is called;* otherwise, this method does nothing and returns.* <p>* Subclasses of <code>Thread</code> should override this method.** @see #start()* @see #stop()* @see #(ThreadGroup, Runnable, String)*/@Overridepublic void run() {IGTpushMsg(alias,message,msgSendType);}public void IGTpushMsg(String alias,String message,String msgSendType){String respMsg = new String();String[] arr = alias.split(",");// 通知透传模板 消息传递TransmissionTemplate template = notificationTemplateDemo(message);ListMessage messages = new ListMessage();messages.setData(template);// 设置消息离线,并设置离线时间messages.setOffline(true);// 离线有效时间,单位为毫秒,可选messages.setOfflineExpireTime(24 * 1000 * 3600);// 配置推送目标List targets = new ArrayList();// taskId用于在推送时去查找对应的messagetry{String taskId = getListAppContentId(messages,null);Map<String,Object> postData = null;for (int i = 0; i < arr.length; i++) {Target target = new Target();target.setAppId(appId);target.setAlias(arr[i]);targets.add(target);//每50个别名(CID)推送一次if (arr.length>50&&targets.size()==50){postData =pushMessageToList(taskId,targets);Map<String,Object> response = httpResponse(postData);if (!"ok".equals(response.get("result"))){response = httpResponse(postData);respMsg = IfspFastJsonUtil.mapTOjson(response);log.info("个推建议值推送结果是:"+respMsg);}targets.clear();}}if (targets.size()>0){postData =pushMessageToList(taskId,targets);Map<String,Object> response = httpResponse(postData);if (!"ok".equals(response.get("result"))){response = httpResponse(postData);respMsg = IfspFastJsonUtil.mapTOjson(response);log.info("个推第二次推送结果是:"+respMsg);}}}catch (Exception e){log.error("个推推送失败,原因是:"+e.getMessage());}}public Map<String, Object> pushMessageToList(String contentId, List<Target> targetList) throws Exception{Map<String, Object> postData = new HashMap();postData.put("authToken", null);postData.put("action", "pushMessageToListAction");postData.put("appkey", appKey);postData.put("contentId", contentId);boolean needDetails = GTConfig.isPushListNeedDetails();postData.put("needDetails", needDetails);boolean async = GTConfig.isPushListAsync();postData.put("async", async);boolean needAliasDetails = GTConfig.isPushListNeedAliasDetails();postData.put("needAliasDetails", needAliasDetails);int limit;if (async && !needDetails) {limit = GTConfig.getAsyncListLimit();} else {limit = GTConfig.getSyncListLimit();}if (targetList.size() > limit) {throw new BizException("1000","target size:" + targetList.size() + " beyond the limit:" + limit);} else {List<String> clientIdList = new ArrayList();List<String> aliasList = new ArrayList();String appId = null;Iterator var12 = targetList.iterator();while(true) {Target target;do {if (!var12.hasNext()) {postData.put("appId", appId);postData.put("clientIdList", clientIdList);postData.put("aliasList", aliasList);postData.put("type", 2);return postData;}target = (Target)var12.next();String targetCid = target.getClientId();String targetAlias = target.getAlias();if (targetCid != null && !"".equals(targetCid.trim())) {clientIdList.add(targetCid);} else if (targetAlias != null && !"".equals(targetAlias.trim())) {aliasList.add(targetAlias);}} while(appId != null && !"".equals(appId.trim()));appId = target.getAppId();}}}public TransmissionTemplate notificationTemplateDemo(String message) {
// NotificationTemplate template = new NotificationTemplate();
// // 设置APPID与APPKEY
// template.setAppId(appId);
// template.setAppkey(appKey);
// // 设置通知栏标题与内容
// template.setTitle("黔农E付收款通知");
// template.setText(message);
// // 配置通知栏图标
// template.setLogo("icon.png");// 配置通知栏网络图标
// template.setLogoUrl("");// 设置通知是否响铃,震动,或者可清除
// template.setIsRing(true);
// template.setIsVibrate(true);
// template.setIsClearable(true);// 透传消息设置,1为强制启动应用,客户端接收到消息后就会立即启动应用;2为等待应用启动
// template.setTransmissionType(2);
// template.setTransmissionContent(message);//ios 消息推送
// APNPayload apnPayload = new APNPayload();
// APNPayload.SimpleAlertMsg alertMsg = new APNPayload.SimpleAlertMsg(message);
// apnPayload.setAlertMsg(alertMsg);
// template.setAPNInfo(apnPayload);
// return template;TransmissionTemplate template = new TransmissionTemplate();template.setAppId(appId);template.setAppkey(appKey);//设置透传消息template.setTransmissionContent(message);template.setTransmissionType(2);//设置三方通知Notify no = new Notify();no.setTitle("黔农E付收款通知!");no.setContent(message);no.setIntent(""); //客户端生成提供给服务端no.setType(GtReq.NotifyInfo.Type._intent);template.set3rdNotifyInfo(no);//设置ios推送消息APNPayload payload = new APNPayload();payload.setBadge(1);payload.setContentAvailable(1);payload.setSound("default");payload.setCategory("$由客户端定义");//简单模式APNPayload.SimpleMsgpayload.setAlertMsg(new APNPayload.SimpleAlertMsg(message));//字典模式使用下者//payload.setAlertMsg(getDictionaryAlertMsg());template.setAPNInfo(payload);return template;}private String getListAppContentId(Message message, String taskGroupName) {Map<String, Object> postData = new HashMap();Map<String, Object> response = null;if (taskGroupName != null) {postData.put("taskGroupName", taskGroupName);}postData.put("action", "getContentIdAction");postData.put("appkey", appKey);postData.put("clientData", Base64Util.getBASE64(message.getData().getTransparent().toByteArray()));postData.put("transmissionContent", message.getData().getTransmissionContent());postData.put("isOffline", message.isOffline());postData.put("offlineExpireTime", message.getOfflineExpireTime());postData.put("pushType", message.getData().getPushType());postData.put("type", 2);if (message instanceof ListMessage) {postData.put("contentType", 1);} else if (message instanceof AppMessage) {postData.put("contentType", 2);AppMessage appMessage = (AppMessage) message;ParamUtils.checkAppid(message, appMessage.getAppIdList());postData.put("appIdList", appMessage.getAppIdList());List<String> phoneTypeList = null;List<String> provinceList = null;List<String> tagList = null;new ArrayList();if (appMessage.getConditions() == null) {phoneTypeList = appMessage.getPhoneTypeList();provinceList = appMessage.getProvinceList();tagList = appMessage.getTagList();postData.put("phoneTypeList", phoneTypeList);postData.put("provinceList", provinceList);postData.put("tagList", tagList);} else {List<Map<String, Object>> conditions = appMessage.getConditions().getCondition();}postData.put("speed", appMessage.getSpeed());String pushTime = appMessage.getPushTime();if (pushTime != null && !pushTime.isEmpty()) {postData.put("pushTime", pushTime);}}postData.put("pushNetWorkType", message.getPushNetWorkType());//调用个推 获取绑定的个推平台信息绑定的idresponse = httpResponse(postData);String result = LangUtil.parseString(response.get("result"));String contentId = LangUtil.parseString(response.get("contentId"));if ("ok".equals(result) && contentId != null) {return contentId;} else {throw new RuntimeException("host:[" + host + "]获取contentId失败:" + result);}}/*** http 调用方法* @param postData* @return*/public Map<String,Object> httpResponse(Map<String,Object> postData){HttpURLConnection client = null;String response = null;try {postData.put("version", GTConfig.getSDKVersion());postData.put("authToken",null);client = IGtpushHttpClient.buildConnect(postData.get("action").toString());IGtpushHttpClient.sendMsg(client, IfspFastJsonUtil.mapTOjson(postData).toString());response =IGtpushHttpClient.receiveMsg(client);client.disconnect();Map<String,Object> respData =(Map<String,Object>)IfspFastJsonUtil.jsonTOmap(response);if ("ok".equals(respData.get("result"))){return respData;}if("sign_error".equals(respData.get("result"))){long timeStamp = System.currentTimeMillis();String sign = SignUtil.getSign(appKey, masterSecret, timeStamp);Map<String, Object> postData1 = new HashMap();postData1.put("action", "connect");postData1.put("appkey", appKey);postData1.put("timeStamp", timeStamp);postData1.put("sign", sign);postData1.put("version", GTConfig.getSDKVersion());client = IGtpushHttpClient.buildConnect(postData1.get("action").toString());IGtpushHttpClient.sendMsg(client, IfspFastJsonUtil.mapTOjson(postData1).toString());response =IGtpushHttpClient.receiveMsg(client);client.disconnect();Map<String,Object> respdata =(Map<String,Object>)IfspFastJsonUtil.jsonTOmap(response);//放入authToken 值postData.put("authToken",respdata.get("authtoken"));client = IGtpushHttpClient.buildConnect(postData.get("action").toString());IGtpushHttpClient.sendMsg(client, IfspFastJsonUtil.mapTOjson(postData).toString());response =IGtpushHttpClient.receiveMsg(client);client.disconnect();respData =(Map<String,Object>)IfspFastJsonUtil.jsonTOmap(response);if ("ok".equals(respData.get("result"))){return respData;}}} catch (Exception e) {e.printStackTrace();}return null;}//苹果消息弹出框private static APNPayload.DictionaryAlertMsg getDictionaryAlertMsg(){APNPayload.DictionaryAlertMsg alertMsg = new APNPayload.DictionaryAlertMsg();alertMsg.setBody("body");alertMsg.setActionLocKey("ActionLockey");alertMsg.setLocKey("LocKey");alertMsg.addLocArg("loc-args");alertMsg.setLaunchImage("launch-image");// IOS8.2以上版本支持alertMsg.setTitle("Title");alertMsg.setTitleLocKey("TitleLocKey");alertMsg.addTitleLocArg("TitleLocArg");return alertMsg;}
}
透传模板集成到通知中官方提供文档:
1. 概述
解决接入第三方推送遇到的兼容问题,降低接入成本。
2. 功能名字
2.1应用场景
为方便接入了第三方厂商推送的客户,更加简便的使用个推透传模板推送,特别对透传模板进行扩展,使透传模板支持以第三方厂商的通知方式进行下发。目前第三方厂商的通知到达率显著高于第三方透传的到达率。
3. 使用方式
3.1使用说明
使用透传模板时,设置notify对象的title, content, intent等参数。
Notify的说明
成员和方法名 |
类型 |
必填 |
说明 |
setTitle |
String |
是 |
通知栏标题 |
setContent |
String |
是 |
通知栏内容 |
setUrl |
String |
否 |
点击通知,打开应用的链接 |
setIntent |
String |
否 |
长度小于1000字节,通知带intent传递参数推荐使用,intent最好由Android开发工程师生成,生成方式见附录 |
setType |
Type |
否 |
取值为(Type._url、Type._intent),如果设置了url、intent,需要指定Type对应的类型;Type所在的包为:com.gexin.rp.sdk.dto.GtReq.NotifyInfo |
public static TransmissionTemplate transmissionTemplateDemo(String appId, String appKey){ TransmissionTemplate template = new TransmissionTemplate(); template.setAppId(appId); template.setAppkey(appKey); template.setTransmissionContent("透传内容"); template.setTransmissionType(2); Notify notify = new Notify(); notify.setTitle("请输入通知栏标题"); notify.setContent("请输入通知栏内容"); notify.setIntent("intent:#Intent;launchFlags=0x10000000;package=com.pp.yl;component=你的包名 /com.getui.demo.MainActivity;i.parm1=12;end"); notify.setType(Type._intent); // notify.setUrl("https://dev.getui.com/"); //notify.setType(Type._url); template.set3rdNotifyInfo(notify);//设置第三方通知 return template; }
|
4. 功能代码示例
5. 附录:Andriod开发工程师生成intent参考
Andriod开发工程师生成intent,可以在Android代码中定义一个Intent,然后通过Intent.toUri(Intent.URI_INTENT_SCHEME)获取对应的Intent Uri。
Intent intent = new Intent();
|
5.1生成Intent
5.2设置 package(可选)
如果设置了package,则表示目标应用必须是package所对应的应用。
intent.setPackage("com.getui.demo"); |
5.3设置 component (必选)
component为目标页面的准确activity路径,component中包含应用包名和activity类的全路径。
intent.setComponent(new ComponentName("com.getui.demo", "com.getui.demo.TestActivity")); |
5.4设置 launchFlags (不起作用)
launcherFlags 可指定在启动activity时的启动方式,个推sdk以及厂商sdk在启动activity时会自动设置为FLAG_ACTIVITY_NEW_TASK,所以该设置没有实际意义。
5.5设置参数
intent.putExtra("stringType", "string"); intent.putExtra("booleanType", true); intent.putExtra("doubleType", 1.0); intent.putExtra("floatType", 1.0f); intent.putExtra("longType", 1L); intent.putExtra("intType", 1); // 还有其他类型的参数可以设置,通过查找`putExtra`方法的重载方法即可 |
可通过intent.putExtra方法设置一系列的参数。
5.6设置action
//设置action intent.setAction("android.intent.action.oppopush"); |
由于oppo sdk仅支持通过action的方式打开activity,所以若您的应用需要支持oppo推送(打开指定页面),您需要在intent中设置action,并在AndroidManifet.xml配置对应的action,如下:
<!– android:exported="true" 必须配置,否则在华为机型上无法启动–> <activity android:name="com.getui.demo.TestActivity" android:exported="true"> <intent-filter> <!– category 为必须设置项 设置为 android.intent.category.DEFAULT 即可–> <category android:name="android.intent.category.DEFAULT" /> <action android:name="android.intent.action.oppopush" /> </intent-filter> </activity> |
AndroidManifet.xml配置如下:
5.7生成 intent uri
Log.d(TAG, intent.toUri(Intent.URI_INTENT_SCHEME)); |
打印结果为:intent:#Intent;action=android.intent.action.oppopush;package=com.getui.demo;component=com.getui.demo/com.getui.demo.TestActivity;f.floatType=1.0;l.longType=1;B.booleanType=true;S.stringType=string;d.doubleType=1.0;i.intType=1;end
将生成的intent uri交给服务端开发人员,在对应模板的setIntent方法中设置即可。
=====================三更====================================
使用jmeter测试,发现每次访问个推平台消耗时间大概是300毫秒左右,发送一次推送如果走完所有的流程,需要大概2500毫秒,很耗时间。而且,目前在生产上有用户反馈收不到推送信息,经过排查得知当日的推送消息次数超过了200万次,而多推pushListMessage有这个次数限制。所以需要优化这个推送流程。经过询问个推的开发人员得知,在交互的过程中获取鉴权码,鉴权码的有效期是24个小时,另外接口pushSingleMessage推送是没有次数限制。本次优化的流程思路就是将鉴权码保存到redis中,并设置有效期,推送接口使用单推+多推相结合的方式行优化。目前从测试结果来开个推使用还是有些问题。问题一:个推使用多推时离线发送(只有ios,所谓离线就是退出app页面,个推离线推送的时候会将消息推送给厂商,厂商将消息推送到设备,这个时间不可控,测试环境中,有时间延时,个推厂商给解释说开发环境苹果厂商推送不稳定)会有1~2分钟的时延。问题二:个推使用单推的时候,ios手机推出app,收不到推送消息,个推开发人员解释是开发环境苹果厂商aoip 推送不稳。鉴于这两种给推送结果,目前占时开发出两套优化流程 1. 单推+多推(生产上测试,测试没有问题,优先使用这个),2.多推 (1不行才采用这个方)
优化后代码流程:
1.单推:
2.多推:
优化后代码:
/***@author lxw*@date 2019/12/20*@desc 安卓群推*@param alias, message, msgSendType*@return void**/public void IGTandroidPushMsg(String alias,String message){log.info("安卓用户{}开始推送日志.....",alias);String respMsg = new String();String[] arr = alias.split(",");// 通知透传模板 消息传递NotificationTemplate nTemplate = notificationTemplateDemo(message);ListMessage messages = new ListMessage();messages.setData(nTemplate);// 设置消息离线,并设置离线时间messages.setOffline(true);// 离线有效时间,单位为毫秒,可选messages.setOfflineExpireTime(24 * 1000 * 3600);// 配置推送目标List targets = new ArrayList();// taskId用于在推送时去查找对应的messagetry{String taskId = getListAppContentId(messages,null);Map<String,Object> postData = null;for (int i = 0; i < arr.length; i++) {Target target = new Target();target.setAppId(appId);target.setAlias(arr[i]);targets.add(target);//每50个别名(CID)推送一次if (arr.length>50&&targets.size()==50){postData =pushMessageToList(taskId,targets);Map<String,Object> response = httpResponse(postData);if (!IGParams.PUSH_MSG_OK.equals(response.get("result"))){response = httpResponse(postData);respMsg = IfspFastJsonUtil.mapTOjson(response);}targets.clear();}}if (targets.size()>0) {postData = pushMessageToList(taskId, targets);Map<String, Object> response = httpResponse(postData);if (IGParams.PUSH_NO_TARGET.equals(response.get("result"))||IGParams.PUSH_MSG_OK.equals(response.get("result"))) {log.info("用户{}个推推送结果是:" + response.get("result"),alias);}else {response = httpResponse(postData);respMsg = IfspFastJsonUtil.mapTOjson(response);log.info("用户{}个推第二次推送结果是:" + respMsg,alias);}}}catch (Exception e){log.error("安卓用户{}推送失败,原因是:"+e.getMessage(),alias);}}/***@author lxw*@date 2019/12/20*@desc 苹果群推*@param alias, message, msgSendType*@return void**/public void IGTIosPushMsg(String alias,String message){log.info("ios用户{}开始推送.....",alias);String respMsg = new String();String[] arr = alias.split(",");//透传模板 消息传递TransmissionTemplate tTemplate = transmissionTemplateDemo(message);ListMessage messages = new ListMessage();messages.setData(tTemplate);// 设置消息离线,并设置离线时间messages.setOffline(true);// 离线有效时间,单位为毫秒,可选messages.setOfflineExpireTime(24 * 1000 * 3600);// 配置推送目标List targets = new ArrayList();// taskId用于在推送时去查找对应的messagetry{String taskId = getListAppContentId(messages,null);Map<String,Object> postData = null;for (int i = 0; i < arr.length; i++) {Target target = new Target();target.setAppId(appId);target.setAlias(arr[i]);targets.add(target);//每50个别名(CID)推送一次if (arr.length>50&&targets.size()==50){postData =pushMessageToList(taskId,targets);Map<String,Object> response = httpResponse(postData);if (!IGParams.PUSH_MSG_OK.equals(response.get("result"))){response = httpResponse(postData);respMsg = IfspFastJsonUtil.mapTOjson(response);}targets.clear();}}if (targets.size()>0){postData =pushMessageToList(taskId,targets);Map<String,Object> response = httpResponse(postData);if (IGParams.PUSH_NO_TARGET.equals(response.get("result"))||IGParams.PUSH_MSG_OK.equals(response.get("result"))) {log.info("用户{}个推推送结果是:" + response.get("result"),alias);}else {response = httpResponse(postData);respMsg = IfspFastJsonUtil.mapTOjson(response);log.info("用户{}再次推送结果是:" + response.get("result"),alias);}}}catch (Exception e){log.error("ios用户{}推送失败,原因是:"+e.getMessage(),alias);}}/***@author lxw*@date 2019/12/20*@desc 群推消息参数组装*@param contentId, targetList*@return java.util.Map<java.lang.String,java.lang.Object>**/public Map<String, Object> pushMessageToList(String contentId, List<Target> targetList) throws Exception{log.info("pushMessageToList组装推送参数开始,用户taskid:{}。。。。",contentId);Map<String, Object> postData = new HashMap();postData.put("authToken", getAuthTokenCache().opsForValue().get("authToken")==null?"":getAuthTokenCache().opsForValue().get("authToken"));postData.put("action", "pushMessageToListAction");postData.put("appkey", appKey);postData.put("contentId", contentId);boolean needDetails = GTConfig.isPushListNeedDetails();postData.put("needDetails", needDetails);boolean async = GTConfig.isPushListAsync();postData.put("async", async);boolean needAliasDetails = GTConfig.isPushListNeedAliasDetails();postData.put("needAliasDetails", needAliasDetails);int limit;if (async && !needDetails) {limit = GTConfig.getAsyncListLimit();} else {limit = GTConfig.getSyncListLimit();}if (targetList.size() > limit) {throw new BizException("1000","target size:" + targetList.size() + " beyond the limit:" + limit);} else {List<String> clientIdList = new ArrayList();List<String> aliasList = new ArrayList();String appId = null;Iterator var12 = targetList.iterator();while(true) {Target target;do {if (!var12.hasNext()) {postData.put("appId", appId);postData.put("clientIdList", clientIdList);postData.put("aliasList", aliasList);postData.put("type", 2);return postData;}target = (Target)var12.next();String targetCid = target.getClientId();String targetAlias = target.getAlias();if (targetCid != null && !"".equals(targetCid.trim())) {clientIdList.add(targetCid);} else if (targetAlias != null && !"".equals(targetAlias.trim())) {aliasList.add(targetAlias);}} while(appId != null && !"".equals(appId.trim()));appId = target.getAppId();}}}//通知消息public NotificationTemplate notificationTemplateDemo(String message) {NotificationTemplate template = new NotificationTemplate();// 设置APPID与APPKEYtemplate.setAppId(appId);template.setAppkey(appKey);Style0 style = new Style0();style.setTitle("黔农E付收款通知");// 设置通知栏标题与内容style.setText(message);// 配置通知栏网络图标style.setLogo("icon.png");// 设置通知是否响铃,震动,或者可清除style.setRing(true);style.setVibrate(true);style.setClearable(true);// 透传消息设置,1为强制启动应用,客户端接收到消息后就会立即启动应用;2为等待应用启动template.setTransmissionType(1);template.setTransmissionContent(message);template.setStyle(style);return template;}//透传消息public TransmissionTemplate transmissionTemplateDemo(String message) {Map<String,String> msgMap = new HashMap<>();msgMap.put("黔农商户宝",message);TransmissionTemplate template = new TransmissionTemplate();template.setAppId(appId);template.setAppkey(appKey);//透传消息设置template.setTransmissionContent(IfspFastJsonUtil.mapTOjson(msgMap));template.setTransmissionType(2);//ios 消息推送APNPayload payload = new APNPayload();payload.setAutoBadge("1");payload.setContentAvailable(0);payload.setVoicePlayType(1);payload.setSound("default");payload.setCategory("$由客户端定义");VoIPPayload voIPPayload = new VoIPPayload();Map<String,Object> vp = new HashMap<>();vp.put("titile","黔农E付收款通知");vp.put("message",message);vp.put("payload","payload");voIPPayload.setVoIPPayload(IfspFastJsonUtil.mapTOjson(vp));template.setAPNInfo(voIPPayload);return template;}//获取群推的taskidprivate String getListAppContentId(Message message, String taskGroupName) {Map<String, Object> postData = new HashMap();Map<String, Object> response = null;if (taskGroupName != null) {postData.put("taskGroupName", taskGroupName);}postData.put("action", "getContentIdAction");postData.put("appkey", appKey);postData.put("clientData", Base64Util.getBASE64(message.getData().getTransparent().toByteArray()));postData.put("transmissionContent", message.getData().getTransmissionContent());postData.put("isOffline", message.isOffline());postData.put("offlineExpireTime", message.getOfflineExpireTime());postData.put("pushType", message.getData().getPushType());postData.put("type", 2);if (message instanceof ListMessage) {postData.put("contentType", 1);} else if (message instanceof AppMessage) {postData.put("contentType", 2);AppMessage appMessage = (AppMessage) message;ParamUtils.checkAppid(message, appMessage.getAppIdList());postData.put("appIdList", appMessage.getAppIdList());List<String> phoneTypeList = null;List<String> provinceList = null;List<String> tagList = null;new ArrayList();if (appMessage.getConditions() == null) {phoneTypeList = appMessage.getPhoneTypeList();provinceList = appMessage.getProvinceList();tagList = appMessage.getTagList();postData.put("phoneTypeList", phoneTypeList);postData.put("provinceList", provinceList);postData.put("tagList", tagList);} else {List<Map<String, Object>> conditions = appMessage.getConditions().getCondition();}postData.put("speed", appMessage.getSpeed());String pushTime = appMessage.getPushTime();if (pushTime != null && !pushTime.isEmpty()) {postData.put("pushTime", pushTime);}}postData.put("pushNetWorkType", message.getPushNetWorkType());//调用个推 获取绑定的个推平台信息绑定的idresponse = httpResponse(postData);String result = LangUtil.parseString(response.get("result"));String contentId = LangUtil.parseString(response.get("contentId"));if (IGParams.PUSH_MSG_OK.equals(result) && contentId != null) {return contentId;} else {throw new RuntimeException("host:[" + host + "]获取contentId失败:" + result);}}/*** http 调用方法* @param postData* @return*/public Map<String,Object> httpResponse(Map<String,Object> postData){log.info("调用平台传参:"+IfspFastJsonUtil.mapTOjson(postData));HttpURLConnection client = null;String response = null;Map<String,Object> respData = new HashMap<>();try {postData.put("version", GTConfig.getSDKVersion());postData.put("authToken",getAuthTokenCache().opsForValue().get("authToken")==null?"":getAuthTokenCache().opsForValue().get("authToken"));client = IGtpushHttpClient.buildConnect(postData.get("action").toString());IGtpushHttpClient.sendMsg(client, IfspFastJsonUtil.mapTOjson(postData).toString());response =IGtpushHttpClient.receiveMsg(client);client.disconnect();respData =(Map<String,Object>)IfspFastJsonUtil.jsonTOmap(response);if(IGParams.PUSH_SIGN_ERROR.equals(respData.get("result"))){long timeStamp = System.currentTimeMillis();String sign = SignUtil.getSign(appKey, masterSecret, timeStamp);Map<String, Object> postData1 = new HashMap();postData1.put("action", "connect");postData1.put("appkey", appKey);postData1.put("timeStamp", timeStamp);postData1.put("sign", sign);postData1.put("version", GTConfig.getSDKVersion());client = IGtpushHttpClient.buildConnect(postData1.get("action").toString());IGtpushHttpClient.sendMsg(client, IfspFastJsonUtil.mapTOjson(postData1).toString());response =IGtpushHttpClient.receiveMsg(client);client.disconnect();Map<String,Object> respdata =(Map<String,Object>)IfspFastJsonUtil.jsonTOmap(response);//放入authToken 值postData.put("authToken",respdata.get("authtoken"));//将authToken 放入redis 并设置超时时间getAuthTokenCache().opsForValue().set("authToken",(String)respdata.get("authtoken"),TimeUnit.HOURS.toHours(24),TimeUnit.HOURS);client = IGtpushHttpClient.buildConnect(postData.get("action").toString());IGtpushHttpClient.sendMsg(client, IfspFastJsonUtil.mapTOjson(postData).toString());response =IGtpushHttpClient.receiveMsg(client);client.disconnect();respData =(Map<String,Object>)IfspFastJsonUtil.jsonTOmap(response);return respData;}return respData;} catch (Exception e) {log.error("个推接收响应信息失败,原因是:"+e.getMessage());}return respData;}//苹果消息弹出框private static APNPayload.DictionaryAlertMsg getDictionaryAlertMsg(String message){APNPayload.DictionaryAlertMsg alertMsg = new APNPayload.DictionaryAlertMsg();alertMsg.setBody(message);alertMsg.setTitle("黔农E付收款通知");return alertMsg;}/***@author lxw*@date 2019/12/20*@desc 单推消息参数组装*@param message, target, requestId*@return java.util.Map<java.lang.String,java.lang.Object>**/public Map<String, Object> pushMessageToSingle(Message message, Target target, String requestId) {HttpURLConnection client = null;String response = new String();if (requestId == null || "".equals(requestId.trim())) {requestId = UUID.randomUUID().toString();}Map<String, Object> pushResult = new HashMap<>();ParamUtils.checkAppid(message, target);Map<String, Object> postData = this.getSingleMessagePostData(message, target, requestId);try {pushResult = httpResponse(postData);}catch (Exception e){log.error("单推失败!"+e.getMessage());}return pushResult;}/***@author lxw*@date 2019/12/20*@desc 单推上送消息组装*@param message, target, requestId*@return java.util.Map<java.lang.String,java.lang.Object>**/Map<String, Object> getSingleMessagePostData(Message message, Target target, String requestId) {Map<String, Object> postData = new HashMap();postData.put("action", "pushMessageToSingleAction");postData.put("appkey", this.appKey);if (requestId != null) {postData.put("requestId", requestId);}postData.put("clientData", Base64Util.getBASE64(message.getData().getTransparent().toByteArray()));postData.put("transmissionContent", message.getData().getTransmissionContent());postData.put("isOffline", message.isOffline());postData.put("offlineExpireTime", message.getOfflineExpireTime());postData.put("appId", target.getAppId());postData.put("clientId", target.getClientId());postData.put("alias", target.getAlias());postData.put("type", 2);postData.put("pushType", message.getData().getPushType());postData.put("pushNetWorkType", message.getPushNetWorkType());return postData;}/***@author lxw*@date 2019/12/20*@desc 安卓单推*@param alias, message, msgSendType*@return void**/public void iGSinglePust(String alias,String message) {log.info("安卓用户{}开始推送。。。",alias);NotificationTemplate template = notificationTemplateDemo(message);SingleMessage messages = new SingleMessage();messages.setOffline(true);// 离线有效时间,单位为毫秒,可选messages.setOfflineExpireTime(24 * 3600 * 1000);messages.setData(template);// 可选,1为wifi,0为不限制网络环境。根据手机处于的网络情况,决定是否下发messages.setPushNetWorkType(0);Target target = new Target();target.setAppId(appId);target.setAlias(alias);Map<String, Object> ret = null;try {ret = pushMessageToSingle(messages, target,null);} catch (RequestException e) {log.error("服务器响应异常:"+e.getMessage());ret = pushMessageToSingle(messages, target, e.getRequestId());}}/***@author lxw*@date 2019/12/20*@desc ios单推*@param alias, message, msgSendType*@return void**/public void iGSinglePustIOS(String alias,String message) {log.error("苹果用户{}开始推送",alias);TransmissionTemplate template = transmissionTemplateDemo(message);SingleMessage messages = new SingleMessage();messages.setOffline(true);// 离线有效时间,单位为毫秒,可选messages.setOfflineExpireTime(24 * 3600 * 1000);messages.setData(template);// 可选,1为wifi,0为不限制网络环境。根据手机处于的网络情况,决定是否下发messages.setPushNetWorkType(0);Target target = new Target();target.setAppId(appId);target.setAlias(alias);Map<String, Object> ret = null;try {ret = pushMessageToSingle(messages, target,null);} catch (RequestException e) {log.error("服务器响应异常:"+e.getMessage());ret = pushMessageToSingle(messages, target, e.getRequestId());}}//获取spring中redis 注册的beanpublic IfspRedisCacheOperation<String> getPushRedisCacheOperation(){return (IfspRedisCacheOperation<String>) IfspSpringContextUtils.getInstance().getBean("pushRedisCache");}public IfspRedisCacheOperation<String> getAuthTokenCache(){return (IfspRedisCacheOperation<String>) IfspSpringContextUtils.getInstance().getBean("authTokenRedisCache");}
http 链接还是使用最上方的链接
工具类:
public Static final String PUSH_SIGN_ERROR="sign_error";
public Static final String PUSH_NO_TARGET="NOTarget";
public Static final String PUSH_MSG_OK="ok";
总结:
1.目前生产使用模式是单推+多推结合的方式。
2.个推推送分为 离线推送、在线推送,在线推送是指 个推平台将消息推送给手机,离线推送是指 个推将消息推送给手机厂商,由厂商来推送消息。区分是离线推送还是在线推送,可以查看推送成功后的响应报文中有个推送状态,那里会显示是离线推送还是在线推送。
3.手机接收不到消息问题排查
3.1:核对配置参数是否正确(appId,appKey,masterScript…..);
3.2:如果是使用别名推送,查看推送是否绑定了cid(个推为每个手机设备分配的识别码,每个手机只能生成一个,不会变);个推平台提供了方法查询别名下绑定的cid 个数,每个别名只能绑定10个cid。别名绑定超过10时候,新绑定的cid 会将已经绑定的cid其中一个顶掉。别名下cid 查询:
import com.gexin.rp.sdk.base.IAliasResult;
import com.gexin.rp.sdk.http.IGtPush;public class GETTUIaLIAS {private static String appId = "QFoBXS1TrJ9yc";//个推上配置的appIdprivate static String appKey = "M2FJjXxnP3Ark";//个推上配置的appKey private static String masterSecret = "aWU9lqy8CX6EP";//个推上配置的masterSecret static String host = "http://sdk.open.api.igexin.com/apiex.htm";public static void main(String[] args) {String Alias = "8201807060000001_13641064684";//要查询的别名IGtPush push = new IGtPush(host, appKey, masterSecret);IAliasResult queryClient = push.queryClientId(appId, Alias);System.out.println("根据别名获取的CID:" + queryClient.getClientIdList());}
}
,服务端是获取不到每个手机的cid ,需要客户端(app端) 来获取cid。查看cid 所属苹果或者安卓可以去个推平台
中,输入别名下查询出cid ,就可以查看出手机型号和所属手机厂商。