一. 前言:
最近项目又要拓展几个大流程,一直在加班(咦,为什么是又…╥﹏╥…),其中app推送是小熙调研并且实现落地的。趁现在有点闲暇时间记录分享下。
小熙在最初是选定极光推送(下篇分享)的,但由于财务方面,不得不转向调研信鸽推送。
信鸽并未展现出如bat大厂的突出优势,只是借用腾讯大数据用户的数据分析,为用户分组划分标签以及通过人口属性、消费能力、短时兴趣、LBS 信息等数据分析,让开发者可以针对不同用户群体推送不同的内容。
信鸽官网
二. 视图:
展示图:
三. 依赖:
信鸽官网依赖坐标:
<dependency>
<groupId>com.github.xingePush</groupId>
<artifactId>xinge</artifactId>
<version>1.2.4</version>
</dependency>
四. 配置代码:
- yml配置数据:
# 腾讯信鸽推送, 官方未实现ios和android一起推送,所以有两类 key
xinge:
android-appKey: 1580002xxx
android-masterSecret: cedfb61f4f60074d84xxxxxxxxx
ios-appKey: 168000xxxx
ios-masterSecret: 0be4326e1b2a8ea55922dexxxxxxxx
# 小熙的应用是上海服务器的,所以访问的上海渠道
area-channel-url: https://api.tpns.sh.tencent.com/
# 1:dev,0:product
environment: 1
- 配置文件类:
package com.chengxi.datalom.utils.XinGe;
import com.tencent.xinge.XingeApp;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
/**
* 程熙cjp:https://blog.csdn.net/weixin_41133233
* 信鸽推送配置类
*
* @author chengxi
* @date 2020-12-10
*/
@Component
@Data
@ConfigurationProperties(prefix = "xinge")
public class XinGePushConfig {
@Value("android-appKey")
public String androidAppKey;
@Value("android-masterSecret")
public String androidMasterSecret;
@Value("ios-appKey")
private String iosAppKey;
@Value("ios-masterSecret")
private String iosMasterSecret;
@Value("area-channel-url")
private String areaChannelUrl;
@Value("environment")
private String environment;
@Bean(name = "androidXinGeApp")
public XingeApp androidXinGeApp() throws Exception {
return XingeApp.Builder.class.newInstance().appId(androidAppKey).secretKey(androidMasterSecret).domainUrl(areaChannelUrl).build();
}
@Bean(name = "iosXinGeApp")
public XingeApp iosXinGeApp() throws Exception {
return XingeApp.Builder.class.newInstance().appId(iosAppKey).secretKey(iosMasterSecret).domainUrl(areaChannelUrl).build();
}
public String getEnvironmentNum() {
return this.environment;
}
}
- 封装工具类:
package com.crystalshield.mcd.smscenter.util;
import com.crystalshield.mcd.smscenter.config.XinGePushConfig;
import com.tencent.xinge.XingeApp;
import com.tencent.xinge.bean.*;
import com.tencent.xinge.bean.ios.Alert;
import com.tencent.xinge.bean.ios.Aps;
import com.tencent.xinge.push.app.PushAppRequest;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.json.JSONException;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.ArrayList;
/**
* 程熙cjp:https://blog.csdn.net/weixin_41133233
* 信鸽推送工具
*
* @author chengxi
* @date 2020/12/10 19:38
*/
@Slf4j
@Component
public class XinGeUtil {
@Resource(name = "androidXinGeApp")
private XingeApp androidXinGeApp;
@Resource(name = "iosXinGeApp")
private XingeApp iosXinGeApp;
@Autowired
private XinGePushConfig xinGePushConfig;
/**
* 安卓全平台推送
*
* @param title 推送标题
* @param content 推送内容
* @param activity 点击动作
* @param expandInformation 拓展信息
*/
public Boolean pushAllAndroid(String title, String content, String activity, Object expandInformation) {
return pushAndroidBase(title, content, activity, AudienceType.all, null, expandInformation);
}
/**
* 安卓单账号推送
*
* @param title 推送标题
* @param content 推送内容
* @param activity 点击动作
* @param account 推送账号
* @param expandInformation 拓展信息
*/
public Boolean pushAccountAndroid(String title, String content, String activity, ArrayList<String> account, Object expandInformation) {
return pushAndroidBase(title, content, activity, AudienceType.account, account, expandInformation);
}
/**
* 安卓账号列表推送
*
* @param title 推送标题
* @param content 推送内容
* @param activity 点击动作
* @param accountList 推送账号列表
* @param expandInformation 拓展信息
*/
public Boolean pushAccountListAndroid(String title, String content, String activity, ArrayList<String> accountList, Object expandInformation) {
return pushAndroidBase(title, content, activity, AudienceType.account_list, accountList, expandInformation);
}
/**
* 安卓基础推送
*
* @param title 推送标题
* @param content 推送内容
* @param activity 点击动作
* @param audienceType 推送类型
* @param accountList 推送账号
* @param expandInformation 拓展信息
*/
private Boolean pushAndroidBase(String title, String content, String activity, AudienceType audienceType, ArrayList<String> accountList, Object expandInformation) {
// 设置消息体
Message message = getAndroidMessage(title, content, activity, expandInformation);
// 获取推送请求返回的字符串
JSONObject resultJson = androidXinGeApp.pushApp(queryPushAppRequestReturnString(message, Platform.android, audienceType, accountList));
// 校验返回信息是否成功
return judgeReturnBoolean(resultJson);
}
/**
* iOS单账号推送
*
* @param title 推送标题
* @param content 推送内容
* @param activity 点击动作
* @param account 推送账号
* @param expandInformation 拓展信息
*/
public Boolean pushAccountIos(String title, String content, String activity, ArrayList<String> account, Object expandInformation) {
return pushIosBase(title, content, activity, AudienceType.account, account, expandInformation);
}
/**
* iOS账号列表推送
*
* @param title 推送标题
* @param content 推送内容
* @param activity 点击动作
* @param accounts 用户账号集合
* @param expandInformation 拓展信息
*/
public Boolean pushAccountListIos(String title, String content, String activity, ArrayList<String> accounts, Object expandInformation) {
return pushIosBase(title, content, activity, AudienceType.account_list, accounts, expandInformation);
}
/**
* iOS全平台推送
*
* @param title 推送标题
* @param content 推送内容
* @param activity 点击动作
* @param expandInformation 拓展信息
*/
public Boolean pushAllIos(String title, String content, String activity, Object expandInformation) {
return pushIosBase(title, content, activity, AudienceType.all, null, expandInformation);
}
/**
* iOS基础推送
*
* @param title 推送标题
* @param content 推送内容
* @param activity 点击动作
* @param audienceType 推送类型
* @param accountList 推送账号
* @param expandInformation 拓展信息
*/
private Boolean pushIosBase(String title, String content, String activity, AudienceType audienceType, ArrayList<String> accountList, Object expandInformation) {
//设置消息体
Message message = getIosMessage(title, content, activity, expandInformation);
//推送,并返回回馈信息
JSONObject resultJson = iosXinGeApp.pushApp(queryPushAppRequestReturnString(message, Platform.ios, audienceType, accountList));
return judgeReturnBoolean(resultJson);
}
/**
* 获取校验返回的布尔值
*
* @param resultJson 返回json字符串
* @return
*/
private Boolean judgeReturnBoolean(JSONObject resultJson) {
boolean result = false;
int ret_code = 1;
try {
ret_code = resultJson.getInt("ret_code");
log.info("[信鸽推送]PushResult result is " + resultJson);
return ret_code == 0 ? true : false;
} catch (JSONException e) {
e.printStackTrace();
log.error("[信鸽推送]Connection error. Should retry later. ", e);
} finally {
log.info(resultJson.toString());
}
return result;
}
/**
* 获取推送请求返回的字符串(如需特殊操作,请拓展,目前需求为此)
*
* @param message 推送的消息
* @param platform 平台类型
* @param audienceType 推送类型
* @param accountList 推送账号
* @return
*/
private String queryPushAppRequestReturnString(Message message, Platform platform, AudienceType audienceType, ArrayList<String> accountList) {
//推送请求信息
PushAppRequest pushAppRequest = new PushAppRequest();
//推送环境
pushAppRequest.setEnvironment(String.valueOf(Environment.dev.getType()).equals(xinGePushConfig.getEnvironment()) ? Environment.dev : Environment.product);
//消息体
pushAppRequest.setMessage(message);
//消息类型
pushAppRequest.setMessage_type(MessageType.notify);
//推送平台
pushAppRequest.setPlatform(platform);
//推送目标
pushAppRequest.setAudience_type(audienceType);
//推送账号
if (CollectionUtils.isNotEmpty(accountList)) {
pushAppRequest.setAccount_list(accountList);
}
return pushAppRequest.toString();
}
/**
* 设置并返回安卓消息体(如需特殊操作,请拓展,目前需求为此)
*
* @param title 推送标题
* @param content 推送内容
* @param activity 点击动作
* @param expandInformation 拓展信息
*/
private Message getAndroidMessage(String title, String content, String activity, Object expandInformation) {
//安卓消息设置
MessageAndroid messageAndroid = new MessageAndroid();
//消息点击动作设置
ClickAction clickAction = new ClickAction();
clickAction.setAction_type(1);
clickAction.setActivity(activity);
//点击动作加入消息设置
messageAndroid.setAction(clickAction);
//推送消息其他参数设置
messageAndroid.setBuilder_id(0);
messageAndroid.setRing(1);
messageAndroid.setVibrate(1);
messageAndroid.setClearable(1);
messageAndroid.setN_id(0);
messageAndroid.setLights(1);
messageAndroid.setIcon_type(0);
messageAndroid.setStyle_id(1);
//添加拓展信息(此信息不直接展示在推送上)
messageAndroid.setCustom_content(expandInformation);
//封装推送消息
Message message = queryMessage(title, content);
message.setAndroid(messageAndroid);
return message;
}
/**
* 设置并返回ios消息体(如需特殊操作,请拓展,目前需求为此)
*
* @param title 推送标题
* @param content 推送内容
* @param activity 点击动作
* @param expandInformation 拓展信息
*/
private Message getIosMessage(String title, String content, String activity, Object expandInformation) {
//ios消息设置
MessageIOS messageIOS = new MessageIOS();
//苹果推送服务(APNs)特有的消息体字段
Aps aps = new Aps();
//标题和消息内容
Alert alert = new Alert();
alert.setTitle(title);
alert.setBody(content);
aps.setAlert(alert);
aps.setCategory("INVITE_CATEGORY");
aps.setBadge_type(5);
messageIOS.setAps(aps);
//设置拓展信息(此信息不直接展示在推送上)
messageIOS.setCustom(expandInformation);
//封装推送消息
Message message = queryMessage(title, content);
message.setIos(messageIOS);
return message;
}
/**
* 获取Message
*
* @param title
* @param content
* @return
*/
private Message queryMessage(String title, String content) {
Message message = new Message();
message.setTitle(title);
message.setContent(content);
return message;
}
}
五. 示例:
下面试小熙的测试用例:
@Autowired
private XinGeUtil xinGeUtil;
@Test
public void testXinGe() throws JSONException {
// 这里可以使用项目定义的信鸽传输类,以下只是示例
JSONObject jsonObject = new JSONObject();
jsonObject.put("userName", "小熙");
// 测试单个ios账户
System.out.println(xinGeUtil.pushAccountIos("IOS测试标题", "IOS测试内容", "", Lists.newArrayList("13456767890"), null));
// 测试批量安卓账户
System.out.println(xinGeUtil.pushAccountListAndroid("批量用户的安卓测试标题", "批量用户的安卓测试内容", "", Lists.newArrayList("17601000911","18601980911"), null));
// 测试批量安卓账户并且加上拓展字段
System.out.println(xinGeUtil.pushAccountListAndroid("批量用户的安卓测试标题", "批量用户的安卓测试内容", "", Lists.newArrayList("17601000911","18601980911"), jsonObject.toString()));
}
六. 后语:
到此小熙介绍的,后端java集成就好了,前端集成还需要按照官网流程操作生成对应应用,获取对应key。个人感觉还是极光比较好用些,下篇介绍极光推送。