XPush

A lightweight, pluggable Android message push framework. One key integration push (Aurora push, Friends push, Huawei, Mi push, etc.), provide effective survival mechanism, support push expansion, fully decouple push and business logic, free your hands!

Before asking an issue, please read the wisdom of Asking and fill in the issue template strictly to save your time.

Before use, please read the instructions carefully and say the important things three times!!

Before use, please read the instructions carefully and say the important things three times!!

Before use, please read the instructions carefully and say the important things three times!!

About me


Characteristics of the

  • Easy integration. Push integration takes just a few lines of code, and there are already push channels such as Aurora and Umeng, which can be expanded according to your needs.

  • Strong compatibility. Android 9.0 is now fully supported.

  • Powerful. Support push related registration, deregistration, tag increase, delete, access, alias binding, unbinding, access, push connection status access and other operations, and can return the response results; Supports push notifications, notification click events, and custom messages.

  • Unified message subscription. The framework provides a unified channel for subscribing to and unsubscribing to push messages from anywhere, no matter what kind of push you use, making it easier to receive and process messages.

  • Support for adding message filters. Interceptors, like those in OkHttp, can filter the incoming messages globally, filtering out the push messages that we really need.

  • Provide effective survival mechanism. Ensure the arrival rate and stability of notifications for applications that are connected to XPush, which many push frameworks cannot do.

The structure

This framework draws on some ideas in OnePush (which is no longer maintained), together with my 3-year experience in news push, and forms the following parts:

  • IPushClient: provides apis for the message push platform.

  • Message push event forwarder IPushDispatcher: Used to forward third-party message push events to events that can be recognized by XPush.

  • Message push receiver IPushReceiver: receives events forwarded by the IPushDispatcher in a unified manner. It is the event receiving center.

  • IMessageObservable: Manages the subscription and forwarding of push messages.

  • Filtering policy for push messages IMessageFilterStrategy: Filters, processes, and manages push messages.

The above five components can be customized to suit your own business needs.

Message Push Process

After sending a push message in the background:

Third party push platform -- (message) --> third party push platform internal receiving message Receiver --> (rewrite its receiving method) --> IPushDispatcher --> (forward message content as XPushMsg/XPushCommand) --> IPushReceiver --> (if you do not use the message management provided by XPushManager, this is the end) : --IPushReceiver-- > XPushManager -----> IMessageFilterStrategy --> IMessageObservable --> (The message is forwarded to the specific subscribed place)Copy the code

Why did you do this project

As anyone who has done Android notifications knows, not only is Android fragmented, but there are a lot of different platforms. As early as 2017, the Ministry of Industry and Information Technology (MIIT) called on all manufacturers to develop a unified Android message push platform, but so far there has been no following (the reason is that the benefits are too big and no one wants to compromise).

However, we can not put all our hopes on this completely uncertain event, code will be written after all, and function will be on, rather than being controlled by others, it is better to revolution themselves, to build a message push platform solution that can be controlled by themselves.

One might say, “Why do you want to build your own integration when both UmENG and Carrier Pigeon support vendor push integration?” It doesn’t really matter if you don’t have a requirement for promptness and availability (which, in practice, doesn’t work). What I need to explain here is that it is impossible for you to put your fate in the hands of others. Unlike other businesses, push is relatively complex and requires a large number of event messages to be processed, which requires a large demand on the server. Are you willing to give your push messages to a third-party push platform for processing? Besides, can you force your backend to access a specific third-party push platform? If not, instead of being controlled by others, why not grasp these destiny in their own hands, then write out the function of their own peace of mind ah.

Before the QQ communication group has been someone hope I open source a message push framework, in fact, I wrote a push framework in the last company, but the bundle business is too deep, coupled with the suspicion of avoiding leaks, there is no need to open source. This push framework is a complete rewrite, with a new design, will make the framework more general, flexible.


Quick Integration Guide

Add Gradle dependencies

1. Add repositories for Build. Gradle

allprojects {
    repositories {
        ...
        maven { url "https://jitpack.io" }
    }
}
Copy the code

2. Add main dependencies for XPush:

dependencies { ... / / push core library implementation 'com. Making. Xuexiangjys. XPush: XPush - core: 1.0.0' / / push living library implementation 'com. Making. Xuexiangjys. XPush: keeplive: 1.0.0'}Copy the code

3. Add third-party push dependencies (add them according to your own needs, or all of them can be added)

