Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wecloud_im_server
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
hewei
wecloud_im_server
Commits
fada5499
Commit
fada5499
authored
Sep 18, 2021
by
giaogiao
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
完成apns推送第二版
parent
ad1069e1
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
217 additions
and
1 deletions
+217
-1
bootstrap/src/test/java/io/geekidea/springbootplus/test/IosApnsBase64Test.java
+78
-0
bootstrap/src/test/java/io/geekidea/springbootplus/test/IosApnsPushTest.java
+1
-1
common/pom.xml
+10
-0
common/src/main/java/com/wecloud/im/ws/sender/IosPush.java
+128
-0
No files found.
bootstrap/src/test/java/io/geekidea/springbootplus/test/IosApnsBase64Test.java
0 → 100644
View file @
fada5499
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();
// }
}
bootstrap/src/test/java/io/geekidea/springbootplus/test/IosApnsPushTest.java
View file @
fada5499
...
...
@@ -27,7 +27,7 @@ public class IosApnsPushTest {
Map
<
String
,
Object
>
customProperty
=
new
HashMap
<
String
,
Object
>(
10
);
String
apnsCertificatePath
=
"frogsell_push_dev.p12"
;
String
deviceToken
=
"27c93ca84bbf17d9ff8eb05df0576ac49822db2ae1c02aa0afea83b5c3861276"
;
String
alertTitle
=
"你好"
;
String
alertTitle
=
"你好
22
"
;
String
alertBody
=
"hi"
;
int
badge
=
1
;
String
topicBundleId
=
"com.jdw.frogsell"
;
...
...
common/pom.xml
View file @
fada5499
...
...
@@ -140,6 +140,16 @@
</dependencies>
<build>
<resources>
<resource>
<directory>
src/main/resources
</directory>
<includes>
<include>
**/*.p12
</include>
</includes>
<filtering>
false
</filtering>
</resource>
</resources>
<plugins>
...
...
common/src/main/java/com/wecloud/im/ws/sender/IosPush.java
View file @
fada5499
...
...
@@ -65,6 +65,107 @@ public class IosPush {
// 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 证书
...
...
@@ -181,6 +282,28 @@ public class IosPush {
/**
* 获取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 productFlag 环境: true=正式, false测试
* @param certificatePassword ios证书通用密码
...
...
@@ -201,4 +324,9 @@ public class IosPush {
return
apnsXTClient
;
}
public
static
InputStream
getApnsCertificate
(
String
apnsCertificatePath
)
{
return
ClassLoader
.
getSystemClassLoader
().
getResourceAsStream
(
apnsCertificatePath
);
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment