admin 管理员组文章数量: 887021
java服务端统一消息推送(苹果, 华为, 小米, 极光,vivo)
1. 引入依赖
<!-- 极光 -->
<dependency><groupId>cn.jpush.api</groupId><artifactId>jpush-client</artifactId><version>3.3.10</version>
</dependency>
<dependency><groupId>cn.jpush.api</groupId><artifactId>jiguang-common</artifactId><version>1.1.4</version>
</dependency>
<!-- 苹果 -->
<dependency><groupId>com.notnoop.apns</groupId><artifactId>apns</artifactId><version>1.0.0.Beta6</version>
</dependency>
<!-- 华为 -->
<dependency><groupId>com.huawei.android</groupId><artifactId>huawei-push</artifactId><version>1.1.1</version>
</dependency>
<!-- 小米,vivo 请去官网下载, 然后配置到maven私服仓库nexus -->
<dependency><groupId>com.xiaomi</groupId><artifactId>mipush</artifactId><version>2.2.20</version>
</dependency><dependency><groupId>com.vivo</groupId><artifactId>vpush</artifactId><version>1.1.0</version>
</dependency>
2. 定义推送接口
public interface PushMessage {/*** 通知栏消息推送*/public int pushNcMsg(PushMessageDTO pushMessageDTO, String content, String title) throws Exception ;/*** 透传推送*/public int pushTransMsg(PushMessageDTO pushMessageDTO, String content) throws Exception ;}
//辅助类 appName, appId, appKey ,masterSecret请去官网注册账号,添加app应用获取
@Getter
@Setter
@ToString
public class PushMessageDTO implements Serializable {private static final long serialVersionUID = 1L;private String appName; //应用名称private String appId; //应用idprivate String appKey; //应用keyprivate String masterSecret; //秘钥private String target; //推送目标private String platform; //推送平台}
3. 实现类
//苹果都是透传推送
@Component
public class ApplePushMessage implements PushMessage {@Overridepublic int pushNcMsg(PushMessageDTO pushMessageDTO, String content, String title) throws Exception {// TODO Auto-generated method stubreturn 0;}//苹果的appKey是voippush.p12文件路径, masterSecret是密码@Overridepublic int pushTransMsg(PushMessageDTO pushMessageDTO, String content) throws Exception {ApnsService service = APNS.newService().withCert(pushMessageDTO.getAppKey(), pushMessageDTO.getMasterSecret()).withSandboxDestination().withAppleDestination(true).build();String payloadApple = APNS.newPayload().alertBody(content).build();String token = pushMessageDTO.getTarget();service.push(token, payloadApple);return 1;}
}
//华为
@Component
public class HuaWeiPushMessage implements PushMessage {private static String tokenUrl = ""; // 获取认证Token的URLprivate static String apiUrl = ".do"; // 应用级消息下发APIprivate static String accessToken;// 下发通知消息的认证Tokenprivate static long tokenExpiredTime; // accessToken的过期时间@Overridepublic int pushNcMsg(PushMessageDTO pushMessageDTO, String content, String title) throws Exception {if (tokenExpiredTime <= System.currentTimeMillis()) {refreshToken(pushMessageDTO.getMasterSecret(), pushMessageDTO.getAppKey());}/* PushManager.requestToken为客户端申请token的方法,可以调用多次以防止申请token失败 *//* PushToken不支持手动编写,需使用客户端的onToken方法获取 */JSONArray deviceTokens = new JSONArray();// 目标设备TokendeviceTokens.add(pushMessageDTO.getTarget());JSONObject body = new JSONObject();// 仅通知栏消息需要设置标题和内容,透传消息key和value为用户自定义body.put("title", title);// 消息标题body.put("content", content);// 消息内容体JSONObject param = new JSONObject();param.put("appPkgName", pushMessageDTO.getAppName());// 定义需要打开的appPkgNameJSONObject action = new JSONObject();action.put("type", 3);// 类型3为打开APP,其他行为请参考接口文档设置action.put("param", param);// 消息点击动作参数JSONObject msg = new JSONObject();msg.put("type", 3);// 3: 通知栏消息,异步透传消息请根据接口文档设置msg.put("action", action);// 消息点击动作msg.put("body", body);// 通知栏消息body内容JSONObject hps = new JSONObject();// 华为PUSH消息总结构体hps.put("msg", msg);JSONObject payload = new JSONObject();payload.put("hps", hps);String 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\":\"" + pushMessageDTO.getAppKey() + "\"}", "UTF-8");httpPost(postUrl, postBody, 5000, 5000);return 1;}@Overridepublic int pushTransMsg(PushMessageDTO pushMessageDTO, String context) throws Exception {if (tokenExpiredTime <= System.currentTimeMillis()) {refreshToken(pushMessageDTO.getMasterSecret(),pushMessageDTO.getAppKey());}/* PushManager.requestToken为客户端申请token的方法,可以调用多次以防止申请token失败 *//* PushToken不支持手动编写,需使用客户端的onToken方法获取 */JSONArray deviceTokens = new JSONArray();// 目标设备TokendeviceTokens.add(pushMessageDTO.getTarget());JSONObject body = new JSONObject();body.put("online", 1);JSONObject param = new JSONObject();param.put("appPkgName", pushMessageDTO.getAppName());JSONObject action = new JSONObject();action.put("type", 3);// 类型3为打开APP,其他行为请参考接口文档设置action.put("param", param);// 消息点击动作参数JSONObject msg = new JSONObject();msg.put("type", 1);// 1: 透传异步消息,通知栏消息请根据接口文档设置msg.put("body", body.toString());// body内容不一定是JSON,可以是String,若为JSON需要转化为String发送msg.put("action", action);// 消息点击动作JSONObject hps = new JSONObject();// 华为PUSH消息总结构体hps.put("msg", msg);JSONObject payload = new JSONObject();payload.put("hps", hps);String 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\":\"" + pushMessageDTO.getAppKey() + "\"}", "UTF-8");httpPost(postUrl, postBody, 5000, 5000);return 1;}// 获取下发通知消息的认证Tokenprivate void refreshToken(String appSecret, String appId) throws IOException {String msgBody = MessageFormat.format("grant_type=client_credentials&client_secret={0}&client_id={1}", URLEncoder.encode(appSecret, "UTF-8"), appId);String response = httpPost(tokenUrl, msgBody, 5000, 5000);JSONObject obj = JSONObject.parseObject(response);accessToken = obj.getString("access_token");tokenExpiredTime = System.currentTimeMillis() + (obj.getLong("expires_in") - 5 * 60) * 1000;}//httpPost请求private String httpPost(String httpUrl, String data, int connectTimeout, int readTimeout) throws IOException {OutputStream outPut = null;HttpURLConnection urlConnection = null;InputStream in = null;try {URL url = new URL(httpUrl);urlConnection = (HttpURLConnection) url.openConnection();urlConnection.setRequestMethod("POST");urlConnection.setDoOutput(true);urlConnection.setDoInput(true);urlConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");urlConnection.setConnectTimeout(connectTimeout);urlConnection.setReadTimeout(readTimeout);urlConnection.connect();// POST dataoutPut = urlConnection.getOutputStream();outPut.write(data.getBytes("UTF-8"));outPut.flush();// read responseif (urlConnection.getResponseCode() < 400) {in = urlConnection.getInputStream();} else {in = urlConnection.getErrorStream();}List<String> lines = IOUtils.readLines(in, urlConnection.getContentEncoding());StringBuffer strBuf = new StringBuffer();for (String line : lines) {strBuf.append(line);}System.out.println(strBuf.toString());return strBuf.toString();} finally {IOUtils.closeQuietly(outPut);IOUtils.closeQuietly(in);if (urlConnection != null) {urlConnection.disconnect();}}}}
//小米
@Component
public class XiaoMiPushMessage implements PushMessage {@Overridepublic int pushNcMsg(PushMessageDTO pushMessageDTO, String content, String title) throws Exception {Constants.useOfficial();Sender sender = new Sender(pushMessageDTO.getMasterSecret());String messagePayload = "{\"online\":\"1\"}";Message message = new Message.Builder().title(title).description(content).payload(messagePayload).restrictedPackageName(pushMessageDTO.getAppName()).passThrough(0).extra(Constants.EXTRA_PARAM_NOTIFY_EFFECT, Constants.NOTIFY_LAUNCHER_ACTIVITY).notifyType(-1).build();sender.sendToAlias(message, pushMessageDTO.getTarget(), 1);return 1;}@Overridepublic int pushTransMsg(PushMessageDTO pushMessageDTO, String content) throws Exception {Constants.useOfficial();Sender sender = new Sender(pushMessageDTO.getMasterSecret());String messagePayload = "{\"online\":\"1\"}";Message message = new Message.Builder().description(content).payload(messagePayload).restrictedPackageName(pushMessageDTO.getAppName()).passThrough(1).notifyType(-1).build();sender.sendToAlias(message, pushMessageDTO.getTarget(), 1);return 1;}}
//vivo暂时只有通知栏消息推送
@Component
public class VivoPushMessage implements PushMessage {@Overridepublic int pushNcMsg(PushMessageDTO pushMessageDTO, String content, String title) throws Exception {Sender sender = new Sender(pushMessageDTO.getMasterSecret());//注册登录开发平台网站获取到的appSecretResult result = sender.getToken(Integer.valueOf(pushMessageDTO.getAppId()), pushMessageDTO.getAppKey());//注册登录开发平台网站获取到的appId和appKeySender senderMessage = new Sender(pushMessageDTO.getMasterSecret(),result.getAuthToken());Message singleMessage = new Message.Builder().regId(pushMessageDTO.getTarget())//该测试手机设备订阅推送后生成的regId.notifyType(3).title(title).content(content).timeToLive(1000).skipType(2).skipContent("")workType(-1).requestId("1234567890123456").build();Result resultMessage = senderMessage.sendSingle(singleMessage);return 1;}@Overridepublic int pushTransMsg(PushMessageDTO pushMessageDTO, String content) throws Exception {return 1;}}
4 . 统一消息推送接口
public void pushMessageToAllPlatform(PushMessageVO pushMessageVO) {String[] sipCodeList = pushMessageVO.getSipCode().split(",");// 查询推送信息,在数据库构建的表(见文章末尾)List<PushMessageDTO> pushMessageDTOList = rxSipPlatformTargetMapper.selectPushMessage(pushMessageVO.getAppName(), sipCodeList);// 推送消息if (null != pushMessageDTOList && !pushMessageDTOList.isEmpty()) {for (PushMessageDTO pushMessageDTO : pushMessageDTOList) {pushMessageToApp(pushMessageDTO, pushMessageVO.getPushType(), pushMessageVO.getContent(), pushMessageVO.getTitle());}}
}private int pushMessageToApp(PushMessageDTO pushMessageDTO, String pushType,String content, String title) {try {PushMessage pushMessage = (PushMessage) SpringUtil.getBean(PlatformEnum.getNameByType(pushMessageDTO.getPlatform()));if (StringUtils.isBlank(pushType) || "NC".equals(pushType)) {pushMessage.pushNcMsg(pushMessageDTO, content, title);}if (StringUtils.isBlank(pushType) || "TS".equals(pushType)) {pushMessage.pushTransMsg(pushMessageDTO, content);}} catch (Exception e) {log.error(e.toString());return 0;}return 1;}
//辅助参数类
public enum PlatformEnum {
JIGUANG ("JIGUANG","jiGuangPushMessage"),
HUAWEI ("HUAWEI","huaWeiPushMessage"),
APPLE ("APPLE","applePushMessage"),
XIAOMI ("XIAOMI","xiaoMiPushMessage"),
OPPO ("OPPO","oppoPushMessage"),
VIVO ("VIVO","vivoPushMessage");
private String platformType;
private String platformName;
private PlatformEnum(String platformType, String platformName) {
this.platformType = platformType;
this.platformName = platformName;
}
public String getPlatformType() {
return platformType;
}
public void setPlatformType(String platformType) {
this.platformType = platformType;
}
public String getPlatformName() {
return platformName;
}
public void setPlatformName(String platformName) {
this.platformName = platformName;
}
public static String getNameByType(String platformType) {
for (PlatformEnum e : PlatformEnum.values()) {
if (e.getPlatformType().equals(platformType)) {
return e.getPlatformName();
}
}
return null;
}
}
public class PushMessageVO implements Serializable {private static final long serialVersionUID = 1L;@ApiModelProperty(value="app名称" ,required=true)private String appName;@ApiModelProperty(value="设备编号(多个用逗号隔开)" ,required=true)private String sipCode;@ApiModelProperty(value="消息推送模式(NC-通知栏消息, TS-透传消息)" ,required=true)private String pushType;@ApiModelProperty(value="消息内容" ,required=true)private String content;@ApiModelProperty(value="消息标题")private String title;}
数据库表:
CREATE TABLE `rx_sip_platform_target` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`sip_code` varchar(255) DEFAULT NULL COMMENT '设备编号',
`platform` varchar(255) DEFAULT '0' COMMENT '推送平台',
`target` varchar(255) DEFAULT NULL COMMENT '推送目标',
`update_time` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) COMMENT='设备登录推送目标表';
CREATE TABLE `rx_app_config` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'id',
`app_name` varchar(64) NOT NULL COMMENT '应用名称',
`app_id` varchar(20) DEFAULT NULL COMMENT '应用ID',
`app_key` varchar(128) NOT NULL COMMENT 'appKey',
`master_secret` varchar(64) NOT NULL COMMENT 'masterSecret',
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`update_time` timestamp NULL DEFAULT NULL,
`platform` varchar(255) DEFAULT '0' COMMENT '推送平台',
PRIMARY KEY (`id`)
) COMMENT='应用推送平台配置信息';
//苹果的appKey是voippush.p12文件路径, masterSecret是密码
//查询推送集sql
<select id="selectPushMessage" resultMap="PushMessageDTOMap">SELECTc.app_name,c.app_id,c.app_key,c.master_secret,c.platform,p.targetFROMrx_sip_platform_target pINNER JOIN rx_app_config c ON c.platform = p.platformWHEREc.app_name =#{appName,jdbcType=VARCHAR}AND p.sip_code IN<foreach collection="sipCodeList" item="sipCode" open="(" close=")" separator=",">#{sipCode,jdbcType=VARCHAR}</foreach>
</select>
本文标签: java服务端统一消息推送(苹果 华为 小米 极光 vivo)
版权声明:本文标题:java服务端统一消息推送(苹果, 华为, 小米, 极光,vivo) 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.freenas.com.cn/free/1698122192h286691.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论