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{*;}

复制代码

特别感谢

若是以为项目还不错,能够考虑打赏一波

联系方式

相关文章
相关标签/搜索