1、引入依赖:
<!-- 极光推送 begin -->
<dependency>
<groupId>cn.jpush.api</groupId>
<artifactId>jpush-client</artifactId>
<version>3.4.7</version>
</dependency>
<dependency>
<groupId>cn.jpush.api</groupId>
<artifactId>jiguang-common</artifactId>
<version>1.1.9</version>
</dependency>
<!-- 极光推送 end -->
2、整合工具类:
package com.demo.common.util;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.jiguang.common.ClientConfig;
import cn.jiguang.common.ServiceHelper;
import cn.jiguang.common.connection.NettyHttpClient;
import cn.jiguang.common.resp.APIConnectionException;
import cn.jiguang.common.resp.APIRequestException;
import cn.jiguang.common.resp.ResponseWrapper;
import cn.jpush.api.JPushClient;
import cn.jpush.api.push.GroupPushClient;
import cn.jpush.api.push.GroupPushResult;
import cn.jpush.api.push.PushResult;
import cn.jpush.api.push.model.Message;
import cn.jpush.api.push.model.Platform;
import cn.jpush.api.push.model.PushPayload;
import cn.jpush.api.push.model.audience.Audience;
import cn.jpush.api.push.model.notification.AndroidNotification;
import cn.jpush.api.push.model.notification.IosNotification;
import cn.jpush.api.push.model.notification.Notification;
import com.google.common.collect.Maps;
import com.zjrc.common.constant.CommonConstants;
import com.zjrc.common.model.dto.PushBeanDto;
import io.netty.handler.codec.http.HttpMethod;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.*;
/**
* 极光推送工具类
*
* @author wangxf
* @since 2020/09/18
*/
@Slf4j
@Component
public class JPushUtil {
// 极光官网-应用管理-appkey
//@Value("${push.appkey}")
private static String APP_KEY = "dc790a88a0cfd5c4163d08bc";
// 极光官网-个人管理中心-点击查看-secret
//@Value("${push.secret}")
private static String MASTER_SECRET = "18365deebd7b853e395f04ff";
// 极光推送设置过期时间
//@Value("${jpush.liveTime}")
private static String LIVE_TIME = "1000";
// 极光官网-分组管理-groupkey
//@Value("${push.groupkey}")
private static String GROUP_KEY = "f95dc825ab1721c77de8d426";
// 极光官网-分组管理-点击查看-secret
//@Value("${push.groupsecret}")
private static String GROUP_MASTER_SECRET = "d570da25c93f4bb3d8ab3efd";
/**
* 发送自定义消息,由APP端拦截信息后再决定是否创建通知(目前APP用此种方式)
*
* @param title App通知栏标题
* @param content App通知栏内容(为了单行显示全,尽量保持在22个汉字以下)
* @param extrasMap 额外推送信息(不会显示在通知栏,传递数据用)
* @param alias 别名数组,设定哪些用户手机能接收信息(为空则所有用户都推送)
* @return PushResult
*/
public PushResult sendCustomPush(String title, String content, Map<String, String> extrasMap, String... alias) throws APIConnectionException, APIRequestException {
ClientConfig clientConfig = ClientConfig.getInstance();
clientConfig.setTimeToLive(Long.parseLong(LIVE_TIME));
// 使用NativeHttpClient网络客户端,连接网络的方式,不提供回调函数
JPushClient jpushClient = new JPushClient(MASTER_SECRET, APP_KEY, null, clientConfig);
// 设置为消息推送方式为仅推送消息,不创建通知栏提醒
PushPayload payload = buildCustomPushPayload(title, content, extrasMap, alias);
PushResult result = jpushClient.sendPush(payload);
return result;
}
/**
* 发送通知消息(Android|IOS)
*
* @param title App通知栏标题
* @param content App通知栏内容(为了单行显示全,尽量保持在22个汉字以下)
* @param extrasMap 额外推送信息(不会显示在通知栏,传递数据用)
* @param tags 标签数组,设定哪些用户手机能接收信息(为空则所有用户都推送)
*/
public PushResult sendNoticePush(String title, String content, Map<String, String> extrasMap, String... tags) {
ClientConfig clientConfig = ClientConfig.getInstance();
clientConfig.setTimeToLive(Long.valueOf(LIVE_TIME));
// 使用NativeHttpClient网络客户端,连接网络的方式,不提供回调函数
JPushClient jpushClient = new JPushClient(MASTER_SECRET, APP_KEY, null, clientConfig);
PushResult result = null;
// 设置推送方式
final PushPayload payload = buildPushAllByTags(title, content, extrasMap, tags);
try {
result = jpushClient.sendPush(payload);
} catch (APIConnectionException e) {
log.error("请求连接异常,请稍后重试", e);
log.error("推送编号: {}", payload.getSendno());
} catch (APIRequestException e) {
log.error("推送服务异常,请及时检查", e);
log.info("请求状态: {} " , e.getStatus());
log.info("错误码: {} " , e.getErrorCode());
log.info("错误信息: {} " , e.getErrorMessage());
log.info("错误信息ID: {}" , e.getMsgId());
}finally {
return result;
}
}
/**
* 发送Android系统通知消息
*
* @param title App通知栏标题
* @param content App通知栏内容(为了单行显示全,尽量保持在22个汉字以下)
* @param extrasMap 额外推送信息(不会显示在通知栏,传递数据用)
* @param tags 标签数组,设定哪些用户手机能接收信息(为空则所有用户都推送)
*/
public PushResult sendNoticeAndroidPush(String title, String content, Map<String, String> extrasMap, String... tags) {
ClientConfig clientConfig = ClientConfig.getInstance();
clientConfig.setTimeToLive(Long.valueOf(LIVE_TIME));
// 使用NativeHttpClient网络客户端,连接网络的方式,不提供回调函数
JPushClient jpushClient = new JPushClient(MASTER_SECRET, APP_KEY, null, clientConfig);
PushResult result = null;
// 设置推送方式
final PushPayload payload = buildPushAndroidByTags(title, content, extrasMap, tags);
try {
result = jpushClient.sendPush(payload);
} catch (APIConnectionException e) {
log.error("请求连接异常,请稍后重试", e);
log.error("推送编号: {}", payload.getSendno());
} catch (APIRequestException e) {
log.error("推送服务异常,请及时检查", e);
log.info("请求状态: {} " , e.getStatus());
log.info("错误码: {} " , e.getErrorCode());
log.info("错误信息: {} " , e.getErrorMessage());
log.info("错误信息ID: {}" , e.getMsgId());
}finally {
return result;
}
}
/**
* 发送IOS系统通知消息
*
* @param content App通知栏内容(为了单行显示全,尽量保持在22个汉字以下)
* @param extrasMap 额外推送信息(不会显示在通知栏,传递数据用)
* @param tags 标签数组,设定哪些用户手机能接收信息(为空则所有用户都推送)
*/
public PushResult sendNoticeIosPush(String content, Map<String, String> extrasMap, String... tags) {
ClientConfig clientConfig = ClientConfig.getInstance();
clientConfig.setTimeToLive(Long.valueOf(LIVE_TIME));
// 使用NativeHttpClient网络客户端,连接网络的方式,不提供回调函数
JPushClient jpushClient = new JPushClient(MASTER_SECRET, APP_KEY, null, clientConfig);
PushResult result = null;
// 设置推送方式
final PushPayload payload = buildPushIosByTags(content, extrasMap, tags);
try {
result = jpushClient.sendPush(payload);
} catch (APIConnectionException e) {
log.error("请求连接异常,请稍后重试", e);
log.error("推送编号: {}", payload.getSendno());
} catch (APIRequestException e) {
log.error("推送服务异常,请及时检查", e);
log.info("请求状态: {} " , e.getStatus());
log.info("错误码: {} " , e.getErrorCode());
log.info("错误信息: {} " , e.getErrorMessage());
log.info("错误信息ID: {}" , e.getMsgId());
}finally {
return result;
}
}
/**
* 异步请求推送方式
* 使用NettyHttpClient,异步接口发送请求,通过回调函数可以获取推送成功与否情况
*
* @param title 通知栏标题
* @param content 通知栏内容(为了单行显示全,尽量保持在22个汉字以下)
* @param extrasMap 额外推送信息(不会显示在通知栏,传递数据用)
* @param alias 需接收的用户别名数组(为空则所有用户都推送)
*/
public void sendAsyncPush(String title, String content, Map<String, String> extrasMap, String... alias) {
ClientConfig clientConfig = ClientConfig.getInstance();
clientConfig.setTimeToLive(Long.valueOf(LIVE_TIME));
String host = (String) clientConfig.get(ClientConfig.PUSH_HOST_NAME);
final NettyHttpClient client = new NettyHttpClient(ServiceHelper.getBasicAuthorization(APP_KEY, MASTER_SECRET),
null, clientConfig);
try {
URI uri = new URI(host + clientConfig.get(ClientConfig.PUSH_PATH));
PushPayload payload = buildPushPayload(title,content,extrasMap,alias);
client.sendRequest(HttpMethod.POST, payload.toString(), uri, new NettyHttpClient.BaseCallback() {
@Override
public void onSucceed(ResponseWrapper responseWrapper) {
if (CommonConstants.RESPONSE_CODE == responseWrapper.responseCode) {
log.info("极光推送成功,返回结果: {}", responseWrapper.responseContent);
} else {
log.info("极光推送失败,返回结果: {} ", responseWrapper.responseContent);
}
}
});
} catch (URISyntaxException e) {
e.printStackTrace();
} finally {
// 需要手动关闭Netty请求进程,否则会一直保留
client.close();
}
}
/**
* 设置、更新、设备的 tag, alias 信息。
*
* @param registrationId 设备的registrationId
* @param alias 更新设备的别名属性
* @param tagsToAdd 添加设备的tag属性
* @param tagsToRemove 移除设备的tag属性
*/
public void UpdateDeviceTagAlias(String registrationId, String alias, Set<String> tagsToAdd, Set<String> tagsToRemove){
try {
JPushClient jpushClient = new JPushClient(MASTER_SECRET, APP_KEY);
jpushClient.updateDeviceTagAlias(registrationId, alias, tagsToAdd, tagsToRemove);
} catch (APIConnectionException e) {
log.error("请求连接异常,请稍后重试", e);
} catch (APIRequestException e) {
log.error("推送服务异常,请及时检查", e);
log.info("请求状态: {} ", e.getStatus());
log.info("错误码: {} ", e.getErrorCode());
log.info("错误信息: {} ", e.getErrorMessage());
log.info("错误信息ID: {}", e.getMsgId());
}
}
/**
* 构建Android和IOS的推送通知对象
*
* @return PushPayload
*/
private PushPayload buildPushPayload(String title, String content, Map<String, String> extrasMap,String... alias) {
if (CollUtil.isEmpty(extrasMap)) {
extrasMap = Maps.newHashMap();
}
// 批量删除数组中空元素
String[] newAlias = removeArrayEmptyElement(alias);
return PushPayload.newBuilder().setPlatform(Platform.android_ios())
// 别名为空,全员推送;别名不为空,按别名推送
.setAudience((null == newAlias || newAlias.length == 0) ? Audience.all() : Audience.alias(alias))
//.setAudience(Audience.registrationId("d"))
.setNotification(Notification.newBuilder().setAlert(content)
.addPlatformNotification(
AndroidNotification.newBuilder().setTitle(title).addExtras(extrasMap).build())
.addPlatformNotification(IosNotification.newBuilder().incrBadge(1).addExtras(extrasMap).build())
.build())
.build();
}
/**
* 根据标签推送相应的消息
*
* @param title 推送消息标题
* @param content 推送消息内容
* @param extrasMap 推送额外信息
* @param tags 推送的目标标签
* @return
*/
private PushPayload buildPushAllByTags(String title, String content, Map<String, String> extrasMap, String... tags) {
if (CollUtil.isEmpty(extrasMap)) {
extrasMap = Maps.newHashMap();
}
//批量删除数组中的空元素
String[] newTags = removeArrayEmptyElement(tags);
return PushPayload.newBuilder()
//设置推送平台为android | ios
.setPlatform(Platform.android_ios())
//设置标签
.setAudience(Audience.tag(newTags))
//设置 推送的标签标题
// 设置通知方式(以alert方式提醒)
.setNotification(Notification.newBuilder().setAlert(content)
.addPlatformNotification(AndroidNotification.newBuilder()
.setTitle(title)
.addExtras(extrasMap).build())
.addPlatformNotification(IosNotification.newBuilder()
.incrBadge(1)
.addExtras(extrasMap).build())
.build())
//sendno int 可选 推送序号 纯粹用来作为 API 调用标识
//离线消息保留时长 推送当前用户不在线时,为该用户保留多长时间的离线消息(默认 86400 (1 天),最长 10 天。设置为 0 表示不保留离线消息,只有推送当前在线的用户可以收到)
//apns_production boolean 可选 APNs是否生产环境 True 表示推送生产环境,False 表示要推送开发环境; 如果不指定则为推送生产环境
//big_push_duration int 可选 定速推送时长(分钟) 又名缓慢推送,把原本尽可能快的推送速度,降低下来,在给定的 n 分钟内,均匀地向这次推送的目标用户推送。最大值为 1440。未设置则不是定速推送
// .setOptions(Options.newBuilder().setApnsProduction(false).setTimeToLive(8600).setBigPushDuration(1).build())
//设置通知内容
// .setMessage(Message.newBuilder().setTitle("").setMsgContent("").setContentType("").build())
.build();
}
/**
* 根据标签 构建Android推送消息
* @param title
* @param content
* @param extrasMap
* @param tags
* @return
*/
private PushPayload buildPushAndroidByTags(String title, String content, Map<String, String> extrasMap, String... tags) {
if (CollUtil.isEmpty(extrasMap)) {
extrasMap = Maps.newHashMap();
}
//批量删除数组中的空元素
String[] newTags = removeArrayEmptyElement(tags);
PushPayload payload = PushPayload.newBuilder()
.setPlatform(Platform.android())
.setAudience(Audience.tag(newTags))
.setNotification(Notification.newBuilder()
.setAlert(content)
.addPlatformNotification(AndroidNotification.newBuilder()
.setTitle(title)
.addExtras(extrasMap).build())
.build())
.build();
return payload;
}
/**
* 根据标签 构建IOS推送消息
* @param content
* @param extrasMap
* @param tags
* @return
*/
private PushPayload buildPushIosByTags(String content, Map<String, String> extrasMap, String... tags) {
if (CollUtil.isEmpty(extrasMap)) {
extrasMap = Maps.newHashMap();
}
//批量删除数组中的空元素
String[] newTags = removeArrayEmptyElement(tags);
PushPayload payload = PushPayload.newBuilder()
.setPlatform(Platform.ios())
.setAudience(Audience.tag(newTags))
.setNotification(Notification.newBuilder()
.setAlert(content)
.addPlatformNotification(IosNotification.newBuilder()
.incrBadge(1)
.addExtras(extrasMap).build())
.build())
.build();
return payload;
}
/**
* 构建Android和IOS的自定义消息的推送消息对象
*
* @return PushPayload
*/
private PushPayload buildCustomPushPayload(String title, String content, Map<String, String> extrasMap, String... alias) {
// 批量删除数组中空元素
String[] newAlias = removeArrayEmptyElement(alias);
return PushPayload.newBuilder().setPlatform(Platform.android_ios())
.setAudience((null == newAlias || newAlias.length == 0) ? Audience.all() : Audience.alias(newAlias))
.setNotification(Notification.newBuilder().setAlert(content)
.addPlatformNotification(AndroidNotification.newBuilder().setTitle(title).addExtras(extrasMap).build()).build())
.setMessage(Message.newBuilder().setTitle(title).setMsgContent(content).addExtras(extrasMap).build())
.build();
}
/**
* 分组推送消息
* @param title
* @param content
* @param extrasMap
* @param alias
*/
public void sendGroupPush(String title, String content, Map<String, String> extrasMap, String... alias) {
GroupPushClient groupPushClient = new GroupPushClient(GROUP_MASTER_SECRET, GROUP_KEY);
final PushPayload payload = buildPushPayload(title,content,extrasMap,alias);
try {
GroupPushResult groupPushResult = groupPushClient.sendGroupPush(payload);
Map<String, PushResult> result = groupPushResult.getAppResultMap();
for (Map.Entry<String, PushResult> entry : result.entrySet()) {
PushResult pushResult = entry.getValue();
PushResult.Error error = pushResult.error;
if (ObjectUtil.isNotNull(error)) {
log.info("group_key: {}, error_code : {}, error_message: {}", entry.getKey(), error.getCode(), error.getMessage());
} else {
log.info("group_key: {}, send_no: {}, msg_id: {}" ,entry.getKey(), pushResult.sendno, pushResult.msg_id);
}
}
} catch (APIConnectionException e) {
log.error("请求连接异常,请稍后重试", e);
log.error("推送编号: {}", payload.getSendno());
} catch (APIRequestException e) {
log.error("推送服务异常,请及时检查", e);
log.info("请求状态: {} ", e.getStatus());
log.info("错误码: {} ", e.getErrorCode());
log.info("错误信息: {} ", e.getErrorMessage());
log.info("错误信息ID: {}", e.getMsgId());
}
}
/**
* 删除别名中的空元素(需删除如:null,""," ")
*
* @param strArray
* @return String[]
*/
private String[] removeArrayEmptyElement(String... strArray) {
if (null == strArray || strArray.length == 0) {
return null;
}
List<String> tempList = Arrays.asList(strArray);
List<String> strList = new ArrayList<String>();
Iterator<String> iterator = tempList.iterator();
while (iterator.hasNext()) {
String str = iterator.next();
// 消除空格后再做比较
if (null != str && !"".equals(str.trim())) {
strList.add(str);
}
}
// 若仅输入"",则会将数组长度置为0
String[] newStrArray = strList.toArray(new String[strList.size()]);
return newStrArray;
}
}