Commit fada5499 by giaogiao

完成apns推送第二版

parent ad1069e1
package io.geekidea.springbootplus.test;
import cn.hutool.core.codec.Base64;
import com.turo.pushy.apns.DeliveryPriority;
import com.turo.pushy.apns.PushType;
import com.wecloud.im.ws.sender.IosPush;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
public class IosApnsBase64Test {
public static void main(String[] args) throws IOException {
// apnsCertificatePath 证书
// * @param productFlag 环境
// * @param deviceToken 设备token
// * @param alertTitle 标题
// * @param alertBody 副标题
// * @param contentAvailable Boolean.FALSE
// * @param customProperty 自定义属性
// * @param badge 角标数量
// * @param priority DeliveryPriority.IMMEDIATE
// * @param pushType PushType.ALERT
// * @param topicBundleId undleId
// * @param sound rtc= "call.caf"; 否则为default
Map<String, Object> customProperty = new HashMap<String, Object>(10);
String apnsCertificatePath = "frogsell_push_dev.p12";
String deviceToken = "27c93ca84bbf17d9ff8eb05df0576ac49822db2ae1c02aa0afea83b5c3861276";
String alertTitle = "你好333";
String alertBody = "hi333";
int badge = 1;
String topicBundleId = "com.jdw.frogsell";
boolean contentAvailable = false;
InputStream certificate = IosPush.getApnsCertificate(apnsCertificatePath);
String encode = Base64.encode(certificate);
// 解码
byte[] decode = Base64.decode(encode);
InputStream inputStream2 = new ByteArrayInputStream(decode);
IosPush.push(inputStream2, Boolean.FALSE, deviceToken, alertTitle, alertBody,
contentAvailable, customProperty, badge
, DeliveryPriority.IMMEDIATE, PushType.ALERT, topicBundleId,
"default");
}
// public static byte[] readInputStream(InputStream inputStream) throws IOException {
// byte[] buffer = new byte[1024];
// int len = 0;
// ByteArrayOutputStream bos = new ByteArrayOutputStream();
// while ((len = inputStream.read(buffer)) != -1) {
// bos.write(buffer, 0, len);
// }
// bos.close();
// return bos.toByteArray();
// }
// private static String inputToString(InputStream is) throws IOException {
// final int bufferSize = 1024;
// final char[] buffer = new char[bufferSize];
// final StringBuilder out = new StringBuilder();
// Reader in = new InputStreamReader(is, StandardCharsets.UTF_8);
// for (; ; ) {
// int rsz = in.read(buffer, 0, buffer.length);
// if (rsz < 0)
// break;
// out.append(buffer, 0, rsz);
// }
// return out.toString();
// }
}
...@@ -27,7 +27,7 @@ public class IosApnsPushTest { ...@@ -27,7 +27,7 @@ public class IosApnsPushTest {
Map<String, Object> customProperty = new HashMap<String, Object>(10); Map<String, Object> customProperty = new HashMap<String, Object>(10);
String apnsCertificatePath = "frogsell_push_dev.p12"; String apnsCertificatePath = "frogsell_push_dev.p12";
String deviceToken = "27c93ca84bbf17d9ff8eb05df0576ac49822db2ae1c02aa0afea83b5c3861276"; String deviceToken = "27c93ca84bbf17d9ff8eb05df0576ac49822db2ae1c02aa0afea83b5c3861276";
String alertTitle = "你好"; String alertTitle = "你好22";
String alertBody = "hi"; String alertBody = "hi";
int badge = 1; int badge = 1;
String topicBundleId = "com.jdw.frogsell"; String topicBundleId = "com.jdw.frogsell";
......
...@@ -140,6 +140,16 @@ ...@@ -140,6 +140,16 @@
</dependencies> </dependencies>
<build> <build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.p12</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
<plugins> <plugins>
......
...@@ -65,6 +65,107 @@ public class IosPush { ...@@ -65,6 +65,107 @@ public class IosPush {
// String sound) { // String sound) {
// } // }
/**
* @param inputStream 证书输入流
* @param productFlag 环境
* @param deviceToken 设备token
* @param alertTitle 标题
* @param alertBody 副标题
* @param contentAvailable Boolean.FALSE
* @param customProperty 自定义属性
* @param badge 角标数量
* @param priority DeliveryPriority.IMMEDIATE
* @param pushType PushType.ALERT
* @param topicBundleId undleId
* @param sound rtc= "call.caf"; 否则为default
*/
public static void push(InputStream inputStream, Boolean productFlag, final String deviceToken, String alertTitle, String alertBody,
boolean contentAvailable, Map<String, Object> customProperty,
int badge, DeliveryPriority priority, PushType pushType, String topicBundleId,
String sound) {
String certificatePassword = "123456";
if (deviceToken == null || "".equals(deviceToken)) {
logger.error("deviceToken=null");
return;
}
long startTime = System.currentTimeMillis();
//每次完成一个任务(不一定需要线程走完),latch减1,直到所有的任务都完成,就可以执行下一阶段任务,可提高性能
final CountDownLatch latch = new CountDownLatch(1);
//线程安全的计数器
final AtomicLong successCnt = new AtomicLong(0);
ApnsPayloadBuilder payloadBuilder = new ApnsPayloadBuilder();
if (alertTitle != null) {
payloadBuilder.setAlertTitle(alertTitle);
}
if (alertBody != null) {
payloadBuilder.setAlertBody(alertBody);
}
payloadBuilder.setMutableContent(true);
//如果badge小于0,则不推送这个右上角的角标,主要用于消息盒子新增或者已读时,更新此状态
if (badge > 0) {
payloadBuilder.setBadgeNumber(badge);
}
if (!StringUtils.isEmpty(sound)) {
payloadBuilder.setSound(sound);
}
//将所有的附加参数全部放进去
if (customProperty != null) {
for (Map.Entry<String, Object> map : customProperty.entrySet()) {
payloadBuilder.addCustomProperty(map.getKey(), map.getValue());
}
}
payloadBuilder.setContentAvailable(contentAvailable);
String payload = payloadBuilder.buildWithDefaultMaximumLength();
final String token = TokenUtil.sanitizeTokenString(deviceToken);
SimpleApnsPushNotification pushNotification = new SimpleApnsPushNotification(token, topicBundleId, payload, new Date(), priority, pushType);
try {
//从信号量中获取一个允许机会
SEMAPHORE.acquire();
} catch (Exception e) {
//线程太多了,没有多余的信号量可以获取了
logger.error("ios push get semaphore failed, deviceToken:{}", deviceToken);
logger.error("ios push get semaphore failed", e);
}
logger.debug("token={},payload={}", token, payload);
ApnsClient apnsClient = getAPNSConnect(inputStream, productFlag, certificatePassword);
final Future<PushNotificationResponse<SimpleApnsPushNotification>> future = apnsClient.sendNotification(pushNotification);
future.addListener((GenericFutureListener<Future<PushNotificationResponse>>) pushNotificationResponseFuture -> {
if (future.isSuccess()) {
final PushNotificationResponse<SimpleApnsPushNotification> response = future.getNow();
if (response.isAccepted()) {
logger.debug("success token{}", token);
successCnt.incrementAndGet();
} else {
Date invalidTime = response.getTokenInvalidationTimestamp();
logger.error("Notification rejected by the APNs gateway: " + response.getRejectionReason() + ",payload:" + payload +
"\n,deviceToken:" + deviceToken
, ",alertBody:" + alertBody + ",sanitizeTokenString:" + token);
if (invalidTime != null) {
logger.error("\t…and the token is invalid as of " + response.getTokenInvalidationTimestamp());
}
}
} else {
logger.error("send notification device token={} is failed {} ", token, future.cause().getMessage());
}
latch.countDown();
//释放允许,将占有的信号量归还
SEMAPHORE.release();
});
try {
latch.await(20, TimeUnit.SECONDS);
} catch (InterruptedException e) {
logger.error("ios push latch await failed!", e);
}
long endPushTime = System.currentTimeMillis();
logger.debug("pushMessage success. [成功{}个,耗时{}ms]", successCnt.get(), endPushTime - startTime);
}
/** /**
* @param apnsCertificatePath 证书 * @param apnsCertificatePath 证书
...@@ -181,6 +282,28 @@ public class IosPush { ...@@ -181,6 +282,28 @@ public class IosPush {
/** /**
* 获取apns推送连接 * 获取apns推送连接
* *
* @param inputStream 证书文件
* @param productFlag 环境: true=正式, false测试
* @param certificatePassword ios证书通用密码
* @return
*/
public static ApnsClient getAPNSConnect(InputStream inputStream, Boolean productFlag, String certificatePassword) {
ApnsClient apnsXTClient = null;
try {
EventLoopGroup eventLoopGroup = new NioEventLoopGroup(4);
String environmentHost = productFlag ? ApnsClientBuilder.PRODUCTION_APNS_HOST : ApnsClientBuilder.DEVELOPMENT_APNS_HOST;
apnsXTClient = new ApnsClientBuilder().setApnsServer(environmentHost)
.setClientCredentials(inputStream, certificatePassword)
.setConcurrentConnections(4).setEventLoopGroup(eventLoopGroup).build();
} catch (Exception e) {
logger.error("ios get push apns client failed!", e);
}
return apnsXTClient;
}
/**
* 获取apns推送连接
*
* @param apnsCertificatePath 证书文件 * @param apnsCertificatePath 证书文件
* @param productFlag 环境: true=正式, false测试 * @param productFlag 环境: true=正式, false测试
* @param certificatePassword ios证书通用密码 * @param certificatePassword ios证书通用密码
...@@ -201,4 +324,9 @@ public class IosPush { ...@@ -201,4 +324,9 @@ public class IosPush {
return apnsXTClient; return apnsXTClient;
} }
public static InputStream getApnsCertificate(String apnsCertificatePath) {
return ClassLoader.getSystemClassLoader().getResourceAsStream(apnsCertificatePath);
}
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment