跳转至

华为

前期准备

一 参考华为推送集成文档 注册和创建应用后,开通 PUSH 权限,记录下应用的 AppID、AppSecret。

二 前往融云开发者后台,在“应用标识 -> Andrid -> 华为推送设置” 栏目中,填写上一步在华为后台申请到的应用的 AppSecret,AppID。

填写这两项后,即表示开通华为推送功能,在华为 ROM 上面会使用系统级别的华为推送,从而提高推送到达率。如不想使用华为推送,将设置项保存为空即可,设置 30 分钟后内生效。

在融云开发者后台填写华为 AppSecret 和 AppID,以及推送通知标题。

“自定义点击动作 intent” 这一栏非必填,默认点击通知时会唤起会话列表界面。您也可以自定义点击通知时的跳转 Intent,详细请参考华为推送通知说明

接入流程

导入推送 SDK

在项目的 build.gradle 文件,allprojects->repositories 里面配置 HMS SDK 的 maven 仓库。

allprojects {
 repositories {
     jcenter()
	   maven {url 'http://developer.huawei.com/repo/'}
 }
}
之后打开 APP 模块的 build.gradle 文件,配置编译依赖

 dependencies {
    api 'com.huawei.android.hms:base:2.6.1.301'
    api 'com.huawei.android.hms:push:2.6.1.301'
}

提示

融云 SDK 从 2.8.10 版本开始支持 HMS 推送,如您使用的是之前版本的 SDK 请先进行升级。

注意:HMS 需要在手机上安装 2.4.0+ 版本的华为移动服务(华为帐号)

添加推送配置

配置 AndroidManifest.xml 文件,在 manifest 节点下增加所需的权限:

<!--HMS-SDK引导升级HMS功能,访问OTA服务器需要网络权限-->
<uses-permission android:name="android.permission.INTERNET" />
<!--HMS-SDK引导升级HMS功能,保存下载的升级包需要SD卡写权限-->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!--检测网络状态-->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<!--检测wifi状态-->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<!--为了获取用户手机的IMEI,用来唯一的标识用户。-->
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>

<!--如果是安卓8.0,应用编译配置的targetSdkVersion>=26,请务必添加以下权限 -->
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
在 application 节点下增加:

<meta-data
     android:name="com.huawei.hms.client.appid"
     android:value="您的华为 AppKey" />
<!-- BridgeActivity定义了HMS-SDK中一些跳转所需要的透明页面-->
<activity
    android:name="com.huawei.hms.activity.BridgeActivity"
    android:configChanges="orientation|locale|screenSize|layoutDirection|fontScale"
    android:excludeFromRecents="true"
    android:exported="false"
    android:hardwareAccelerated="true"
    android:theme="@android:style/Theme.Translucent" >
    <meta-data
        android:name="hwc-theme"
        android:value="androidhwext:style/Theme.Emui.Translucent" />
 </activity>

<!-- 解决华为移动服务升级问题的透明界面(必须声明)-->
<activity
    android:name="com.huawei.android.hms.agent.common.HMSAgentActivity"
    android:configChanges="orientation|locale|screenSize|layoutDirection|fontScale"
    android:excludeFromRecents="true"
    android:exported="false"
    android:hardwareAccelerated="true"
    android:theme="@android:style/Theme.Translucent" >
    <meta-data
        android:name="hwc-theme"
        android:value="androidhwext:style/Theme.Emui.Translucent" />
 </activity>

<provider
    android:name="com.huawei.hms.update.provider.UpdateProvider"
	  android:authorities="xxx.xxx.xxx.hms.update.provider"
    android:exported="false"
    android:grantUriPermissions="true">
</provider>
<!-- 第三方相关 :接收Push消息(注册、Push消息、Push连接状态)广播 -->
<receiver android:name="io.rong.push.platform.hms.HMSReceiver" >
    <intent-filter>
    <!-- 必须,用于接收token -->
	  <action android:name="com.huawei.android.push.intent.REGISTRATION" />
    <!-- 必须,用于接收消息 -->
    <action android:name="com.huawei.android.push.intent.RECEIVE" />
    <!-- 可选,用于点击通知栏或通知栏上的按钮后触发onEvent回调 -->
    <action android:name="com.huawei.android.push.intent.CLICK" />
    <!-- 可选,查看push通道是否连接,不查看则不需要 -->
    <action android:name="com.huawei.intent.action.PUSH_STATE" />
    </intent-filter>
</receiver>
<receiver android:name="com.huawei.hms.support.api.push.PushEventReceiver" >
     <intent-filter>
     <!-- 接收通道发来的通知栏消息,兼容老版本Push -->
     <action android:name="com.huawei.intent.action.PUSH" />
     </intent-filter>
</receiver>

上述 xml 里 "您的华为 AppKey" 需要用实际申请的应用 ID 替换, “xxx.xxx.xxx”用实际的应用包名替换。

启用推送服务

在调用融云初始化 API (即 RongIM.init() 或 RongIMClient.init()) 之前,将 PushConfig 里的 hms 开关打开。如果没有 PushConfig 对象,则需要新建一个,并进行相应配置。

PushConfig config = new PushConfig.Builder()
        .enableMiPush("", "") //配置小米推送
        .enableHWPush(true)  // 配置华为推送
        .build();
RongPushClient.setPushConfig(config);
RongIM.init(this);
异常事件处理

