XPush 一個輕量級、可插拔的Android消息推送框架

XPush

api
I
Star

一個輕量級、可插拔的Android消息推送框架。一鍵集成推送(極光推送、友盟推送、華爲、小米推送等),提供有效的保活機制,支持推送的拓展,充分解耦推送和業務邏輯,解放你的雙手!java

在提issue前,請先閱讀【提問的智慧】,並嚴格按照issue模板進行填寫,節約你們的時間。android

在使用前,請必定要仔細閱讀使用說明文檔,重要的事情說三遍!!!git

在使用前,請必定要仔細閱讀使用說明文檔,重要的事情說三遍!!!github

在使用前,請必定要仔細閱讀使用說明文檔,重要的事情說三遍!!!apache

關於我

github
csdn
簡書
掘金
知乎


特徵

  • 集成方便。只需幾行代碼便可實現推送的集成,目前已經提供極光、友盟等推送渠道,除此以外還能夠根據本身的須要進行擴展。json

  • 兼容性強。目前已完美支持Android 9.0。api

  • 功能強大。支持推送相關的註冊、註銷,標籤的增長、刪除、獲取,別名的綁定、解綁、獲取,推送的鏈接狀態獲取等操做,並能返回響應的結果;支持接收推送通知、通知的點擊事件、自定義消息等推送類型。bash

  • 統一的消息訂閱。框架提供了統一的消息訂閱渠道,不管你使用了何種推送方式,均可以在任何地方進行推送消息的訂閱和取消訂閱,方便消息的接收和處理。服務器

  • 支持增長消息過濾器。相似OkHttp中的攔截器,能夠對接收的消息進行全局過濾,過濾出那些咱們真正須要的推送消息。app

  • 提供有效的保活機制。保證接入XPush的應用消息推送的到達率和穩定性,這也是不少推送框架所作不到的。

組成結構

本框架借鑑了OnePush(目前已不維護了)中的部分思想,加之我3年消息推送的經驗,造成了以下幾個部分:

  • 消息推送客戶端IPushClient:主要提供消息推送平臺的主要API。

  • 消息推送事件轉發器IPushDispatcher:主要用於將第三方的消息推送事件轉發爲XPush可識別的事件。

  • 消息推送接收器IPushReceiver:統一接收IPushDispatcher轉發過來的事件,是事件的接收中心。

  • 推送消息的被觀察者IMessageObservable:主要負責管理推送消息的訂閱和轉發。

  • 推送消息的過濾策略IMessageFilterStrategy:主要負責推送消息的過濾處理和管理。

以上5個組成部分能夠根據你自身的業務需求進行自定義。

消息推送流程

在後臺發出一則推送消息後:

第三方推送平臺 --- (消息) ---> 第三方推送平臺內部的接收消息的Receiver --->(重寫其接收的方法)---> IPushDispatcher ---> (轉發消息內容爲XPushMsg/XPushCommand)---> IPushReceiver ---> (如不使用XPushManager提供的消息管理,這裏直接結束)

    【使用XPushManager提供的消息管理】:---IPushReceiver---> XPushManager -----> IMessageFilterStrategy --->(對消息進行過濾處理)---> IMessageObservable ---> (消息轉發到具體訂閱的地方)

複製代碼

爲何要作這個項目

作過Android消息推送的人都知道,Android不只設備碎片化嚴重,推送平臺也是五花八門的。早在2017年工信部就號召全部的廠商來制定統一的Android消息推送平臺,可到如今也沒有下文(究其緣由仍是這其中的利益太大了,誰也不想妥協)。

但是咱們也不能將但願全都寄託在這個徹底沒有定數的事件上,代碼終歸要寫,功能終歸要上,與其受制於人,不如本身革命,搞一個本身能控制的消息推送全平臺解決方案來得靠譜。

可能有人又會說,如今友盟和信鴿都支持廠商推送的集成,爲什麼你本身還要搞一套呢?若是你對推送的及時性和到達率都沒什麼要求的話,其實也是無所謂的(實踐證實,並很差用)。在這裏我須要說明的是,你不可能把本身的命運交到別人的手裏,推送有別於其餘的業務,相對來講比較複雜,須要處理大批量的事件消息,對服務器的要求比較大,你願意把你的推送消息交給第三方推送平臺去處理?再說了,你能強制大家後臺接入指定第三方的推送平臺?若是都不能,與其受制於人,何不把這些命運把握在本身的手上,那麼寫出來的功能本身也安心啊。

