1. 程式人生 > 其它 >java整合極光推送

java整合極光推送

技術標籤:工具類極光推送訊息推送

一. 前言:

上篇小熙介紹了信鴿推送,這篇繼續分享下極光推送的整合。

極光推送是第三方推送平臺,部分免費的第三方訊息推送服務,目前各方面都還不錯。極光推送讓開發者可以即時地向其應用程式的使用者推送通知或訊息,與使用者保持互動,從而有效地提高留存率。官方整合了Android推送、iOS推送的統一推送服務,傳送使用者的指定範圍也是有很多全面的選擇。
極光官網

二. 檢視:

展示圖:
極光

三. 依賴:

極光官網依賴座標:

		<!-- 極光推送 -->
        <dependency>
            <groupId>
cn.jpush.api</groupId> <artifactId>jpush-client</artifactId> <version>3.4.3</version> </dependency>

四. 官網摘錄:

  1. audience:推送目標

    推送裝置物件,表示一條推送可以被推送到哪些裝置列表。確認推送裝置物件,JPush 提供了多種方式,比如:別名、標籤、註冊 ID、分群、廣播等。

    all
    如果要發廣播(全部裝置),則直接填寫 “all”。

    基於業務優化的需求,極光將於 3 月 10 日對「廣播推送」的頻率進行限制,調整為 10 次每天,超過呼叫限制時將返回報錯碼 2008,官網控制檯將與 Push API 同步調整。

    注意:本次調整僅限制廣播,對廣播外的推送不影響。如廣播推送需更高頻率,請聯絡商務,詳情請閱讀公告。

    關鍵字型別含義說明備註
    tagJSON Array標籤OR陣列。多個標籤之間是 OR 的關係,即取並集。 用標籤來進行大規模的裝置屬性、使用者屬性分群。 一次推送最多 20 個。
    • 有效的 tag 組成:字母(區分大小寫)、數字、下劃線、漢字、特殊字元@!#$&*+=.|¥。
    • 限制:每一個 tag 的長度限制為 40 位元組。(判斷長度需採用 UTF-8 編碼)
    tag_andJSON Array標籤AND陣列。多個標籤之間是 AND 關係,即取交集。注意與 tag 區分。一次推送最多 20 個。
    tag_notJSON Array標籤NOT陣列。多個標籤之間,先取多標籤的並集,再對該結果取補集。一次推送最多 20 個。
    aliasJSON Array別名陣列。多個別名之間是 OR 關係,即取並集。用別名來標識一個使用者。一個裝置只能繫結一個別名,但多個裝置可以繫結同一個別名。一次推送最多 1000 個。
    • 有效的 alias 組成:字母(區分大小寫)、數字、下劃線、漢字、特殊字元@!#$&*+=.|¥。
    • 限制:每一個 alias 的長度限制為 40 位元組。(判斷長度需採用 UTF-8 編碼)
    registration_idJSON Array註冊ID陣列。多個註冊 ID 之間是 OR 關係,即取並集。裝置標識。一次推送最多 1000 個。客戶端整合 SDK 後可獲取到該值。如果您一次推送的 registration_id 值超過 1000 個,可以直接使用 檔案推送 功能。
    segmentJSON Array使用者分群 ID 在頁面建立的使用者分群的 ID。定義為陣列,但目前限制一次只能推送一個。目前限制是一次只能推送一個。
    abtestJSON ArrayA/B Test ID在頁面建立的 A/B 測試的 ID。定義為陣列,但目前限制是一次只能推送一個。目前限制一次只能推送一個。

官網更多詳情