可以在自定义的继承自 PushMessageReceiver 的广播接收器中,复写如下事件来捕捉推送异常事件。

    /**
     * 第三方push状态回调
     *
     * @param pushType   push类型
     * @param action     当前的操作,连接或者获取token
     * @param resultCode 返回的错误码
     */
     @Override
     public void onThirdPartyPushState(PushType pushType, String action, long resultCode) {
         super.onThirdPartyPushState(pushType, action, resultCode);
     }
当 pushType 为 PushType.HUAWEI, 且错误码为以下几种时,可以调用 RongPushCient.resolveHWPushError() 方法来尝试解决。

    /**
     * 处理华为push连接错误,由终端用户操作解决.
     * 当错误码为以下错误码才能通过终端用户操作解决:
     * {@link com.huawei.hms.api.ConnectionResult#SERVICE_MISSING}
     * {@link com.huawei.hms.api.ConnectionResult#SERVICE_VERSION_UPDATE_REQUIRED}
     * {@link com.huawei.hms.api.ConnectionResult#BINDFAIL_RESOLUTION_REQUIRED}
     *
     * @param activity  当前界面的activity, 不能传空
     * @param errorCode 错误码
     */
    public static void resolveHWPushError(Activity activity, long errorCode) throws RongException {}

HMS 相关错误码说明可参考以下链接:错误码说明

至此,HMS 推送集成完毕。

推送通知说明

一 通知方式

为了保证推送的及时性,在使用华为 HMS 推送时,我们默认使用的是通知栏推送方式,即由华为手机系统直接弹出通知。所以不支持自定义通知显示。

二 捕捉通知到达事件

由于 HMS 在推送到达时,没有回调事件,所以 HMS 推送不支持捕捉通知到达事件。

三 通知点击事件

拦截通知点击事件

华为通知栏推送方式下,当用户点击通知时,华为系统会通过隐式调用的方式,发出 intent 事件,您可以拦截该事件,获取用户点击行为以及携带的数据。

默认传递的 intent 如下:

intent://你的包名/conversationlist?isFromPush=true#Intent;scheme=rong;launchFlags=0x4000000;end
该 intent 会同时携带一些附加数据,比如您在调用 RongIMClient.getInstance.sendMessage() 时传递的参数 pushData,比如您在使用开发者后台的广播推送功能时,自定义的键值对等。

您可以参考以下示例获取数据,并进行相应的业务处理。

Intent intent = getIntent();
if (intent.getData().getScheme().equals("rong") && intent.getData().getQueryParameter("isFromPush") != null) {
    if (intent.getData().getQueryParameter("isFromPush").equals("true")) {
        String options = getIntent().getStringExtra("options"); // 获取 intent 里携带的附加数据
        NLog.d(TAG, "options:", options);
        try{
            JSONObject jsonObject = new JSONObject(options);
            if(jsonObject.has("appData")) {   // appData 对应的是客户端 sendMessage() 时的参数 pushData
                NLog.d(TAG, "pushData:", jsonObject.getString("appData"));
            }
            if(jsonObject.has("rc")) {
                JSONObject rc = jsonObject.getJSONObject("rc");
                NLog.d(TAG, "rc:", rc);
                String targetId = rc.getString("tId"); // 该推送通知对应的目标 id.
                String pushId = rc.getString("id");  // 开发者后台使用广播推送功能发出的推送通知,会有该字段,代表该推送的唯一 id, 需要调用下面接口,上传用户打开事件。
                if(!TextUtils.isEmpty(pushId)) {
                    RongPushClient.recordNotificationEvent(pushId); // 上传用户打开事件,以便进行推送打开率的统计。
                    NLog.d(TAG, "pushId:", pushId);
                }
                if (rc.has("ext") && rc.getJSONObject("ext") != null) {
                    String ext = rc.getJSONObject("ext").toString(); // 使用开发者后台的广播推送功能时,填充的自定义键值对。
                    NLog.d(TAG, "ext:", ext);
                }
            }
        } catch (JSONException e) {

        }
        enterActivity();
    }
}

自定义 intent

您也可以自定义点击通知时,发出的 intent,自定义的 intent 获取方式可以参考如下代码:

Intent intent = new Intent(Intent.ACTION_VIEW);
Uri uri = Uri.parse("rong://" + this.getPackageName()).buildUpon()
        .appendPath("conversationlist")
        .appendQueryParameter("isFromPush", "true").build();
intent.setData(uri);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
String intentUri = intent.toUri(Intent.URI_INTENT_SCHEME);

将上面代码中最终生成的 intentUri 填写到开发者后台即可。

应用角标设置

开发者后台“应用标识 - 华为推送设置”中,设置角标数(badgeAddNum)及桌面图标对应的应用入口 Activity 类(badgeClass),可自定义角标功能。

详细参考华为服务端发送应用角标功能。

冲突处理

如果您本身的业务体系已接入了 HMS 推送,在通过融云接入 HMS 推送时,会导致继承自华为 PushMessageReceiver 的自定义广播和融云 HMSReceiver 冲突。这时候需要您将继承自华为 PushMessageReceiver 的广播改为继承自融云 SDK 中的 HMSReceiver。在回调事件中判断如果是融云业务,调用父类方法,否则调用自身业务逻辑。另外还需要在 AndroidManifest.xml 里将 HMSReceiver 改为您自定义的广播接收器名称。

混淆打包

如果需要混淆,则加上下面的混淆脚本:

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

-keep class com.huawei.gamebox.plugin.gameservice.**{*;}

-keep public class com.huawei.android.hms.agent.** extends android.app.Activity { public *; protected *; }
-keep interface com.huawei.android.hms.agent.common.INoProguard {*;}
-keep class * extends com.huawei.android.hms.agent.common.INoProguard {*;}