JPush SDK 華為通道集成指南
概述
在國內(nèi) Android 生態(tài)中超棺,推送通道都是由終端與云端之間的長鏈接來維持,嚴(yán)重依賴于應(yīng)用進(jìn)程的存活狀態(tài)呵燕。如今一些手機(jī)廠家會(huì)在自家 rom 中做系統(tǒng)級(jí)別的推送通道棠绘,再由系統(tǒng)分發(fā)給各個(gè) app,以此提高在自家 rom 上的推送送達(dá)率再扭。
JPush SDK 為了盡可能提高開發(fā)者在各類 rom 上的推送送達(dá)率氧苍,對(duì)使用 EMUI 的設(shè)備推送,自動(dòng)切換到華為通道泛范。同時(shí)让虐,為了保證 SDK 的易用性,原本 JPush 的所有接口調(diào)用邏輯都不用修改,JPush 會(huì)對(duì)自身支持的功能做兼容.只需在manifest中配置上華為HMS SDK 必須的配置組件即可.
功能描述
JPush 初始化的時(shí)候可選擇是否初始化 HMS Push 通道罢荡。
在 EMUI 設(shè)備上 JPush 通道與 華為 通道共存.
華為 通道初始化后支持 tag/alias這些 JPush 原有的功能,其它的 JPush 未支持的功能目前暫時(shí)還不可用.
增加兼容華為HMS SDK初始化失敗處理錯(cuò)誤的接口.
注:極光根據(jù) EMUI 系統(tǒng)版本間差異赡突,現(xiàn)采取的方案是 EMUI 4.1 及以上版本对扶,使用 HMS 服務(wù),通知走 HMS 通道惭缰;對(duì)于 EMUI 4.1 以下版本還是走極光通道浪南。
配置集成步驟
主要步驟為:
<h3 id="1">添加 Huawei SDK 到項(xiàng)目中</h3>
-
拷貝third-push/huawei/libs中的插件包(jpush-android-plugin-huawei-v3.x.x.jar)到工程libs目錄下
- 注意:也可使用jcenter集成方式,無需拷貝jpush-android-plugin-huawei-v3.x.x.jar文件漱受,也無需配置cn.jpush.android.service.PluginHuaweiPlatformsService組件
- 示例:implementation 'cn.jiguang.sdk.plugin:huawei:3.x.x'
在 Huawei 上創(chuàng)建和 JPush 上同包名的待發(fā)布應(yīng)用,創(chuàng)建完成后下載該應(yīng)用的 agconnect-services.json 配置文件并添加到應(yīng)用的 module 目錄下络凿。
在根級(jí) build.gradle 中添加規(guī)則,以納入 HMS 服務(wù)插件 和 華為 的 Maven 代碼庫,可根據(jù)華為開發(fā)者聯(lián)盟發(fā)布的版本更新選擇最新版本:
ldscript {
repositories {
google()
jcenter()
maven {url 'http://developer.huawei.com/repo/'}
}
}
buildscript {
dependencies {
classpath 'com.huawei.agconnect:agcp:1.0.0.300'
}
}
allprojects {
repositories {
google()
jcenter()
maven {url 'http://developer.huawei.com/repo/'}
}
}
- 在應(yīng)用 module 的 build.gradle 文件底部添加 apply plugin 代碼行絮记,以啟用 gradle 插件:
// ADD THIS AT THE TOP
apply plugin: 'com.huawei.agconnect'
- 在應(yīng)用 module 的 gradle 中 dependencies 節(jié)點(diǎn)添加如下代碼到千,可根據(jù) 華為 發(fā)布的版本更新選擇最新版本:
dependencies {
implementation 'com.huawei.hms:push:3.0.3.301'
//引入極光-華為插件憔四,如果采用此配置了赵,無需拷貝jpush-android-plugin-huawei-v3.x.x.jar文件甸赃,也無需配置cn.jpush.android.service.PluginHuaweiPlatformsService組件
implementation 'cn.jiguang.sdk.plugin:huawei:3.x.x'
}
注1:極光集成華為通道在 JPush Android SDK 3.0.5 添加埠对,對(duì)應(yīng)測(cè)試的華為HMS SDK 版本為:HMS-SDK-2.4.0.300.aar
注2:JPush Android SDK 3.0.9 適配HMS SDK的升級(jí),對(duì)應(yīng)測(cè)試的華為HMS SDK 版本為:HMSSdk-base-2.5.2.300.aar,HMSSdk-push-2.5.2.300.aar
注3:JPush Android SDK 3.1.2 適配HMS SDK的升級(jí),對(duì)應(yīng)測(cè)試的華為HMS SDK 版本為:HMSSdk-base-2.5.3.302.aar,HMSSdk-push-2.5.3.302.aar
注4:從HMS_SDK_2.6.0.301版本開始支持jar包+res資源集成貌笨,JPush Android SDK 3.1.5對(duì)應(yīng)測(cè)試的華為HMS SDK 版本為:HMS_SDK_2.6.0.301.jar
注5:JPush Android SDK 3.2.0 更新華為HMS SDK版本為:hmssdk_2.6.3.301.jar
注6:JPush Android SDK 3.3.6 更新華為HMS SDK版本為:hmssdk_2.6.3.306.jar
注7:JPush Android SDK 3.5.4 更新華為HMS SDK版本為:3.0.3.301
<h3 id="2">2. 配置接收 HMS 消息的服務(wù)</h3>
<service
android:name="cn.jpush.android.service.PluginHuaweiPlatformsService"
android:exported="false">
<intent-filter>
<action android:name="com.huawei.push.action.MESSAGING_EVENT" />
</intent-filter>
</service
<h3 id="3">3. 在build.gradle中配置在華為后臺(tái)添加的指紋證書對(duì)應(yīng)的簽名</h3>
注:HMS 服務(wù)必須要求 app 簽名才能注冊(cè)成功锥惋。指紋證書是在終端采用keytool -list -v -keystore keystorefileName 獲取偶對(duì)應(yīng)的指紋證書.
signingConfigs {
release {
storeFile file("release.keystore")//簽名文件的path
storePassword "123456"
keyAlias "android.keystore"
keyPassword "123456"
}
}
buildTypes {
release {
minifyEnabled true
proguardFiles 'proguard-rules.pro'
signingConfig signingConfigs.release
}
debug{
minifyEnabled false
signingConfig signingConfigs.release
}
}
HMS SDK的編譯混淆問題
如果使用了 proguard膀跌,需要在配置文件中加入,可以防止一個(gè)誤報(bào)的 warning 導(dǎo)致無法成功編譯捅伤,
-ignorewarning
-keepattributes *Annotation*
-keepattributes Exceptions
-keepattributes InnerClasses
-keepattributes Signature
-keepattributes SourceFile,LineNumberTable
-keep class com.hianalytics.android.**{*;}
-keep class com.huawei.updatesdk.**{*;}
-keep class com.huawei.hms.**{*;}
點(diǎn)擊通知跳轉(zhuǎn) Activity
功能說明
支持的版本
此功能從 JPush Android SDK 3.0.9 開始支持
華為手機(jī)通知跳轉(zhuǎn)的定義
華為 push 允許開發(fā)者在推送通知的時(shí)候傳入自定義的 intent uri 字符串丛忆,當(dāng)用戶點(diǎn)擊了該通知蘸际,系統(tǒng)會(huì)根據(jù) uri 的值過濾出匹配的 Activity 粮彤,并打開 Activity导坟,達(dá)到跳轉(zhuǎn)的目的惫周。
使用方式
Push API 推送說明
在 push api 的 payload 中的 "notification" 的 "android" 節(jié)點(diǎn)下添加以下字段:
<div class="table-d" align="center" >
<table border="1" width = "100%">
<tr bgcolor="#D3D3D3" >
<th >關(guān)鍵字</th>
<th >類型</th>
<th >示例</th>
<th >說明</th>
</tr>
<tr >
<td>uri_activity</td>
<td>string</td>
<td>"com.example.jpushdemo.OpenClickActivity"</td>
<td>該字段用于指定開發(fā)者想要打開的 activity递递,值為activity 節(jié)點(diǎn)的 “android:name ” 屬性值登舞。</td>
</tr>
</table>
</div>
示例:
demo manifest配置:
<activity android:name="com.example.jpushdemo.OpenClickActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
請(qǐng)求json如下:
{
"platform": [
"android"
],
"audience": "all",
"notification": {
"android": {
"alert": "在線alert003",
"title": "在線title003",
"uri_activity": "com.example.jpushdemo.OpenClickActivity",
}
},
"message": {
"msg_content": "自定義消息內(nèi)容003"
}
}
SDK 端配置
1.AndroidManifest.xml中配置點(diǎn)擊通知要打開的 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 屬性必須設(shè)置為 true,并增加示例中的 intent-filter氯迂,否則會(huì)導(dǎo)致無法收到通知。
2.獲取通知相關(guān)信息
目前啟動(dòng)配置的 activity 都是使用 Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK 方式啟動(dòng)匾二,只需要在您配置的 activity 中的onCreate方法中進(jìn)行處理察藐,獲取通知信息分飞。
通過 getIntent().getData() 獲取到Intent 數(shù)據(jù)睹限。獲取到的數(shù)據(jù)是 JSON 字符串,通過解析可以獲得通知相關(guān)內(nèi)容染服。
JSON 示例如下:
{
"msg_id":"123456",
"n_content":"this is content",
"n_extras":{"key1":"value1","key2":"value2"},
"n_title":"this is title",
"rom_type":0
}
JSON 內(nèi)容字段說明:
字段 | 取值類型 | 描述 |
---|---|---|
msg_id | String | 通過此key獲取到通知的msgid |
n_title | String | 通過此key獲取到通知標(biāo)題 |
n_content | String | 通過此key獲取到通知內(nèi)容 |
n_extras | String | 通過此key獲取到通知附加字段 |
rom_type | byte | 通過此key獲取到下發(fā)通知的平臺(tái)挖垛。得到值說明:byte類型的整數(shù)秉颗, 0為極光蚕甥,1為小米菇怀,2為華為,3為魅族库快,4為oppo义屏,5為vivo闽铐,8為FCM奶浦。 |
注: rom_type 用于點(diǎn)擊事件的上報(bào)澳叉,一般情況下開發(fā)者只需要取到該字段的值用于上報(bào)成洗,不需要關(guān)心具體取值。
3.通知點(diǎn)擊上報(bào)
解析通知內(nèi)容后充包,需主動(dòng)調(diào)用接口來進(jìn)行通知點(diǎn)擊上報(bào)遥椿,上報(bào)接口如下:
/**
* context 上下文
* msgId 消息ID
* whichPushSDK 收到推送的平臺(tái),即 rom_type 字段的取值家浇。
**/
JPushInterface.reportNotificationOpened(Context context, String msgId, byte whichPushSDK);
注: 點(diǎn)擊上報(bào)必須傳入正確的 whichPushSDK 參數(shù)钢悲,否則會(huì)造成統(tǒng)計(jì)數(shù)據(jù)錯(cuò)誤。
4.富媒體調(diào)整
在 AndroidManifest.xml 中將 PushActivity、PopWinActivity 的 android:exported="false" 屬性修改為 true督笆,否則會(huì)導(dǎo)致收不到富媒體推送娃肿。
5.Activity 示例代碼
package com.example.jpushdemo;
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;
/**
* Created by jiguang on 17/7/5.
*/
public class OpenClickActivity extends Activity {
private static final String TAG = "OpenClickActivity";
/**消息Id**/
private static final String KEY_MSGID = "msg_id";
/**該通知的下發(fā)通道**/
private static final String KEY_WHICH_PUSH_SDK = "rom_type";
/**通知標(biāo)題**/
private static final String KEY_TITLE = "n_title";
/**通知內(nèi)容**/
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();
}
/**
* 處理點(diǎn)擊事件料扰,當(dāng)前啟動(dòng)配置的Activity都是使用
* Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK
* 方式啟動(dòng)晒杈,只需要在onCreat中調(diào)用此方法進(jìn)行處理
*/
private void handleOpenClick() {
Log.d(TAG, "用戶點(diǎn)擊打開了通知");
String data = null;
//獲取華為平臺(tái)附帶的jpush信息
if (getIntent().getData() != null) {
data = getIntent().getData().toString();
}
//獲取fcm拯钻、oppo、vivo拼余、華碩匙监、小米平臺(tái)附帶的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);
String extras = jsonObject.optString(KEY_EXTRAS);
StringBuilder sb = new StringBuilder();
sb.append("msgId:");
sb.append(String.valueOf(msgId));
sb.append("\n");
sb.append("title:");
sb.append(String.valueOf(title));
sb.append("\n");
sb.append("content:");
sb.append(String.valueOf(content));
sb.append("\n");
sb.append("extras:");
sb.append(String.valueOf(extras));
sb.append("\n");
sb.append("platform:");
sb.append(getPushSDKName(whichPushSDK));
mTextView.setText(sb.toString());
//上報(bào)點(diǎn)擊事件
JPushInterface.reportNotificationOpened(this, msgId, whichPushSDK);
} catch (JSONException e) {
Log.w(TAG, "parse notification error");
}
}
private String getPushSDKName(byte whichPushSDK) {
String name;
switch (whichPushSDK){
case 0:
name = "jpush";
break;
case 1:
name = "xiaomi";
break;
case 2:
name = "huawei";
break;
case 3:
name = "meizu";
break;
case 4:
name= "oppo";
break;
case 5:
name = "vivo";
break;
case 6:
name = "asus";
break;
case 8:
name = "fcm";
break;
default:
name = "jpush";
}
return name;
}
}