dependencies { ... / / select what you want integration push library implementation 'com. Making. Xuexiangjys. XPush: XPush - jpush: 1.0.0' implementation 'com. Making. Xuexiangjys. XPush: XPush - umeng: 1.0.0' implementation 'com. Making. Xuexiangjys. XPush: XPush - huawei: 1.0.0' Implementation 'com. Making. Xuexiangjys. XPush: XPush - xiaomi: 1.0.0'}Copy the code

Initialize the XPush configuration

1. Register for the notification push receiver. There are two ways to do it. Just pick one.

  • If you want to use the message management provided by XPushManager, register the XPushReceiver provided by the framework default directly in AndroidManifest.xml. Of course, you can also inherit XPushReceiver and override the related methods.

  • If you want to implement your own message management, you can inherit AbstractPushReceiver class, override the methods in it, and register it in 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> <! - the default message to push the receiver - > < receiver android: name = "com. Xuexiang. Xpush. Core. The receiver. The 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>Copy the code

Note that if your Android device is 8.0 or above, static registered broadcasts will not work properly. There are two ways to resolve this:

  • Dynamically register notification push receivers

  • Modify the emitter of the push message

If (build.version.sdk_int >= build.version_codes.o) {//Android8.0 static broadcast registration failed solution 1: Dynamic registration XPush. RegisterPushReceiver (new CustomPushReceiver ()); / / Android8.0 static radio registration failure solution 2: modify the launcher XPush. SetIPushDispatcher (new Android26PushDispatcherImpl (CustomPushReceiver. Class)); }Copy the code

2. Under the Application tag of AndroidManifest.xml, add the third party push client implementation class.

Note that the PlatformName and PlatformCode registered here must correspond to those in the push client implementation class.

<! XPush_[PlatformName]_[PlatformCode]--> <! --value format: path to the full class name of the corresponding client entity class --> <! - if introduced xpush - jpush library - > < meta - data android: name = "XPush_JPush_1000" android: value = "com. Xuexiang. Xpush. Jpush. JPushClient" / > <! <meta-data android:name="XPush_UMengPush_1001" android:value="com.xuexiang.xpush.umeng.UMengPushClient" /> <! <meta-data android:name="XPush_HuaweiPush_1002" android:value="com.xuexiang.xpush.huawei.HuaweiPushClient" /> <! <meta-data android:name="XPush_MIPush_1003" > <meta-data android:name="XPush_MIPush_1003" android:value="com.xuexiang.xpush.xiaomi.XiaoMiPushClient" />Copy the code

3. Add third-party AppKey and AppSecret.

AppKey and AppSecret need to be obtained by registering the application on the respective push platform. Note that if xpush-Xiaomi is used, then you need to add Xiaomi’s AppKey and AppSecret to AndroidManifest. XML (note that the ‘\’ below must be added, otherwise you will get float instead of String, The id and key will not get the correct data.

<! <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" /> <! Static registration, huawei HMS push - > < meta - data android: name = "com. Huawei. HMS. Client. Appid" android: value = "101049475" / > <! -- Mi push static registration, the following "\" must be added, <meta-data android:name="MIPUSH_APPID" android:value="\ 2882303761518134164"/> <meta-data android:name="MIPUSH_APPKEY" android:value="\ 5371813415164"/>Copy the code

4. Initialize XPush in Application

There are two ways to initialize XPush. Select one method according to business needs.

  • Static registration
/** * Static registration initialpush */ private void initPush() {xpush.debug (buildconfig.debug); Xpush. init(this, new UMengPushClient()); XPush.register(); }Copy the code
  • Dynamic registration
/ / private void initPush() {xpush.debug (buildconfig.debug); // Dynamic registration, 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(); }Copy the code

How to use XPush

1. Push registration and deregistration

  • Push registration is completed by calling xpush.register ().

  • The push is logged out by calling xpush.unregister ().

  • By calling xpush.getPushToken (), you get the Token(Token) for the message push.

  • By calling xpush.getPlatformCode (), you get the code that is currently using the push platform.

2. Processing of pushed tags

  • You can addTags(passing multiple tags is supported) by calling xpush.addtags ().

  • By calling xpush.deletetags (), you can deleteTags(passing multiple tags is supported).

  • Get all the tags for the current device by calling xpush.gettags ().

It should be noted that Au push currently does not support the acquisition of labels, Huawei push does not support all the operations of labels, Xiaomi push only supports one label operation at a time.

3, push alias processing

  • The alias is bound by calling xpush.bindalias ().

  • The alias is unbound by calling xpush.unbindAlias ().

  • Get the alias to which the current device is bound by calling xpush.getalias ().

Note that UmENG Push currently does not support obtaining aliases, and Huawei Push does not support all operations on aliases.

4. Receiving push messages

  • You can receive push messages anywhere by calling the xpushManager.get ().register() method and registering for a message subscription to MessageSubscriber.

  • You can unsubscribe the message by calling the xpushManager.get ().unregister() method.

It is important to note here that the callback to the message subscription is not necessarily on the main thread, so make sure to switch to the main thread if there is any UI action in the callback. For reference, the following demo code uses XAOP, another of my open source libraries, to automatically switch to the MainThread using the @mainthread annotation alone.

/** * Initialize listeners */ @override protected void listeners () {xpushManager.get ().register(mMessageSubscriber); } private MessageSubscriber mMessageSubscriber = new MessageSubscriber() { @Override public void OnMessageReceived (CustomMessage message) {showMessage(string.format (" received CustomMessage :%s", message)); } @override public void onNotification(Notification Notification) {showMessage(String. Format (" received Notification :%s"), notification)); }}; @MainThread private void showMessage(String msg) { tvContent.setText(msg); } @Override public void onDestroyView() { XPushManager.get().unregister(mMessageSubscriber); super.onDestroyView(); }Copy the code

5. Filtering processing of push messages

  • The filtering processing of subscription push messages can be added by calling the xpushManager.get ().addfilter () method. For messages we don’t want to process, we can filter them through message filters.

  • The message filter is removed by calling the xpushManager.get ().removeFilter() method.

*/ @override protected void listeners () {xpushManager.get ().addFilter(mMessageFilter); } private IMessageFilter mMessageFilter = new IMessageFilter() { @Override public boolean filter(Notification Notification) {if (notification.getContent().contains("XPush")) {showMessage(" notification was intercepted "); return true; } return false; } @Override public boolean filter(CustomMessage message) { if (message.getMsg().contains("XPush")) { ShowMessage (" custom message intercepted "); return true; } return false; }}; @Override public void onDestroyView() { XPushManager.get().removeFilter(mMessageFilter); super.onDestroyView(); }Copy the code

6. Click processing of push notifications

We can be more elegant with notifications of click events, customizing their actions after a click and opening the page we want the user to see.

We can add the operation of opening the specified page to the onNotificationClick callback in the IPushReceiver for the global message push.

@Override public void onNotificationClick(Context context, XPushMsg msg) { super.onNotificationClick(context, msg); 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); }Copy the code

Note that this requires you to push notifications from the messaging platform using a custom action or open a specified page type, and pass in Intent URI content in the following format:

  • Title: Indicates the title of the notification

  • Content: Indicates the content of the notification

  • ExtraMsg: An extended field attached to notifications that can hold JSON or other content

  • KeyValue: The key-value pair attached to the notification

xpush://com.xuexiang.xpush/notification? Title = this is a notification &content= this is the content of the notification &extramsg =xxxxxxxxx&keyValue={"param1": "1111", "param2": "2222"}Copy the code

Of course you can also customize the incoming Intent uri format, concrete can be reference in the project XPushNotificationClickActivity and AndroidManifest. XML


Platform Push

Currently supported push platforms

Push platform The platform of The platform code Module name The client class
The aurora push JPush 1000 xpush-jpush com.xuexiang.xpush.jpush.JPushClient
Their Allies to push UMengPush 1001 xpush-umeng com.xuexiang.xpush.umeng.UMengPushClient
Huawei’s push HuaweiPush 1002 xpush-huawei com.xuexiang.xpush.huawei.HuaweiPushClient
Millet push MIPush 1003 xpush-xiaomi com.xuexiang.xpush.xiaomi.XiaoMiPushClient

Push platform considerations

All features of aurora Push platform are supported.

Their Allies to push

  • In addition to being registered in the main process, the alliance push needs to be registered in the channel when XPush is initialized.

  • Amun push does not support the acquisition of Tag and alias

  • Umeng Push does not support monitoring the pushed connection status.

Huawei’s push

  • Huawei push needs to install the latest push service before registration. Otherwise, the registration fails (library upgrade or installation prompt is automatically displayed).

  • Huawei push does not support all Tag and alias operations.

  • Huawei push does not support notification arrival events.

Millet push

  • Xiaomi push can only operate one Tag at a time.

  • No result feedback from xiaomi push for logout.

  • Mi Push does not support monitoring the connection status of the push.

How to expand third-party push

Due to the large number of Android push platforms, it is not possible or necessary for this project to provide integration libraries for all push platforms. If I don’t have an integration library for the push platform you want to use, you’ll need to write your own.

In fact, expanding a third-party push library is not very difficult, as long as you follow the following 4 steps to complete:

  • 1. Create a new Android Library Module and import the dependencies of the push platform you are going to integrate with. This includes introducing a push dependency library or SDK and configuring AndroidManifest.xml.

  • 2. Create the client XXXClient of the push platform, implement the IPushClient interface, and rewrite the corresponding methods. Init, register, unRegister, getPlatformCode and getPlatformName must be overridden.

The IPushClient interface methods are as follows:

Public interface IPushClient {/** * initialize the IPushClient. ** @param context */ void init(context context); Void register(); / / void register(); Void unRegister(); /** * unRegister(); ** @param alias */ void bindAlias(String alias); /** * unBindAlias ** @param alias */ void unBindAlias(String alias); /** * Get the alias */ void getAlias(); /** * @param tag */ void addTags(String... tag); /** * @param tag */ void deleteTags(String... tag); /** * get tag */ void getTags(); /** * @return getPushToken */ String getPushToken(); /** * do not repeat [must] * @return getPlatformCode */ int getPlatformCode(); /** * do not repeat [must] * @return getPlatformName */ String getPlatformName(); }Copy the code
  • 3. Create and rewrite a message Receiver (usually a rewrite Receiver) for the three-party message push. Override the three-party push to receive transparent messages and notifications method, callXPushThe transmitXXX method of transmitXXX forwards notifications, transparent messages, notification click events, and other events to XPush.

The following five methods are invoked:

(1) xpush. transmitMessage(): forwards custom (transparent) messages.

(2) XPush. TransmitNotification () : message forwarding notice arrived.

(3) XPush. TransmitNotificationClick () : click event forwarding notice.

(4) XPush. TransmitCommandResult () : forward IPushClient command execution results.

(5) XPush. TransmitConnectStatusChanged () : forward push connection state change events.

  • 4. Add code obfuscation configuration information corresponding to the push platform.

This completes the integration of the push platform. All that remains is to select the platform to push when you initialize XPush. If you still can’t, you can refer to xpush-Xiaomi and Xpush-Huawei in the project.


The entity is introduced

XPushMsg

Push message translation entity that carries the raw data of the message

The field name type note
mId int Message ID/status
mTitle String Notice the title
mContent String Inform the content
mMsg String Custom (transparently transmitted) messages
mExtraMsg String Message extension field
mKeyValue String Message key-value pairs

Notification

Push notifications, converted from XPushMsg

The field name type note
mId int Message ID/status
mTitle String Notice the title
mContent String Inform the content
mExtraMsg String Message extension field
mKeyValue String Message key-value pairs

CustomMessage

Custom (pass-through) messages, converted from XPushMsg

The field name type note
mMsg String Custom (transparently transmitted) messages
mExtraMsg String Message extension field
mKeyValue String Message key-value pairs

XPushCommand

IPushClient Indicates the result of executing commands

The field name type note
mType int Type the command
mResultCode int The result code
mContent String Command content
mExtraMsg String Expand the fields
mError String The error message

Constant introduction

CommandType

Type of command

The command name The command code note
TYPE_REGISTER 2000 Registered push
TYPE_UNREGISTER 2001 The cancellation of push
TYPE_ADD_TAG 2002 Add tags
TYPE_DEL_TAG 2003 Remove the label
TYPE_GET_TAG 2004 The label
TYPE_BIND_ALIAS 2005 Binding the alias
TYPE_UNBIND_ALIAS 2006 Unbundling alias
TYPE_GET_ALIAS 2007 To obtain an alias
TYPE_AND_OR_DEL_TAG 2008 Add or delete labels

ResultCode

Result code of a command

The results of The result code note
RESULT_OK 0 successful
RESULT_ERROR 1 failure

ConnectStatus

Push Connection Status

The state name Status code note
DISCONNECT 10 Has been disconnected
CONNECTING 11 In the connection
CONNECTED 12 The connected

Confuse configuration

# XPush confusion - keep class * extends com. Xuexiang. XPush. Core. IPushClient {*; } -keep class * extends com.xuexiang.xpush.core.receiver.IPushReceiver{*; ** -keep class cn.jpush.** {*; } -dontwarn cn.jiguang.** -keep class cn.jiguang.** { *; } -keep class * extends cn.jpush.android.service.JPushMessageReceiver{*; } # umeng push -dontwarn com.umeng.** -dontwarn com.taobao.** -dontwarn anet.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.**{*; } # millet push - keep class * extends com. Xiaomi. Mipush. SDK. PushMessageReceiver {*; }Copy the code

Special thanks to

  • OnePush
  • keeplive

Wechat official account

For more information, please search wechat official account: “My Android Open Source Journey”