以前在QQ交流羣裏一直有人但願我開源一個消息推送框架,其實我在上一家公司的時候就寫了一個推送框架,只不過捆綁業務太深,加之避開泄密之嫌,也就沒有開源的必要。這次的推送框架徹底是從新寫了一個,加之全新的設計,會使框架更加通用,靈活。


快速集成指南

添加Gradle依賴

1.先在項目根目錄的 build.gradle 的 repositories 添加:

allprojects {
    repositories {
        ...
        maven { url "https://jitpack.io" }
    }
}
複製代碼

2.添加XPush主要依賴:

dependencies {
  ...
  //推送核心庫
  implementation 'com.github.xuexiangjys.XPush:xpush-core:1.0.0'
  //推送保活庫
  implementation 'com.github.xuexiangjys.XPush:keeplive:1.0.0'
}
複製代碼

3.添加第三方推送依賴(根據本身的需求進行添加,固然也能夠所有添加)

dependencies {
  ...
  //選擇你想要集成的推送庫
  implementation 'com.github.xuexiangjys.XPush:xpush-jpush:1.0.0'
  implementation 'com.github.xuexiangjys.XPush:xpush-umeng:1.0.0'
  implementation 'com.github.xuexiangjys.XPush:xpush-huawei:1.0.0'
  implementation 'com.github.xuexiangjys.XPush:xpush-xiaomi:1.0.0'
}
複製代碼

初始化XPush配置

1.註冊消息推送接收器。方法有兩種,選其中一種就好了。

  • 若是你想使用XPushManager提供的消息管理,直接在AndroidManifest.xml中註冊框架默認提供的XPushReceiver。固然你也能夠繼承XPushReceiver,並重寫相關方法。

  • 若是你想實現本身的消息管理,可繼承AbstractPushReceiver類,重寫裏面的方法,並在AndroidManifest.xml中註冊。

<!--自定義消息推送接收器-->
    <receiver android:name=".push.CustomPushReceiver">
        <intent-filter>
            <action android:name="com.xuexiang.xpush.core.action.RECEIVE_CONNECT_STATUS_CHANGED" />
            <action android:name="com.xuexiang.xpush.core.action.RECEIVE_NOTIFICATION" />
            <action android:name="com.xuexiang.xpush.core.action.RECEIVE_NOTIFICATION_CLICK" />
            <action android:name="com.xuexiang.xpush.core.action.RECEIVE_MESSAGE" />
            <action android:name="com.xuexiang.xpush.core.action.RECEIVE_COMMAND_RESULT" />

            <category android:name="${applicationId}" />
        </intent-filter>
    </receiver>

    <!--默認的消息推送接收器-->
    <receiver android:name="com.xuexiang.xpush.core.receiver.impl.XPushReceiver">
        <intent-filter>
            <action android:name="com.xuexiang.xpush.core.action.RECEIVE_CONNECT_STATUS_CHANGED" />
            <action android:name="com.xuexiang.xpush.core.action.RECEIVE_NOTIFICATION" />
            <action android:name="com.xuexiang.xpush.core.action.RECEIVE_NOTIFICATION_CLICK" />
            <action android:name="com.xuexiang.xpush.core.action.RECEIVE_MESSAGE" />
            <action android:name="com.xuexiang.xpush.core.action.RECEIVE_COMMAND_RESULT" />

            <category android:name="${applicationId}" />
        </intent-filter>
    </receiver>
複製代碼

注意,若是你的Android設備是8.0及以上的話,靜態註冊的廣播是沒法正常生效的,解決的方法有兩種:

  • 動態註冊消息推送接收器

  • 修改推送消息的發射器

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    //Android8.0靜態廣播註冊失敗解決方案一:動態註冊
    XPush.registerPushReceiver(new CustomPushReceiver());

    //Android8.0靜態廣播註冊失敗解決方案二:修改發射器
    XPush.setIPushDispatcher(new Android26PushDispatcherImpl(CustomPushReceiver.class));
}
複製代碼