五. 配置程式碼:

  1. yml中的資料:

    # 極光推送 (true測試環境,false正式環境)
    jpush:
      environment: false
      appKey: d88ba5384916a5c839xxxxxxx
      masterSecret: 1d6cb3e961ec5d360xxxxxx
    
  2. 拓展資訊封裝類:

    package com.chengxi.datalom.utils.jPush;
    
    import lombok.Data;
    import lombok.experimental.Accessors;
    
    /**
     * 極光拓展欄位不能傳輸object,限制了型別,所以封裝更好些
     * 此類為極光推送拓展欄位封裝類(目前欄位是暫定,你也可以拓展)
     *
     * @author chengxi
     * @date 2020/12/9 14:08
     */
    @Data
    @Accessors(chain = true)
    public class JPushVO {
    
        private Long id;
    
        private String userName;
    
        private String content;
    
    }
    
    
  3. 抽象工具父類:

    package com.chengxi.datalom.utils.jPush;
    
    import cn.jiguang.common.resp.APIConnectionException;
    import cn.jiguang.common.resp.APIRequestException;
    import cn.jpush.api.JPushClient;
    import cn.jpush.api.push.PushResult;
    import cn.jpush.api.push.model.Message;
    import cn.jpush.api.push.model.Options;
    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.IosAlert;
    import cn.jpush.api.push.model.notification.IosNotification;
    import cn.jpush.api.push.model.notification.Notification;
    import com.alibaba.fastjson.JSON;
    import com.chengxi.datalom.config.jPush.JPushConfig;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    
    import javax.annotation.PostConstruct;
    
    /**
     * 程熙cjp:https://blog.csdn.net/weixin_41133233
     * 極光抽象推送工具類
     *
     * @author chengxi
     * @date 2020/12/9 16:06
     */
    @Slf4j
    @Component
    public abstract class AbstractJPushToolUtil {
    
        @Autowired
        private JPushConfig jPush;
    
        protected static AbstractJPushToolUtil abstractJPushToolUtils;
    
        @PostConstruct
        public void init() {
            abstractJPushToolUtils = this;
        }
    
        /**
         * 獲取JPushClient例項
         *
         * @return
         */
        private static JPushClient getJPushClient() {
            JPushClient jPushClient = new JPushClient(abstractJPushToolUtils.jPush.getMasterSecret(), abstractJPushToolUtils.jPush.getAppKey());
            return jPushClient;
        }
    
    
        /**
         * 獲取推送建立build
         *
         * @param platform
         * @param audience
         * @param offlineSaveSeconds
         * @param msgTitle
         * @param msgContent
         * @param jPushVO
         * @param sendNo
         * @return
         */
        protected static PushPayload.Builder queryPushPayloadBuilder(Platform platform, Audience audience, Long offlineSaveSeconds, String msgTitle, String msgContent, JPushVO jPushVO, Integer sendNo) {
            return PushPayload.newBuilder()
                    //指定要推送的平臺,all代表當前應用配置了的所有平臺,也可以傳android、ios等具體平臺
                    .setPlatform(platform)
                    //指定推送的接收物件,all代表所有人,也可以指定已經設定成功的tag或alias或該應應用客戶端呼叫介面獲取到的registration id
                    .setAudience(audience)
                    //Platform指定了哪些平臺就會像指定平臺中符合推送條件的裝置進行推送。 jpush的自定義訊息,
                    // sdk預設不做任何處理,不會有通知提示。建議看文件http://docs.jpush.io/guideline/faq/的
                    // [通知與自定義訊息有什麼區別?]瞭解通知和自定義訊息的區別
                    .setMessage(Message.newBuilder().setTitle(msgTitle).setMsgContent(msgContent).addExtra("data", JSON.toJSONString(jPushVO)).build())
                    .setOptions(Options.newBuilder()
                            //此欄位的值是用來指定本推送要推送的apns環境,false表示開發,true表示生產;對android和自定義訊息無意義
                            .setApnsProduction(abstractJPushToolUtils.jPush.getEnvironment())
                            //此欄位是給開發者自己給推送編號,方便推送者分辨推送記錄,預設為1
                            .setSendno(sendNo == null ? 1 : sendNo)
                            //此欄位的值是用來指定本推送的離線儲存時長,如果不傳此欄位則預設儲存一天,最多指定保留十天,單位為秒
                            .setTimeToLive(offlineSaveSeconds)
                            .build());
        }
    
        /**
         * 傳送給所有使用者(目前預設安卓和ios)
         *
         * @param audience
         * @param offlineSaveSeconds
         * @param notificationTitle
         * @param msgTitle
         * @param msgContent
         * @param jPushVO
         * @param sendNo
         * @return
         */
        public static boolean sendToAll(Audience audience, Long offlineSaveSeconds, String notificationTitle, String msgTitle, String msgContent, JPushVO jPushVO, Integer sendNo) {
            boolean result = false;
            try {
                PushPayload pushPayload = queryPushPayloadBuilder(Platform.android_ios(), audience, offlineSaveSeconds, msgTitle, msgContent, null, sendNo)
                        .setNotification(Notification.newBuilder()
                                //指定當前推送的android通知
                                .addPlatformNotification(queryAndroidNotification(notificationTitle, msgContent, jPushVO))
                                //指定當前推送的ios通知
                                .addPlatformNotification(queryIosNotification(queryIosAlert(notificationTitle, msgContent, msgContent), jPushVO))
                                .build())
                        .build();
                PushResult pushResult = getJPushClient().sendPush(pushPayload);
                if (pushResult.getResponseCode() == 200) {
                    result = true;
                }
                log.info("[極光推送]PushResult result is " + pushResult);
            } catch (APIConnectionException e) {
                log.error("[極光推送]Connection error. Should retry later. ", e);
            } catch (APIRequestException e) {
                log.error("[極光推送]Error response from JPush server. Should review and fix it. ", e);
                printAPIRequestErrorLogInfo(e);
            }
    
            return result;
        }
    
        /**
         * 傳送給安卓使用者
         *
         * @param audience
         * @param offlineSaveSeconds
         * @param notificationTitle
         * @param msgTitle
         * @param msgContent
         * @param jPushVO
         * @return
         */
        public static boolean sendToAndroid(Audience audience, Long offlineSaveSeconds, String notificationTitle, String msgTitle, String msgContent, JPushVO jPushVO, Integer sendNo) {
            boolean result = false;
            try {
                PushPayload pushPayload = queryPushPayloadBuilder(Platform.android(), audience, offlineSaveSeconds, msgTitle, msgContent, null, sendNo)
                        .setNotification(Notification.newBuilder()
                                //指定當前推送的android通知
                                .addPlatformNotification(queryAndroidNotification(notificationTitle, msgContent, jPushVO))
                                .build())
                        .build();
                PushResult pushResult = getJPushClient().sendPush(pushPayload);
                if (pushResult.getResponseCode() == 200) {
                    result = true;
                }
                log.info("[極光推送]PushResult result is " + pushResult);
            } catch (APIConnectionException e) {
                log.error("[極光推送]Connection error. Should retry later. ", e);
            } catch (APIRequestException e) {
                log.error("[極光推送]Error response from JPush server. Should review and fix it. ", e);
                printAPIRequestErrorLogInfo(e);
            }
    
            return result;
        }
    
    
        /**
         * 傳送給IOS使用者
         *
         * @param audience
         * @param offlineSaveSeconds
         * @param notificationTitle
         * @param msgTitle
         * @param msgContent
         * @param jPushVO
         * @return
         */
        public static boolean sendToIos(Audience audience, Long offlineSaveSeconds, String notificationTitle, String msgTitle, String msgContent, JPushVO jPushVO, Integer sendNo) {
            boolean result = false;
            try {
                PushPayload pushPayload = queryPushPayloadBuilder(Platform.ios(), audience, offlineSaveSeconds, msgTitle, msgContent, jPushVO, sendNo)
                        .setNotification(Notification.newBuilder()
                                //指定當前推送的Ios通知
                                // .addPlatformNotification(builder.build()).build())
                                .addPlatformNotification(queryIosNotification(queryIosAlert(notificationTitle, msgTitle, msgContent), jPushVO))
                                .build())
                        .build();
                PushResult pushResult = getJPushClient().sendPush(pushPayload);
                if (pushResult.getResponseCode() == 200) {
                    result = true;
                }
                log.info("[極光推送]PushResult result is " + pushResult);
            } catch (APIConnectionException e) {
                log.error("[極光推送]Connection error. Should retry later. ", e);
            } catch (APIRequestException e) {
                log.error("[極光推送]Error response from JPush server. Should review and fix it. ", e);
                printAPIRequestErrorLogInfo(e);
            }
    
            return result;
        }
    
        /**
         * 列印APIRequestErrorLogInfo
         *
         * @param e
         */
        private static void printAPIRequestErrorLogInfo(APIRequestException e) {
            log.info("[極光推送]HTTP Status: " + e.getStatus());
            log.info("[極光推送]Error Code: " + e.getErrorCode());
            log.info("[極光推送]Error Message: " + e.getErrorMessage());
        }
    
        /**
         * AndroidNotification
         *
         * @param notificationTitle
         * @param msgContent
         * @param jPushVO
         * @return
         */
        private static AndroidNotification queryAndroidNotification(String notificationTitle, String msgContent, JPushVO jPushVO) {
            return AndroidNotification.newBuilder()
                    .setTitle(notificationTitle)
                    .setAlert(msgContent)
                    //此欄位為透傳欄位(型別被極光限定,不能傳object),不會顯示在通知欄。使用者可以通過此欄位來做一些定製需求,如特定的key傳要指定跳轉的頁面(value)
                    .addExtra("data", JSON.toJSONString(jPushVO))
                    .build();
        }
    
        /**
         * 獲取IosNotificationBuilder
         *
         * @param iosAlert
         * @param jPushVO
         * @return
         */
        private static IosNotification queryIosNotification(IosAlert iosAlert, JPushVO jPushVO) {
            return IosNotification.newBuilder()
                    //ios不支援直接設定title,你可以傳一個IosAlert物件哪裡再解析,指定apns title、title、subtitle(這裡的key參考官方文件)等
    //                .setAlert(IosAlert.newBuilder().setTitleAndBody(notificationTitle, null, msgContent).build())
                    .setAlert(iosAlert)
                    //直接傳alert
                    //此項是指定此推送的badge自動加1
                    .incrBadge(1)
                    // .setBadge(+1)
                    //此欄位的值default表示系統預設聲音;傳sound.caf表示此推送以專案裡面打包的sound.caf聲音來提醒,
                    // 如果系統沒有此音訊則以系統預設聲音提醒;此欄位如果傳空字串,iOS9及以上的系統是無聲音提醒,以下的系統是預設聲音
                    .setSound("sound.caf")
                    // .setSound("happy")
                    //此欄位為透傳欄位(型別被極光限定,不能傳object),不會顯示在通知欄。使用者可以通過此欄位來做一些定製需求,如特定的key傳要指定跳轉的頁面(value)
                    .addExtra("data", JSON.toJSONString(jPushVO))
                    //此項說明此推送是一個background推送,想了解background看:http://docs.jpush.io/client/ios_tutorials/#ios-7-background-remote-notification
                    // .setContentAvailable(true)
                    .build();
        }
    
        /**
         * 獲取IOS的IosAlert
         *
         * @param notificationTitle
         * @param subTitle
         * @param msgContent
         * @return
         */
        private static IosAlert queryIosAlert(String notificationTitle, String subTitle, String msgContent) {
            return IosAlert.newBuilder().setTitleAndBody(notificationTitle, subTitle, msgContent).build();
        }
    
        /**
         * 獲取IOS的IosAlert
         *
         * @param notificationTitle
         * @param msgContent
         * @return
         */
        private static IosAlert queryIosAlert(String notificationTitle, String msgContent) {
            return queryIosAlert(notificationTitle, null, msgContent);
        }
    
    }
    
    
  4. 使用工具類:

    package com.chengxi.datalom.utils.jPush;
    
    import cn.jpush.api.push.model.audience.Audience;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.stereotype.Component;
    
    import java.util.List;
    
    /**
     * 程熙cjp:https://blog.csdn.net/weixin_41133233
     * 極光推送工具類
     * audience 型別還有很多用法,這裡是基礎的可以根據需要傳送的範圍進行修改
     * 請參考官網詳細說明:http://docs.jiguang.cn/jpush/server/push/rest_api_v3_push/#audience
     *
     * @author chengxi
     * @date 2020/12/9 15:53
     */
    @Slf4j
    @Component
    public class JPushToolUtil extends AbstractJPushToolUtil {
    
        /**
         * 傳送給所有使用者(預設安卓和ios端)
         *
         * @param notificationTitle
         * @param msgTitle
         * @param msgContent
         * @param jPushVO
         * @return
         */
        public static boolean sendToAll(String notificationTitle, String msgTitle, String msgContent, JPushVO jPushVO) {
            return sendToAll(Audience.all(), 86400L, notificationTitle, msgTitle, msgContent, jPushVO, null);
        }
    
        /**
         * 傳送給批量(別名)使用者(預設安卓和ios端)
         *
         * @param notificationTitle
         * @param msgTitle
         * @param msgContent
         * @param jPushVO
         * @param aliasList
         * @return
         */
        public static boolean sendToAliasListAll(String notificationTitle, String msgTitle, String msgContent, JPushVO jPushVO, List<String> aliasList) {
            return sendToAll(Audience.alias(aliasList), 86400L, notificationTitle, msgTitle, msgContent, jPushVO, null);
        }
    
        /**
         * 傳送給批量(標籤)使用者(預設安卓和ios端)
         *
         * @param notificationTitle
         * @param msgTitle
         * @param msgContent
         * @param jPushVO
         * @param tagList
         * @return
         */
        public static boolean sendToTagListAll(String notificationTitle, String msgTitle, String msgContent, JPushVO jPushVO, List<String> tagList) {
            return sendToAll(Audience.tag(tagList), 86400L, notificationTitle, msgTitle, msgContent, jPushVO, null);
        }
    
        /**
         * 傳送給批量(不在標籤集合中的)使用者(預設安卓和ios端)
         *
         * @param notificationTitle
         * @param msgTitle
         * @param msgContent
         * @param jPushVO
         * @param tagNotList
         * @return
         */
        public static boolean sendToNotTagListAll(String notificationTitle, String msgTitle, String msgContent, JPushVO jPushVO, List<String> tagNotList) {
            return sendToAll(Audience.tag_not(tagNotList), 86400L, notificationTitle, msgTitle, msgContent, jPushVO, null);
        }
    
        /**
         * 傳送給所有安卓使用者(預設全部並且保留離線儲存時長為一天)
         *
         * @param notificationTitle
         * @param msgTitle
         * @param msgContent
         * @param jPushVO
         * @return
         */
        public static boolean sendToAllAndroid(String notificationTitle, String msgTitle, String msgContent, JPushVO jPushVO) {
            return sendToAndroid(Audience.all(), 86400L, notificationTitle, msgTitle, msgContent, jPushVO, null);
        }
    
        /**
         * 傳送給批量(別名)安卓使用者(預設全部並且保留離線儲存時長為一天)
         *
         * @param notificationTitle
         * @param msgTitle
         * @param msgContent
         * @param jPushVO
         * @param aliasList
         * @return
         */
        public static boolean sendToAliasListAndroid(String notificationTitle, String msgTitle, String msgContent, JPushVO jPushVO, List<String> aliasList) {
            return sendToAndroid(Audience.alias(aliasList), 86400L, notificationTitle, msgTitle, msgContent, jPushVO, null);
        }
    
        /**
         * 傳送給批量(標籤中的)安卓使用者(預設全部並且保留離線儲存時長為一天)
         *
         * @param notificationTitle
         * @param msgTitle
         * @param msgContent
         * @param jPushVO
         * @param tagList
         * @return
         */
        public static boolean sendToTagListAndroid(String notificationTitle, String msgTitle, String msgContent, JPushVO jPushVO, List<String> tagList) {
            return sendToAndroid(Audience.tag(tagList), 86400L, notificationTitle, msgTitle, msgContent, jPushVO, null);
        }
    
        /**
         * 傳送給批量(不在標籤中的)安卓使用者(預設全部並且保留離線儲存時長為一天)
         *
         * @param notificationTitle
         * @param msgTitle
         * @param msgContent
         * @param jPushVO
         * @param tagNotList
         * @return
         */
        public static boolean sendToNotTagListAndroid(String notificationTitle, String msgTitle, String msgContent, JPushVO jPushVO, List<String> tagNotList) {
            return sendToAndroid(Audience.tag(tagNotList), 86400L, notificationTitle, msgTitle, msgContent, jPushVO, null);
        }
    
        /**
         * 傳送給所有ios使用者(預設全部並且保留離線儲存時長為一天)
         * @param notificationTitle
         * @param msgTitle
         * @param msgContent
         * @param jPushVO
         * @return
         */
        public static boolean sendToAllIos(String notificationTitle, String msgTitle, String msgContent, JPushVO jPushVO) {
            return sendToIos(Audience.all(), 86400L, notificationTitle, msgTitle, msgContent, jPushVO, null);
        }
    
        /**
         * 傳送給批量(別名)ios使用者(預設全部並且保留離線儲存時長為一天)
         * @param notificationTitle
         * @param msgTitle
         * @param msgContent
         * @param jPushVO
         * @return
         */
        public static boolean sendToAliasListIos(String notificationTitle, String msgTitle, String msgContent, JPushVO jPushVO, List<String> aliasList) {
            return sendToIos(Audience.alias(aliasList), 86400L, notificationTitle, msgTitle, msgContent, jPushVO, null);
        }
    
        /**
         * 傳送給批量(標籤中的)ios使用者(預設全部並且保留離線儲存時長為一天)
         * @param notificationTitle
         * @param msgTitle
         * @param msgContent
         * @param jPushVO
         * @param tagList
         * @return
         */
        public static boolean sendToTagListIos(String notificationTitle, String msgTitle, String msgContent, JPushVO jPushVO, List<String> tagList) {
            return sendToIos(Audience.tag(tagList), 86400L, notificationTitle, msgTitle, msgContent, jPushVO, null);
        }
    
        /**
         * 傳送給批量(不在標籤中的)ios使用者(預設全部並且保留離線儲存時長為一天)
         * @param notificationTitle
         * @param msgTitle
         * @param msgContent
         * @param jPushVO
         * @param tagNotList
         * @return
         */
        public static boolean sendToNotTagListIos(String notificationTitle, String msgTitle, String msgContent, JPushVO jPushVO, List<String> tagNotList) {
            return sendToIos(Audience.tag(tagNotList), 86400L, notificationTitle, msgTitle, msgContent, jPushVO, null);
        }
    
    
    }
    
    

六. 示例:

下面是小熙的測試用例:

    @Test
    public void testJPush() {
        JPushVO pushVO = new JPushVO();
        pushVO.setId(1L);
        pushVO.setUserName("程熙");
        pushVO.setContent("My name is Xiao Xi");
        System.err.println(JPushToolUtil.sendToAll("通知標題", "訊息標題", "訊息內容", pushVO));
    }

七. 後語:

至此小熙就分享完後端整合極光推送了,前端整合也是還需要按照官網流程操作生成應用,獲取對應key,想實現更多功能還是建議多看看官方文件。他的玩法和示例比信鴿要全很多。