小米集成指南
1、使用JCenter自动化集成步骤
确认AndroidStudio的Project根目录的主gradle中配置了jcenter支持。(新建project默认配置就支持)
buildscript { repositories { jcenter() } } allprojects { repositories { jcenter() } }
在应用module的gradle中dependencies节点添加如下代码
dependencies{ implementation 'cn.jiguang.sdk.plugin:xiaomi:3.8.5' // JPushSDK3.8.5为例(厂商版本和jpush SDK版本保持一致,如果需要升级jpush SDK版本,注意厂商SDK版本的升级) }
在应⽤module的gradle中defaultConfig节点添加如下代码(不要遗漏前缀MI-):
manifestPlaceholders=[ JPUSH_PKGNAME:"您应用的包名", XIAOMI_APPKEY:"MI-您的应用对应的小米的APPKEY",//小米平台注册的appkey XIAOMI_APPID:"MI-您的应用对应的小米的APPID",//小米平台注册的appid ]
由于 MiPush 的 regid 只能在主进程获取,非主进程获取到的regid为空,所以极光的 PushReceiver应寄宿于应用主进程, 需要在AndroidManifest.xml中将 PushReceiver 的分离进程配置去掉。配置示例如下:
<receiver android:name="cn.jpush.android.service.PushReceiver" tools:node="replace" android:enabled="true"> <intent-filter android:priority="1000"> <action android:name="cn.jpush.android.intent.NOTIFICATION_RECEIVED_PROXY" /> <!--Required 显示通知栏 --> <category android:name="${applicationId}" /> </intent-filter> <intent-filter> <action android:name="android.intent.action.USER_PRESENT" /> <action android:name="android.net.conn.CONNECTIVITY_CHANGE" /> </intent-filter> <!-- Optional --> <intent-filter> <action android:name="android.intent.action.PACKAGE_ADDED" /> <action android:name="android.intent.action.PACKAGE_REMOVED" /> <data android:scheme="package" /> </intent-filter> </receiver>
2、配置AndroidManifest.xml集成步骤
注意:(JCenter自动化集成与配置AndroidManifest.xml集成二者选择一种即可,如果您完成以上步骤,您可以跳过本段)
手动集成主要步骤为:
- 1. 增加小米插件包及小米推送包
- 2. 配置小米推送sdk所需要的权限
- 3. 配置小米必须的组件
- 4. 配置JPush接受的小米sdk的消息接受类
- 5. 将XIAOMI_APPKEY与XIAOMI_APPID替换为在小米后台注册对应该应用的AppKey/AppID
(1)导入极光的插件包以及小米推送sdk的jar,将极光提供的libs包中的jpush-android-plugin-xiaomi-v3.x.x.jar(插件包)及MiPush_SDK_Client_x_x_x.jar(小米推送包)导入到工程libs/目录下。
注1:极光集成小米通道在 JPush Android SDK 3.0.3 添加,对应测试的小米 SDK 版本为:3.2.2
注2:极光集成小米SDK在 JPush Android SDK 3.2.0 有升级,对应测试的小米 SDK 版本为:3.6.12
注2:极光集成小米SDK在 JPush Android SDK 3.3.2 有升级,对应测试的小米 SDK 版本为:3.6.18
注3:极光集成小米SDK在 JPush Android SDK 3.6.0 有升级,对应测试的小米 SDK 版本为:3.7.5
(2)配置小米推送sdk所需要的权限
<permission android:name="您应用的包名.permission.MIPUSH_RECEIVE" android:protectionLevel="signature" /> <uses-permission android:name="您应用的包名.permission.MIPUSH_RECEIVE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.GET_TASKS" /> <uses-permission android:name="android.permission.VIBRATE" />
(3)配置小米必须的组件
<service android:name="com.xiaomi.push.service.XMJobService" android:enabled="true" android:exported="false" android:permission="android.permission.BIND_JOB_SERVICE" android:process=":pushservice" /> <service android:name="com.xiaomi.push.service.XMPushService" android:enabled="true" android:process=":pushservice" /> <service android:name="com.xiaomi.mipush.sdk.PushMessageHandler" android:enabled="true" android:exported="true" /> <service android:name="com.xiaomi.mipush.sdk.MessageHandleService" android:enabled="true" /> <receiver android:name="com.xiaomi.push.service.receivers.NetworkStatusReceiver" android:exported="true"> <intent-filter> <action android:name="android.net.conn.CONNECTIVITY_CHANGE" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </receiver> <receiver android:name="com.xiaomi.push.service.receivers.PingReceiver" android:exported="false" android:process=":pushservice"> <intent-filter> <action android:name="com.xiaomi.push.PING_TIMER" /> </intent-filter> </receiver>
注:请不要将极光的组件PushReceiver配置进程和主进程分离。(按照示例默认配置即可)否则会影响小米RegId的获取
(4)配置JPush接受的小米sdk的消息接受类
<receiver android:name="cn.jpush.android.service.PluginXiaomiPlatformsReceiver" android:exported="true"> <intent-filter> <action android:name="com.xiaomi.mipush.RECEIVE_MESSAGE" /> </intent-filter> <intent-filter> <action android:name="com.xiaomi.mipush.MESSAGE_ARRIVED" /> </intent-filter> <intent-filter> <action android:name="com.xiaomi.mipush.ERROR" /> </intent-filter> </receiver>
(5)将APPKEY与APPID替换为在小米后台注册对应该应用的AppKey/AppID(不要遗漏前缀MI-)
<meta-data android:name="XIAOMI_APPKEY" android:value="MI-您的应用对应的小米的appkey"/> <meta-data android:name="XIAOMI_APPID" android:value="MI-您的应用对应小米的appID"/>
(6)对于同一个应用集成了多个推送SDK,且其他SDK也使用了小米通道的用户:
可以将这个极光内置的Receiver,换成自己定义的Receiver。
这个Receiver必须继承小米的com.xiaomi.mipush.sdk.PushMessageReceiver
且在每个回调方法,都回调给极光的PluginXiaomiPlatformsReceiver。类似于这样:
public class XMPushReceiver extends PushMessageReceiver { final PluginXiaomiPlatformsReceiver receiver = new PluginXiaomiPlatformsReceiver(); @Override public void onReceivePassThroughMessage(final Context context, final MiPushMessage message) { receiver.onReceivePassThroughMessage(context, message); } @Override public void onNotificationMessageClicked(Context context, MiPushMessage message) { receiver.onNotificationMessageClicked(context, message); } @Override public void onNotificationMessageArrived(Context context, MiPushMessage message) { receiver.onNotificationMessageArrived(context, message); } @Override public void onCommandResult(Context context, MiPushCommandMessage message) { receiver.onCommandResult(context, message); } @Override public void onReceiveRegisterResult(Context context, MiPushCommandMessage message) { receiver.onReceiveRegisterResult(context, message); } }
3、小米SDK的编译混淆问题
如果使用了proguard,需要在配置文件中加入,可以防止一个误报的warning导致无法成功编译:
-dontwarn com.xiaomi.push.** -keep class com.xiaomi.push.**{*;}
4、点击通知跳转到指定Activity(小米,华为,vivo均适用)
说明
小米/华为/vivo的push允许开发者在推送通知的时候传入自定义的intenturi字符串,当用户点击了该通知,系统会根据uri的值过滤出匹配的Activity,并打开Activity,达到跳转的目的。
注1:华为此功能从JPushAndroidSDK3.0.9开始支持;小米和vivo从JPushAndroidSDK3.3.8开始支持
注2:此功能需要服务器端与Android端联合修改与调试。
服务端使用方式
在pushapi的payload中的"notification"的"android"节点下添加以下字段:
关键字 |
类型 |
实例 |
说明 |
uri_activity |
String |
"com.HuananThirdPush.cn.OpenClickActivity" |
该字段用于指定开发者想要打开的activity,值为activity节 点的"android:name"属性值。 |
示例代码:
{ "platform": [ "android" ], "audience": "all", "notification": { "android": { "alert": "在线alert003", "title": "在线title003", "uri_activity": "com.HuananThirdPush.cn.OpenClickActivity" } }, "message": { "msg_content": "自定义消息内容003" } }
极光提供服务端JAVASDK,下载地址GitHub - jpush/jpush-api-java-client: JiGuang's officially supported Java client library for accessing JPush APIs. 极光官方支持的 Java 版本服务器端 SDK。,内含有example样例。可以拉取最新的代码自行打包,也可以直接使用libs文件夹下的jar。
示例代码如下:
注: addCustom("uri_activity","xxx")方法传递的参数在非华为/VIVO/小米机型上做无效处理;addCustom("uri_action","xxx")方法传递的参数在非OPPO/FCM机型上做无效处理
public static PushPayload buildPushObject_CustomField() { Notification notification = Notification.newBuilder() .addPlatformNotification(AndroidNotification.newBuilder() .setAlert(ALERT) .setTitle("Alert test") .setLargeIcon("http://www.jiguang.cn/largeIcon.jpg") .addCustom("uri_activity", "com.HuananThirdPush.cn.OpenClickActivity") .addCustom("uri_flag", "uri_flag") .addCustom("uri_action", "com.HuananThirdPush.cn.OpenClickActivity") .build()) .build(); PushPayload.Builder payloadBuilder = new PushPayload.Builder() .setPlatform(Platform.all()) .setAudience(Audience.all()) .setNotification(notification); return payloadBuilder.build(); }
Android端配置步骤
(1)AndroidManifest.xml中配置点击通知要打开的Activity
<activity android:name="您配置的activity" android:exported="true"> <intent-filter> <action android:name="android.intent.action.VIEW"/> <category android:name="android.intent.category.DEFAULT"/> </intent-filter> </activity>
注:android:exported属性必须设置为true,并增加示例中的intent-filter,否则会导致无法收到通知。
(2)获取通知相关信息
目前启动配置的activity都是使用Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK方式启动,只需要在您配置的activity中的onCreate方法中进行处理,获取通知信息。华为通过getIntent().getData(),小米/vivo/OPPO/FCM通过 getIntent().getExtras().getString("JMessageExtra")取到Intent的数据。获取到的数据是JSON字符串,通过解析可以获得通知相关内容。
JSON示例如下:
{ "msg_id": "123456", "n_content": "thisiscontent", "n_extras": { "key1": "value1", "key2": "value2" }, "n_title": "thisistitle", "rom_type": 0 }
JSON内容字段说明:
字段 |
取值类型 |
描述 |
msg_id |
String |
通过此key获取到通知的msgid |
n_title |
String |
通过此key获取到通知标题 |
n_content |
String |
通过此key获取到通知内容 |
n_extras |
String |
通过此key获取到通知附加字段 |
rom_type |
byte |
通过此key获取到下发通知的平台。得到值说明:byte类型的整数, 0为极光,1为小米,2为华为,3为魅族,4为oppo,5为vivo,8为FCM。 |
注:rom_type用于点击事件的上报,一般情况下开发者只需要取到该字段的值用于上报,不需要关心具体取值
通知点击上报
解析通知内容后,需主动调用接口来进行通知点击上报,上报接口如下
/** * context 上下文 * msgId 消息ID * whichPushSDK 收到推送的平台,即 rom_type 字段的取值。 **/ JPushInterface.reportNotificationOpened(Context context, String msgId, byte whichPushSDK);
注:点击上报必须传入正确的whichPushSDK参数,否则会造成统计数据错误。
富媒体调整
在AndroidManifest.xml中将PushActivity、PopWinActivity的android:exported="false"属性修改为true,否则会导致收不到富媒体推送。
Activity示例代码(华为/小米/OPPO/vivo/FCM厂商均适用,魅族与基础的走极光通道的通知获取方法一致)
package com.HuananThirdPush.cn; import android.app.Activity; import android.os.Bundle; import android.text.TextUtils; import android.util.Log; import android.widget.TextView; import org.json.JSONException; import org.json.JSONObject; import cn.jpush.android.api.JPushInterface; public class OpenClickActivity extends Activity { private static final String TAG = "OpenClickActivity"; /**消息Id**/ private static final String KEY_MSGID = "msg_id"; /**该通知的下发通道**/ private static final String KEY_WHICH_PUSH_SDK = "rom_type"; /**通知标题**/ private static final String KEY_TITLE = "n_title"; /**通知内容**/ private static final String KEY_CONTENT = "n_content"; /**通知附加字段**/ private static final String KEY_EXTRAS = "n_extras"; private TextView mTextView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mTextView = new TextView(this); setContentView(mTextView); handleOpenClick(); } /** * 处理点击事件,当前启动配置的Activity都是使用 * Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK * 方式启动,只需要在onCreat中调用此方法进行处理 */ private void handleOpenClick() { Log.d(TAG, "用户点击打开了通知"); String data = null; //获取华为平台附带的jpush信息 if (getIntent().getData() != null) { data = getIntent().getData().toString(); } //获取fcm/oppo/小米/vivo 平台附带的jpush信息 if (TextUtils.isEmpty(data) && getIntent().getExtras() != null) { data = getIntent().getExtras().getString("JMessageExtra"); } Log.w(TAG, "msg content is " + String.valueOf(data)); if (TextUtils.isEmpty(data)) return; try { JSONObject jsonObject = new JSONObject(data); String msgId = jsonObject.optString(KEY_MSGID); byte whichPushSDK = (byte) jsonObject.optInt(KEY_WHICH_PUSH_SDK); String title = jsonObject.optString(KEY_TITLE); String content = jsonObject.optString(KEY_CONTENT