2.在AndroidManifest.xml的application標籤下,添加第三方推送客戶端實現類.

須要注意的是,這裏註冊的PlatformNamePlatformCode必需要和推送客戶端實現類中的一一對應才行。

<!--name格式:XPush_[PlatformName]_[PlatformCode]-->
<!--value格式:對應客戶端實體類的全類名路徑-->

<!--若是引入了xpush-jpush庫-->
<meta-data
    android:name="XPush_JPush_1000"
    android:value="com.xuexiang.xpush.jpush.JPushClient" />

<!--若是引入了xpush-umeng庫-->
<meta-data
    android:name="XPush_UMengPush_1001"
    android:value="com.xuexiang.xpush.umeng.UMengPushClient" />
    
<!--若是引入了xpush-huawei庫-->
<meta-data
    android:name="XPush_HuaweiPush_1002"
    android:value="com.xuexiang.xpush.huawei.HuaweiPushClient" />

<!--若是引入了xpush-xiaomi庫-->
<meta-data
    android:name="XPush_MIPush_1003"
    android:value="com.xuexiang.xpush.xiaomi.XiaoMiPushClient" />

複製代碼

3.添加第三方AppKey和AppSecret.

這裏的AppKey和AppSecret須要咱們到各自的推送平臺上註冊應用後得到。注意若是使用了xpush-xiaomi,那麼須要在AndroidManifest.xml添加小米的AppKey和AppSecret(注意下面的「\ 」必須加上,不然獲取到的是float而不是String,就會致使id和key獲取不到正確的數據)。

<!--極光推送靜態註冊-->
<meta-data
    android:name="JPUSH_CHANNEL"
    android:value="default_developer" />
<meta-data
    android:name="JPUSH_APPKEY"
    android:value="a32109db64ebe04e2430bb01" />

<!--友盟推送靜態註冊-->
<meta-data
    android:name="UMENG_APPKEY"
    android:value="5d5a42ce570df37e850002e9" />
<meta-data
    android:name="UMENG_MESSAGE_SECRET"
    android:value="4783a04255ed93ff675aca69312546f4" />
    
<!--華爲HMS推送靜態註冊-->
<meta-data
    android:name="com.huawei.hms.client.appid"
    android:value="101049475"/>

<!--小米推送靜態註冊,下面的「\ 」必須加上,不然將沒法正確讀取-->
<meta-data
    android:name="MIPUSH_APPID"
    android:value="\ 2882303761518134164"/>
<meta-data
    android:name="MIPUSH_APPKEY"
    android:value="\ 5371813415164"/>
複製代碼

4.在Application中初始化XPush

初始化XPush的方式有兩種,根據業務須要選擇一種方式就好了:

  • 靜態註冊
/**
 * 靜態註冊初始化推送
 */
private void initPush() {
    XPush.debug(BuildConfig.DEBUG);
    //靜態註冊,指定使用友盟推送客戶端
    XPush.init(this, new UMengPushClient());
    XPush.register();
}
複製代碼
  • 動態註冊
/**
 * 動態註冊初始化推送
 */
private void initPush() {
    XPush.debug(BuildConfig.DEBUG);
    //動態註冊,根據平臺名或者平臺碼動態註冊推送客戶端
    XPush.init(this, new IPushInitCallback() {
        @Override
        public boolean onInitPush(int platformCode, String platformName) {
            String romName = RomUtils.getRom().getRomName();
            if (romName.equals(SYS_EMUI)) {
                return platformCode == HuaweiPushClient.HUAWEI_PUSH_PLATFORM_CODE && platformName.equals(HuaweiPushClient.HUAWEI_PUSH_PLATFORM_NAME);
            } else if (romName.equals(SYS_MIUI)) {
                return platformCode == XiaoMiPushClient.MIPUSH_PLATFORM_CODE && platformName.equals(XiaoMiPushClient.MIPUSH_PLATFORM_NAME);
            } else {
                return platformCode == JPushClient.JPUSH_PLATFORM_CODE && platformName.equals(JPushClient.JPUSH_PLATFORM_NAME);
            }
        }
    });
    XPush.register();
}
複製代碼

如何使用XPush

