1.由於項目的需求,需要在Android APP上實現消息推送功能,所以引用了極光推送(官網:https://www.jiguang.cn/, 文檔:http://docs.jiguang.cn/)
2.極光推送是經過考驗的大規模app推送平台,極光推送目前每天推送消息數超過20億條。 開發者集成SDK后,可以通過調用API推送消息。同時,極光推送提供可視化的web端控制台發送通知,統計分析推送效果。 極光推送全面支持 Android, iOS, Winphone 三大手機平台。
3.要在自己項目集成極光推送功能,首先需要在逛網注冊一個極光賬號,獲取AppKey和masterSecret
4.項目集成java SDK,導入maven依賴
<dependency>
<groupId>cn.jpush.api</groupId>
<artifactId>jpush-client</artifactId>
<version>3.4.3</version>
</dependency>
<dependency>
<groupId>cn.jpush.api</groupId>
<artifactId>jiguang-common</artifactId>
<version>1.1.7</version>
</dependency>
<!--以上部分為極光推送所依賴的jar包-->
5.application.yml需要添加的配置
jpush:
appKey: 81a89169e875c793c1e1d862
masterSecret: 630c4f475810e7426f065b14
liveTime: 1000
apnsProduction: false # 是否生成環境,true表示生成環境
6.創建極光推送基本配置信息
@Component("jpushConfig") public class JpushConfig { /** * 極光推送的用戶名 */ @Value("${jpush.appKey}") private String appkey; /** * 極光推送的密碼 */ @Value("${jpush.masterSecret}") private String masterSecret; /** * 極光推送設置過期時間 */ @Value("${jpush.liveTime}") private String liveTime; public String getAppkey() { return appkey; } public void setAppkey(String appkey) { this.appkey = appkey; } public String getMasterSecret() { return masterSecret; } public void setMasterSecret(String masterSecret) { this.masterSecret = masterSecret; } public String getLiveTime() { return liveTime; } public void setLiveTime(String liveTime) { this.liveTime = liveTime; }
7.編寫極光推送工具類
@Service("jpushService") @Slf4j public class JpushUtils { @Resource JpushConfig jpushConfig; /** * 發送自定義消息,由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(jpushConfig.getLiveTime())); // 使用NativeHttpClient網絡客戶端,連接網絡的方式,不提供回調函數
JPushClient jpushClient = new JPushClient(jpushConfig.getMasterSecret(), jpushConfig.getAppkey(), null, clientConfig); // 設置為消息推送方式為僅推送消息,不創建通知欄提醒 // PushPayload payload = buildCustomPushPayload(title, content, extrasMap, alias);
PushPayload payload = buildCustomPushPayload(title, content, extrasMap, alias); PushResult result = jpushClient.sendPush(payload); return result; } /** * 發送通知消息 * * @param title App通知欄標題 * @param content App通知欄內容(為了單行顯示全,盡量保持在22個漢字以下) * @param extrasMap 額外推送信息(不會顯示在通知欄,傳遞數據用) * @param tags 標簽數組,設定哪些用戶手機能接收信息(為空則所有用戶都推送) */
public PushResult sendPush(String title, String content, Map<String, String> extrasMap, String... tags) throws APIConnectionException, APIRequestException { ClientConfig clientConfig = ClientConfig.getInstance(); clientConfig.setTimeToLive(Long.valueOf(jpushConfig.getLiveTime())); // 使用NativeHttpClient網絡客戶端,連接網絡的方式,不提供回調函數
JPushClient jpushClient = new JPushClient(jpushConfig.getMasterSecret(), jpushConfig.getAppkey(), null, clientConfig); // 設置推送方式
PushPayload payload = buildPushLoadByTags(title, content, extrasMap, tags); PushResult result = jpushClient.sendPush(payload); return result; } /** * 異步請求推送方式 * 使用NettyHttpClient,異步接口發送請求,通過回調函數可以獲取推送成功與否情況 * * @param title 通知欄標題 * @param content 通知欄內容(為了單行顯示全,盡量保持在22個漢字以下) * @param extrasMap 額外推送信息(不會顯示在通知欄,傳遞數據用) * @param alias 需接收的用戶別名數組(為空則所有用戶都推送) */
public void sendPushWithCallback(String title, String content, Map<String, String> extrasMap, String... alias) { ClientConfig clientConfig = ClientConfig.getInstance(); clientConfig.setTimeToLive(Long.valueOf(jpushConfig.getLiveTime())); String host = (String) clientConfig.get(ClientConfig.PUSH_HOST_NAME); NettyHttpClient client = new NettyHttpClient( ServiceHelper.getBasicAuthorization(jpushConfig.getAppkey(), jpushConfig.getMasterSecret()), 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 (200 == responseWrapper.responseCode) { log.info("極光推送成功"); } 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) throws APIConnectionException, APIRequestException { JPushClient jpushClient = new JPushClient(jpushConfig.getMasterSecret(), jpushConfig.getAppkey()); jpushClient.updateDeviceTagAlias(registrationId, alias, tagsToAdd, tagsToRemove); } /** * 構建Android和IOS的推送通知對象 * * @return PushPayload */
private PushPayload buildPushPayload(String title, String content, Map<String, String> extrasMap, String... alias) { if (extrasMap == null || extrasMap.isEmpty()) { extrasMap = new HashMap<String, String>(); } // 批量刪除數組中空元素
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 map 推送額外信息 * @param tags 推送的目標標簽 * @return
*/
public PushPayload buildPushLoadByTags(String title,String content,Map<String,String> map,String... tags) { if(map.isEmpty()){ map = new HashMap<>(); } //批量刪除數組中的空元素
String[] newTags = removeArrayEmptyElement(tags); return PushPayload.newBuilder() //設置推送平台為安卓
.setPlatform(Platform.android()) //設置標簽
.setAudience(Audience.tag(tags)) //設置 推送的標簽標題 // 設置通知方式(以alert方式提醒)
.setNotification(Notification.newBuilder().setAlert(content) .addPlatformNotification(AndroidNotification.newBuilder().setTitle(title).addExtras(map).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和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(alias)) .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(); } /** * 刪除別名中的空元素(需刪除如: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; }
8.測試類
@RunWith(SpringRunner.class) @SpringBootTest @Slf4j public class JgTest { @Autowired JpushUtils jpushUtils; @Test public void testSendMessage() throws APIConnectionException, APIRequestException { String title = "工單受理"; String content = "工單已發起,請開始受理工單信息,謝謝!"; Map<String,String> map = new HashedMap<>(); //設置標簽
HashSet hashSet = new HashSet(); hashSet.add("ywb"); //可以設置多個tag別名 //hashSet.add("客服");
map.put("message","額外的message消息"); //13_1711406300 12_1743331095
PushResult pushResult = jpushUtils.sendCustomPush(title, content, map, "17_ywb"); System.out.println(pushResult.getResponseCode()); //log.info(String.valueOf(pushResult.statusCode));
log.info(String.valueOf(pushResult.sendno)); //設置、更新、設備的 tag, alias 信息。140fe1da9e38e9efd3e
jpushUtils.UpdateDeviceTagAlias("140fe1da9ec6c5fc7af",null,hashSet,null); } @Test public void testSendMessageByTags() throws APIConnectionException, APIRequestException { String title = "工單受理new"; String content = "工單已發起,請開始受理工單信息,謝謝!"; Map<String,String> map = new HashedMap<>(); //設置標簽
HashSet hashSet = new HashSet(); hashSet.add("ywb"); //可以設置多個tag標簽 //hashSet.add("客服");
map.put("message","其他的message消息"); String[] tags = new String[]{"support"}; PushResult pushResult = jpushUtils.sendPush(title, content, map, tags); System.out.println(pushResult.getResponseCode()); } }
9.通過賬號登錄官網可以看到推送歷史記錄
詳細信息
10:注:手機安裝相應的App,安卓端需要知道當前注冊賬號的AppKey,然后就可以收到服務端發送的消息