本代码可以根据类型、推送目标等进行推送、可以手动选择类型、目标等
1、按照客户端类型进行发送 :ios、android、ios&android
2、按照推送目标发送:tag、tag_and、tag_not、alias(别名)、registrationId(设备id)
3.设置离线消息
1、添加极光的maven依赖
<dependency>
<groupId>cn.jpush.api</groupId>
<artifactId>jpush-client</artifactId>
<version>3.3.10</version>
</dependency>
2、设置应用的app_key、masterSecret和apnsProduction
apnsProduction True 表示推送生产环境,False 表示要推送开发环境,
该字段仅对 iOS 的 Notification 有效。
1.将其放在apollo中:
@Value("${app-push.app_key}")
private String appKey;
@Value("${app-push.master_secret}")
private String masterSecret;
@Value("${app-push.app_apns_production}")
private Boolean appApnsProduction;
2.直接在代码中写死(不建议)
private static String APP_KEY = "*************";
private static String MASTER_SECRET = "*************";
private static Boolean APNS_PRODUCTION = false;
3 、构建Android通知推送
private AndroidNotification getAndroidNotification(PushMessageDTO pushMessage) throws UnsupportedEncodingException {
return AndroidNotification.newBuilder()
//消息体
.setTitle(pushMessage.getTitle())
.setAlert(pushMessage.getContent())
.addExtras(getAppExtra(pushMessage))
.build();
}
4、构建IOS通知推送
private IosNotification getIosNotification(PushMessageDTO pushMessage) throws UnsupportedEncodingException {
IosAlert alert = IosAlert.newBuilder().setTitleAndBody(pushMessage.getTitle(), pushMessage.getSubTitle(), pushMessage.getContent()).build();
return IosNotification.newBuilder()
//消息体
.setAlert(alert)
.setSound(pushMessage.getSound())
.setBadge(pushMessage.getBadge())
.addExtras(getAppExtra(pushMessage))
.setMutableContent(true)
.build();
}
5、获取Cid
/**
* 获取 cid, 避免同一个通知被调用多次
*
* @return 返回cid
*/
private String getCidAndReturnOneOfThem(JPushClient jPushClient) {
String value = null;
try {
CIDResult cidResult = jPushClient.getCidList(Constant.CID_COUNT, Constant.CID_TYPE);
value = cidResult.cidlist.get(0);
} catch (APIConnectionException | APIRequestException e) {
log.error("获取极光cid失败 ", e);
throw new ServiceException(ErrorCode.JPUSH_PARTNER_SYSTEM_ERROR);
}
return value;
}
6、设置推送平台
private NotificationPlatfo
rm pushIosMessage(PushMessageDTO pushMessage) throws UnsupportedEncodingException {
Platform platform = Platform.ios();
Notification notification = Notification.newBuilder()
.addPlatformNotification(getIosNotification(pushMessage))
.build();
return NotificationPlatform.builder()
.platform(platform)
.notification(notification)
.build();
}
private NotificationPlatform pushAndroidMessage(PushMessageDTO pushMessage) throws UnsupportedEncodingException {
Platform platform = Platform.android();
Notification notification = Notification.newBuilder()
.addPlatformNotification(getAndroidNotification(pushMessage))
.build();
return NotificationPlatform.builder()
.notification(notification)
.platform(platform)
.build();
}
private NotificationPlatform pushIosAndAndroidMessage(PushMessageDTO pushMessage) throws UnsupportedEncodingException {
Platform platform = Platform.all();
Notification notification = Notification.newBuilder()
.addPlatformNotification(getAndroidNotification(pushMessage))
.addPlatformNotification(getIosNotification(pushMessage))
.build();
return NotificationPlatform.builder()
.notification(notification)
.platform(platform)
.build();
}
7、生成缓存唯一的key
private String getPushKey(PushMessageDTO pushMessage) {
return DigestUtils.md5Hex(pushMessage.getContent() + pushMessage.getSound() +
pushMessage.getPushType() + pushMessage.getTitle() + pushMessage.getAudienceType()
+ DateUtil.getTodayTime());
}
8、生成cid缓存的key
private String getCidPushKey(PushMessageDTO pushMessage, List<String> part) {
return DigestUtils.md5Hex(pushMessage.getContent() + pushMessage.getSound() +
pushMessage.getPushType() + pushMessage.getTitle() + pushMessage.getAudienceType()
+ DateUtil.getTodayTime() + part.toString());
}
9、按照发送目标进行推送
private void pushMessageParts(List<List<String>> parts, Integer audienceType,
PushMessageDTO pushMessage, JPushClient jPushClient,
NotificationPlatform notificationPlatform, String pushKey) {
if (CollectionUtils.isEmpty(parts)) {
pushSendMessage(pushMessage, jPushClient, audienceType, notificationPlatform, pushKey, Collections.emptyList());
return;
}
for (List<String> part : parts) {
pushSendMessage(pushMessage, jPushClient, audienceType, notificationPlatform, pushKey, part);
}
}
10、添加客户端额外参数
private Map<String, String> getAppExtra(PushMessageDTO pushMessage) throws UnsupportedEncodingException {
Map<String, String> extra = new HashMap<>(16);
extra.put(Constant.APP_PUSH_ACTION, pushMessage.getAction());
extra.put(Constant.APP_PUSH_PAYLOAD, URLEncoder.encode(JsonUtil.toJsonString(pushMessage.getPayload()), StandardCharsets.UTF_8.name()));
return extra;
}
11、发送消息体
private void pushSendMessage(PushMessageDTO pushMessage, JPushClient jPushClient, Integer audienceType,
NotificationPlatform notificationPlatform, String pushKey, List<String> part) {
Audience audience;
if (CollectionUtils.isEmpty(part) && audienceType != 5) {
log.info("发送目标为空. pushMessage:{} ", pushMessage.toString());
return;
}
switch (audienceType) {
// 按标签推送
case 1:
audience = Audience.tag(part);
break;
//按registrationId发送
case 2:
audience = Audience.registrationId(part);
break;
//标签并集发送
case 3:
audience = Audience.tag_and(part);
break;
//标签先取并集 再取补集
case 4:
audience = Audience.tag_not(part);
break;
case 5:
audience = Audience.all();
part = Collections.emptyList();
break;
//按别名发送
case 6:
audience = Audience.alias(part);
break;
default:
log.error("推送目标类型参数错误: audience:{} ", audienceType.toString());
throw new ServiceException(ErrorCode.AUDIENCE_PUSH_TYPE_ERROR);
}
// 缓存key audience信息+内容+日期
String cidPushKey = getCidPushKey(pushMessage, part);
String pushKeyValue = redisUtil.get(cidPushKey);
if (StringUtils.isBlank(pushKeyValue)) {
pushKeyValue = getCidAndReturnOneOfThem(jPushClient);
redisUtil.set(cidPushKey, pushKeyValue);
}
String cid = pushKeyValue;
PushPayload payload = PushPayload.newBuilder()
.setPlatform(notificationPlatform.getPlatform())
.setAudience(audience)
.setNotification(notificationPlatform.getNotification())
.setOptions(Options.newBuilder().setApnsProduction(appApnsProduction)
.setTimeToLive(pushMessage.getTimeToLive())
.build())
.setCid(cid)
.build();
try {
jPushClient.sendPush(payload);
String[] audienceValue = part.toArray(new String[0]);
if (CollectionUtils.isNotEmpty(part)) {
redisUtil.lAddAll(pushKey, audienceValue, Constant.ONE_DAY);
}
} catch (APIConnectionException | APIRequestException e) {
log.error("消息发送失败: req:{}", payload, e);
throw new ServiceException(ErrorCode.JPUSH_PARTNER_SYSTEM_ERROR);
}
}
12、发送消息
private void pushMessageByType(PushMessageDTO pushMessage, NotificationPlatform notificationPlatform) {
JPushClient jPushClient = new JPushClient(masterSecret, appKey);
List<String> audienceInfoList = pushMessage.getAudienceInfo();
// 对发送的信息进行排序
Collections.sort(audienceInfoList);
// 过滤重复的信息 日期+内容等
String pushKey = getPushKey(pushMessage);
List<String> redisAudienceList = redisUtil.getList(pushKey);
if (CollectionUtils.isNotEmpty(redisAudienceList)) {
audienceInfoList = audienceInfoList.stream().filter(x -> !redisAudienceList.contains(x)).collect(Collectors.toList());
}
Integer audienceType = pushMessage.getAudienceType();
// 极光别名最多可以推送900个 数量超过则分开推送-- 极光官方支持1000 保险起见设为900
Integer step = Constant.PUSH_MAX_NUMBER;
if (audienceType.equals(Constant.TAG_PUSH_TYPE) || audienceType.equals(Constant.TAG_AND)
|| audienceType.equals(Constant.TAG_NOT)) {
// 标签最多客推15个 极光官方支持20 保险起见设为15
step = Constant.TAG_MAX_NUMBER;
}
List<List<String>> parts = ListUtils.partition(audienceInfoList, step);
pushMessageParts(parts, audienceType, pushMessage, jPushClient, notificationPlatform, pushKey);
jPushClient.close();
}