一、推送的註冊和註銷

  • 經過調用XPush.register(),便可完成推送的註冊。

  • 經過調用XPush.unRegister(),便可完成推送的註銷。

  • 經過調用XPush.getPushToken(),便可獲取消息推送的Token(令牌)。

  • 經過調用XPush.getPlatformCode(),便可獲取當前使用推送平臺的碼。

二、推送的標籤(tag)處理

  • 經過調用XPush.addTags(),便可添加標籤(支持傳入多個)。

  • 經過調用XPush.deleteTags(),便可刪除標籤(支持傳入多個)。

  • 經過調用XPush.getTags(),便可獲取當前設備全部的標籤。

須要注意的是,友盟推送目前暫不支持標籤的獲取,華爲推送不支持標籤的全部操做,小米推送每次只支持一個標籤的操做。

三、推送的別名(alias)處理

  • 經過調用XPush.bindAlias(),便可綁定別名。

  • 經過調用XPush.unBindAlias(),便可解綁別名。

  • 經過調用XPush.getAlias(),便可獲取當前設備所綁定的別名。

須要注意的是,友盟推送目前暫不支持別名的獲取,華爲推送不支持別名的全部操做。

四、推送消息的接收

  • 經過調用XPushManager.get().register()方法,註冊消息訂閱MessageSubscriber,便可在任意地方接收到推送的消息。

  • 經過調用XPushManager.get().unregister()方法,便可取消消息的訂閱。

這裏須要注意的是,消息訂閱的回調並不必定是在主線程,所以在回調中若是進行了UI的操做,必定要確保切換至主線程。下面演示代碼中使用了個人另外一個開源庫XAOP,只經過@MainThread註解就能自動切換至主線程,可供參考。

/**
 * 初始化監聽
 */
@Override
protected void initListeners() {
    XPushManager.get().register(mMessageSubscriber);
}

private MessageSubscriber mMessageSubscriber = new MessageSubscriber() {
    @Override
    public void onMessageReceived(CustomMessage message) {
        showMessage(String.format("收到自定義消息:%s", message));
    }

    @Override
    public void onNotification(Notification notification) {
        showMessage(String.format("收到通知:%s", notification));
    }
};

@MainThread
private void showMessage(String msg) {
    tvContent.setText(msg);
}


@Override
public void onDestroyView() {
    XPushManager.get().unregister(mMessageSubscriber);
    super.onDestroyView();
}
複製代碼

五、推送消息的過濾處理

  • 經過調用XPushManager.get().addFilter()方法,可增長對訂閱推送消息的過濾處理。對於一些咱們不想處理的消息,能夠經過消息過濾器將它們篩選出來。

  • 經過調用XPushManager.get().removeFilter()方法,便可去除消息過濾器。

/**
 * 初始化監聽
 */
@Override
protected void initListeners() {
    XPushManager.get().addFilter(mMessageFilter);
}

private IMessageFilter mMessageFilter = new IMessageFilter() {
    @Override
    public boolean filter(Notification notification) {
        if (notification.getContent().contains("XPush")) {
            showMessage("通知被攔截");
            return true;
        }
        return false;
    }

    @Override
    public boolean filter(CustomMessage message) {
        if (message.getMsg().contains("XPush")) {
            showMessage("自定義消息被攔截");
            return true;
        }
        return false;
    }
};

@Override
public void onDestroyView() {
    XPushManager.get().removeFilter(mMessageFilter);
    super.onDestroyView();
}
複製代碼

六、推送通知的點擊處理

對於通知的點擊事件,咱們能夠處理得更優雅,自定義其點擊後的動做,打開咱們想讓用戶看到的頁面。

咱們能夠在全局消息推送的接收器IPushReceiver中的onNotificationClick回調中,增長打開指定頁面的操做。

@Override
public void onNotificationClick(Context context, XPushMsg msg) {
    super.onNotificationClick(context, msg);
    //打開自定義的Activity
    Intent intent = IntentUtils.getIntent(context, TestActivity.class, null, true);
    intent.putExtra(KEY_PARAM_STRING, msg.getContent());
    intent.putExtra(KEY_PARAM_INT, msg.getId());
    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    ActivityUtils.startActivity(intent);
}
複製代碼

