原博客地址:https://blog.csdn.net/wendy_loves/article/details/78596995
小米推送,华为推送,个推,阿里云推送集成(服务端JAVA开发)
公司新任务中要求集成以上四种推送方式,所以我在这里做下随堂笔记:
这里是官方的文档url:
小米:https://dev.mi.com/mipush/docs/server-sdk/introduction/
华为:http://developer.huawei.com/consumer/cn/service/hms/catalog/huaweipush.html?page=hmssdk_huaweipush_devguide_s
个推:http://docs.getui.com/server/java/template/
阿里云:https://help.aliyun.com/document_detail/48048.html?spm=5176.doc30092.6.604.ivLvNV
博主:qq - 52331395(不喜勿喷,欢迎交流,下述内容来如有误,请留言指出,雷同的应该是没有,我自己写的)
java.jar(小米、个推、阿里云官方很直接给出了maven,个推的maven我本人无法引入,所以我将官方jar打包到私有库里,无法引用的朋友也可以学我使用)
<dependency>
<groupId>com.migroupId>
<artifactId>mipush-sdk-serverartifactId>
<version>2.2.18version>
dependency>
<dependency>
<groupId>com.googlecode.json-simplegroupId>
<artifactId>json-simpleartifactId>
<version>1.1.1version>
dependency>
<dependency>
<groupId>com.gexingroupId>
<artifactId>rp-sdk-baseartifactId>
<version>4.0.0.14version>
dependency>
<dependency>
<groupId>com.gexingroupId>
<artifactId>rp-fastjsonartifactId>
<version>1.0.0.0version>
dependency>
<dependency>
<groupId>com.gexingroupId>
<artifactId>rp-sdk-httpartifactId>
<version>4.0.1.9version>
dependency>
<dependency>
<groupId>com.gexingroupId>
<artifactId>rp-sdk-templateartifactId>
<version>4.0.0.8version>
dependency>
<dependency>
<groupId>com.protobufgroupId>
<artifactId>rp-protobuf-javaartifactId>
<version>2.5.0version>
dependency>
<dependency>
<groupId>com.aliyungroupId>
<artifactId>aliyun-java-sdk-pushartifactId>
<version>3.5.1version>
dependency>
<dependency>
<groupId>com.aliyungroupId>
<artifactId>aliyun-java-sdk-coreartifactId>
<version>3.2.5version>
dependency>
华为 有个自己的http/https方式很便捷
华为官方给出
String HV_TOKEN_URL= “https://login.vmall.com/oauth2/token“;
String HV_API_URL= “https://api.push.hicloud.com/pushsend.do“;
代码展示
1.小米推送(我只推送Android且只应用regId发起推送,所以下面只有推送Android的代码)
1.1构建message
private Message buildMessageForAndroid(String title, String description, String messagePayload,
Integer passThrough, Integer actionType, String actionUrl, Integer notifyType, String extendContent) {
Message message;
Message.Builder builder = new Message.Builder()
.title(title)//标题(注意16字真言限制长度,这段画上重点考)
.description(description)//描述(注意128限制长度,这段画上重点考,这个描述,我理解为副标题,而且在手机客户端呈现的也是标题+描述,内容不会自己显示出来,如果只是为了通知用户信息,我们可以将信息内容放在此处,显示效果比较明显。但是三个文字区域都不可空。需要补充文字方可使用)
.payload(messagePayload)//内容(这个长度够你用了)
.restrictedPackageName(AggregationPushContent.MI_ANDROID_PACKAGE_NAME)//APP包名
.passThrough(passThrough)//是否透传
.notifyType(notifyType)//设置震动,响铃等等
.extra("extend_content", extendContent);//这里要注意下,你可以通过自定义的key传给客户端一段透传参数
if (actionType == 1) {//动作跳转根据自己定义的方式去跳转url,if里的两组.extra是必须要放入的,这段画上重点
builder.extra(Constants.EXTRA_PARAM_NOTIFY_EFFECT, Constants.NOTIFY_ACTIVITY)
.extra(Constants.EXTRA_PARAM_INTENT_URI, actionUrl);
} else if (actionType == 2) {
builder.extra(Constants.EXTRA_PARAM_NOTIFY_EFFECT, Constants.NOTIFY_WEB)
.extra(Constants.EXTRA_PARAM_WEB_URI, actionUrl);
}
message = builder.build();
return message;
}
1.2开始发送
public Result sendMessageToRegId(String messageId, String title, String description,
String messagePayload, Integer passThrough, Integer actionType, String actionUrl, Integer notifyType,
String extendContent, String regId) {
Constants.useOfficial();//这里要注意,这是正式-启动方式,支持IOS跟Android,Constants.useSandbox();这是测试-启动方式,不支持Android,尽量申请正式APP,利用正式环境测试
Sender sender = new Sender("你需要传入你所申请appsecret");
Message message = buildMessageForAndroid(title, description, messagePayload, passThrough, actionType, actionUrl, notifyType, extendContent);
Result result = null;
try {
result = sender.send(message, regId, RETRIES);
} catch (Exception e) {
//log
}
return result;
}
1.3返回值 根据下述返回值自己定义成功与失败吧!
/**
* 发送消息返回的错误码,如果返回ErrorCode.Success表示发送成功,其他表示发送失败。
*/
ErrorCode errorMessage = result.getErrorCode();
/**
* 如果消息发送成功,服务器返回消息的ID;如果发送失败,返回null。
*/
String platformMessageId = result.getMessageId();
/**
* 如果消息发送失败,服务器返回错误原因的文字描述;如果发送成功,返回null。
*/
String reason = result.getReason();
2.华为推送(我只推送Android且只应用deviceToken发起推送,所以下面只有推送Android的代码)
2.1获取应用accessToken(这个token放在redis或者数据库里保存,失效时重新获取,不要发一次,获取一次,因为频繁获取token很有可能获取失败,这也是好的开发规则,自定义失效时间要比实际失效时间减少3-5分钟,把系统耗时放在内,规避掉巧合失效的情况)
/**
* 获取下发通知消息的认证Token
*/
public Map refreshToken() {
String accessToken;//下发通知消息的认证Token
long tokenExpiredTime; //accessToken的过期时间
Map data = Maps.newHashMap();
try {
String msgBody = MessageFormat.format(
"grant_type=client_credentials&client_secret={0}&client_id={1}",
URLEncoder.encode(appSecret, "UTF-8"), appId);
String response = HttpUtil.post(tokenUrl, msgBody);
JSONObject obj = JSONObject.parseObject(response);
accessToken = obj.getString("access_token");
tokenExpiredTime = obj.getLong("expires_in");
data.put(redisKey, accessToken);
data.put(tokenTimeKey, tokenExpiredTime + "");
} catch (Exception e) {
logger.error("HvPush -- >> 认证Token获取失败!原因:e = {}", ExceptionUtil.getMessage(e));
}
return data;
}
2.2构建payLoad
这里发一张我的payLoad结构,官方有现成的内容,我的比较实惠
{
"hps": {
"msg": {
"action": {
"type": 3,
"param": {
"appPkgName": "自定义的路径"
},
},
"type": 1,//这里要注意,华为暂时推荐1或3,3就是通知,1是透传模式,有的小朋友用的方式1,是收不到通知消息的,可以自己多自测下,画上波浪线是重点
"body": {
"extend_content": "透传参数",
"title": "消息标题",
"content": "消息内容"
}
},
"ext": {
"biTag": "Trump",
"icon": "自定义推送消息在通知栏的图标,value为一个公网可以访问的URL"
}
}
2.3发起推送请求并解析返回值
String postBody;
Map req = Maps.newHashMap();
try {
postBody = MessageFormat.format(
"access_token={0}&nsp_svc={1}&nsp_ts={2}&device_token_list={3}&payload={4}",
URLEncoder.encode(accessToken, "UTF-8"),
URLEncoder.encode("openpush.message.api.send", "UTF-8"),
URLEncoder.encode(String.valueOf(System.currentTimeMillis() / 1000), "UTF-8"),
URLEncoder.encode(deviceTokens.toString(), "UTF-8"),
URLEncoder.encode(payload.toString(), "UTF-8"));
String postUrl = apiUrl + "?nsp_ctx=" + URLEncoder.encode("{\"ver\":\"1\", \"appId\":\"" + appId + "\"}", "UTF-8");
String request = HttpUtil.post(postUrl, postBody);
logger.info("HvPush ---- >> 推送结果:messageId = {}, result = {}", messageId, request);
req = JSON.parseObject(request);
} catch (Exception e) {
logger.error("HvPush -- 华为推送失败!messageId = {}, 原因:e = {}", messageId, ExceptionUtil.getMessage(e));
}
if (req.get("code").equals("80000000") && req.get("msg").equals("success")) {
return ResultModel.success("推送成功!");
} else {
return ResultModel.commonError("推送失败!");
}
3.个推官方给的太详细了http://docs.getui.com/server/java/template/大家自己复制吧,可能出现的问题就是官方jar引用问题。
4.阿里云推送(官方SDK,哪来即用)
IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyId, accessKeySecret);
DefaultAcsClient client = new DefaultAcsClient(profile);
PushRequest pushRequest = new PushRequest();
// 推送目标
pushRequest.setAppKey(appKey);
pushRequest.setTarget("DEVICE"); //推送目标: DEVICE:按设备推送 ALIAS : 按别名推送 ACCOUNT:按帐号推送 TAG:按标签推送; ALL: 广播推送
pushRequest.setTargetValue(deviceIds); //根据Target来设定,如Target=DEVICE, 则对应的值为 设备id1,设备id2. 多个值使用逗号分隔.(帐号与设备有一次最多100个的限制)
// pushRequest.setTarget("ALL"); //推送目标: DEVICE:推送给设备; ACCOUNT:推送给指定帐号,TAG:推送给自定义标签; ALL: 推送给全部
// pushRequest.setTargetValue("ALL"); //根据Target来设定,如Target=DEVICE, 则对应的值为 设备id1,设备id2. 多个值使用逗号分隔.(帐号与设备有一次最多100个的限制)
pushRequest.setPushType("NOTICE"); // 消息类型 MESSAGE NOTICE
pushRequest.setDeviceType("ALL"); // 设备类型 ANDROID iOS ALL.
// 推送配置
pushRequest.setTitle("ALi Push Title"); // 消息的标题
pushRequest.setBody("Ali Push Body"); // 消息的内容
// 推送配置: iOS
pushRequest.setIOSBadge(5); // iOS应用图标右上角角标
pushRequest.setIOSMusic("default"); // iOS通知声音
pushRequest.setIOSSubtitle("iOS10 subtitle");//iOS10通知副标题的内容
pushRequest.setIOSNotificationCategory("iOS10 Notification Category");//指定iOS10通知Category
pushRequest.setIOSMutableContent(true);//是否允许扩展iOS通知内容
pushRequest.setIOSApnsEnv("DEV");//iOS的通知是通过APNs中心来发送的,需要填写对应的环境信息。"DEV" : 表示开发环境 "PRODUCT" : 表示生产环境
pushRequest.setIOSRemind(true); // 消息推送时设备不在线(既与移动推送的服务端的长连接通道不通),则这条推送会做为通知,通过苹果的APNs通道送达一次。注意:离线消息转通知仅适用于生产环境
pushRequest.setIOSRemindBody("iOSRemindBody");//iOS消息转通知时使用的iOS通知内容,仅当iOSApnsEnv=PRODUCT && iOSRemind为true时有效
pushRequest.setIOSExtParameters("{\"_ENV_\":\"DEV\",\"k2\":\"v2\"}"); //通知的扩展属性(注意 : 该参数要以json map的格式传入,否则会解析出错)
// 推送配置: Android
pushRequest.setAndroidNotifyType("NONE");//通知的提醒方式 "VIBRATE" : 震动 "SOUND" : 声音 "BOTH" : 声音和震动 NONE : 静音
pushRequest.setAndroidNotificationBarType(1);//通知栏自定义样式0-100
pushRequest.setAndroidNotificationBarPriority(1);//通知栏自定义样式0-100
pushRequest.setAndroidOpenType("URL"); //点击通知后动作 "APPLICATION" : 打开应用 "ACTIVITY" : 打开AndroidActivity "URL" : 打开URL "NONE" : 无跳转
pushRequest.setAndroidOpenUrl("http://www.aliyun.com"); //Android收到推送后打开对应的url,仅当AndroidOpenType="URL"有效
pushRequest.setAndroidActivity("com.alibaba.push2.demo.XiaoMiPushActivity"); // 设定通知打开的activity,仅当AndroidOpenType="Activity"有效
pushRequest.setAndroidMusic("default"); // Android通知音乐
pushRequest.setAndroidPopupActivity("com.ali.demo.PopupActivity");//设置该参数后启动辅助弹窗功能, 此处指定通知点击后跳转的Activity(辅助弹窗的前提条件:1. 集成第三方辅助通道;2. StoreOffline参数设为true)
pushRequest.setAndroidPopupTitle("Popup Title");
pushRequest.setAndroidPopupBody("Popup Body");
pushRequest.setAndroidExtParameters("{\"k1\":\"android\",\"k2\":\"v2\"}"); //设定通知的扩展属性。(注意 : 该参数要以 json map 的格式传入,否则会解析出错)
// 推送控制
Date pushDate = new Date(System.currentTimeMillis()) ; // 30秒之间的时间点, 也可以设置成你指定固定时间
String pushTime = ParameterHelper.getISO8601Time(pushDate);
pushRequest.setPushTime(pushTime); // 延后推送。可选,如果不设置表示立即推送
String expireTime = ParameterHelper.getISO8601Time(new Date(System.currentTimeMillis() + 12 * 3600 * 1000)); // 12小时后消息失效, 不会再发送
pushRequest.setExpireTime(expireTime);
pushRequest.setStoreOffline(true); // 离线消息是否保存,若保存, 在推送时候,用户即使不在线,下一次上线则会收到
PushResponse pushResponse = client.getAcsResponse(pushRequest);
System.out.printf("RequestId: %s, MessageID: %s\n",
pushResponse.getRequestId(), pushResponse.getMessageId());
以上四种推送,针对Android&IOS都做到了很优质的推送服务,在开发中可能要满足多样式的产品需求,去变动传输参数,例如:透传给APP客户端的订单信息,需要播报,需要跳转链接等等。其中小米设备,华为设备也有自己的强硬的推送。我个人认为服务端这边坑还是很小的,至少淹不死人,开发前别急于求成,想找文档,把最官方最全面的API都拿出来,我想都会迎刃而解,服务端需要注意的事项:
1.透传方式(通知 - 服务端直接唤醒APP客户端的通知栏;透传模式 - 服务端将配置的参数传给APP客户端,由开发者自定义)
2.动作&路径
3.设备号要正确,且APP在各个相应平台已经上线
4.透传参数要对正放入,阿里云推送中,对应的透传JSON-MAP 格式要符合客户端的需要
文章标签: 阿里云 小米 华为 推送 个推-java