須要注意的是,這須要你在消息推送平臺推送的通知使用的是自定義動做或者打開指定頁面類型,而且傳入的Intent uri 內容知足以下格式:

  • title:通知的標題

  • content:通知的內容

  • extraMsg:通知附帶的拓展字段,可存放json或其餘內容

  • keyValue:通知附帶的鍵值對

xpush://com.xuexiang.xpush/notification?title=這是一個通知&content=這是通知的內容&extraMsg=xxxxxxxxx&keyValue={"param1": "1111", "param2": "2222"}
複製代碼

固然你也能夠自定義傳入的Intent uri 格式,具體可參考項目中的XPushNotificationClickActivityAndroidManifest.xml


推送平臺說明

目前已支持的推送平臺

推送平臺 平臺名 平臺碼 模塊名 客戶端類
極光推送 JPush 1000 xpush-jpush com.xuexiang.xpush.jpush.JPushClient
友盟推送 UMengPush 1001 xpush-umeng com.xuexiang.xpush.umeng.UMengPushClient
華爲推送 HuaweiPush 1002 xpush-huawei com.xuexiang.xpush.huawei.HuaweiPushClient
小米推送 MIPush 1003 xpush-xiaomi com.xuexiang.xpush.xiaomi.XiaoMiPushClient

推送平臺的注意事項

極光推送平臺全部特性都支持。

友盟推送

  • 友盟推送在進行XPush初始化的時候,除了在主進程中註冊,還須要在channel中註冊。

  • 友盟推送不支持Tag和alias的獲取

  • 友盟推送不支持監聽推送的鏈接狀態。

華爲推送

  • 華爲推送在註冊以前須要安裝最新的推送服務,不然將沒法註冊成功(庫會自動彈出升級或者安裝提示)

  • 華爲推送不支持全部Tag和alias的操做。

  • 華爲推送不支持接收通知到達事件。

小米推送

  • 小米推送一次只能操做一個Tag。

  • 小米推送註銷無結果反饋。

  • 小米推送不支持監聽推送的鏈接狀態。

如何拓展第三方推送

因爲Android推送平臺的衆多,目前本項目不可能也不必提供全部推送平臺的集成庫。若是你想使用的推送平臺在我這沒有找到對應的集成庫的話,那麼就須要你本身寫一個了。

其實拓展一個第三方推送庫也不是很難,只要遵循如下4步驟就能夠完成了:

  • 1.新建一個Android Library Module,而後將你準備集成的推送平臺的依賴內容導入進來。這裏包括引入推送依賴庫或SDK、配置AndroidManifest.xml

  • 2.建立該推送平臺的客戶端XXXClient,實現IPushClient接口,而且重寫對應的方法。其中initregisterunRegistergetPlatformCodegetPlatformName這5個方法是必須重寫的。

IPushClient接口方法詳細以下:

public interface IPushClient {
    /**
     * 初始化【必須】
     *
     * @param context
     */
    void init(Context context);
    /**
     * 註冊推送【必須】
     */
    void register();
    /**
     * 註銷推送【必須】
     */
    void unRegister();
    /**
     * 綁定別名【別名是惟一的】
     *
     * @param alias 別名
     */
    void bindAlias(String alias);
    /**
     * 解綁別名
     *
     * @param alias 別名
     */
    void unBindAlias(String alias);
    /**
     * 獲取別名
     */
    void getAlias();
    /**
     * 增長標籤
     *
     * @param tag 標籤
     */
    void addTags(String... tag);
    /**
     * 刪除標籤
     *
     * @param tag 標籤
     */
    void deleteTags(String... tag);
    /**
     * 獲取標籤
     */
    void getTags();
    /**
     * @return 獲取推送令牌
     */
    String getPushToken();
    /**
     * 注意千萬不要重複【必須】
     * @return 獲取平臺碼
     */
    int getPlatformCode();
    /**
     * 注意千萬不要重複【必須】
     * @return 獲取平臺名
     */
    String getPlatformName();
}

複製代碼
  • 3.建立和重寫三方消息推送的消息接收器(通常是重寫Receiver)。重寫三方推送的的接收透傳消息和通知的方法,調用XPush的transmitXXX方法,將通知、透傳消息、通知點擊事件、以及其餘事件,轉發到XPush。

主要調用如下五個方法:

(1)XPush.transmitMessage(): 轉發自定義(透傳)消息.

(2)XPush.transmitNotification(): 轉發通知到達消息.

(3)XPush.transmitNotificationClick(): 轉發通知點擊事件.

(4)XPush.transmitCommandResult(): 轉發IPushClient命令執行結果.

(5)XPush.transmitConnectStatusChanged(): 轉發推送鏈接狀態發生改變的事件.

  • 4.增長該推送平臺對應的代碼混淆配置信息。

以上即完成了推送平臺的集成。剩下的就是在初始化XPush的時候對推送平臺進行選擇了.若是你看完了仍是不會的話,你能夠參考項目中的xpush-xiaomixpush-huawei.


實體介紹

XPushMsg

推送消息轉譯實體,攜帶消息的原始數據

字段名 類型 備註
mId int 消息ID / 狀態
mTitle String 通知標題
mContent String 通知內容
mMsg String 自定義(透傳)消息
mExtraMsg String 消息拓展字段
mKeyValue String 消息鍵值對

Notification

推送通知,由XPushMsg轉化而來

字段名 類型 備註
mId int 消息ID / 狀態
mTitle String 通知標題
mContent String 通知內容
mExtraMsg String 消息拓展字段
mKeyValue String 消息鍵值對

CustomMessage

自定義(透傳)消息,由XPushMsg轉化而來

字段名 類型 備註
mMsg String 自定義(透傳)消息
mExtraMsg String 消息拓展字段
mKeyValue String 消息鍵值對

XPushCommand

IPushClient執行相關命令的結果信息實體

字段名 類型 備註
mType int 命令類型
mResultCode int 結果碼
mContent String 命令內容
mExtraMsg String 拓展字段
mError String 錯誤信息

常量介紹

CommandType

命令的類型

命令名 命令碼 備註
TYPE_REGISTER 2000 註冊推送
TYPE_UNREGISTER 2001 註銷推送
TYPE_ADD_TAG 2002 添加標籤
TYPE_DEL_TAG 2003 刪除標籤
TYPE_GET_TAG 2004 獲取標籤
TYPE_BIND_ALIAS 2005 綁定別名
TYPE_UNBIND_ALIAS 2006 解綁別名
TYPE_GET_ALIAS 2007 獲取別名
TYPE_AND_OR_DEL_TAG 2008 添加或刪除標籤

ResultCode

命令的結果碼

結果名 結果碼 備註
RESULT_OK 0 成功
RESULT_ERROR 1 失敗

ConnectStatus

推送鏈接狀態

狀態名 狀態碼 備註
DISCONNECT 10 已斷開
CONNECTING 11 鏈接中
CONNECTED 12 已鏈接

混淆配置

# XPush的混淆
-keep class * extends com.xuexiang.xpush.core.IPushClient{*;}
-keep class * extends com.xuexiang.xpush.core.receiver.IPushReceiver{*;}

# 極光推送混淆
-dontwarn cn.jpush.**
-keep class cn.jpush.** { *; }
-dontwarn cn.jiguang.**
-keep class cn.jiguang.** { *; }
-keep class * extends cn.jpush.android.service.JPushMessageReceiver{*;}

# umeng推送
-dontwarn com.umeng.**
-dontwarn com.taobao.**
-dontwarn anet.channel.**
-dontwarn anetwork.channel.**
-dontwarn org.android.**
-dontwarn org.apache.thrift.**
-dontwarn com.xiaomi.**
-dontwarn com.huawei.**
-dontwarn com.meizu.**
-keep class com.taobao.** {*;}
-keep class org.android.** {*;}
-keep class anet.channel.** {*;}
-keep class com.xiaomi.** {*;}
-keep class com.huawei.** {*;}
-keep class com.meizu.** {*;}
-keep class org.apache.thrift.** {*;}
-keep class com.alibaba.sdk.android.**{*;}
-keep class com.ut.**{*;}
-keep class com.ta.**{*;}

# 華爲推送
-keep class com.huawei.hms.**{*;}
-keep class com.huawei.android.hms.agent.**{*;}

# 小米推送
-keep class * extends com.xiaomi.mipush.sdk.PushMessageReceiver{*;}

複製代碼

特別感謝

若是以爲項目還不錯,能夠考慮打賞一波

聯繫方式

相關文章
相關標籤/搜索