Android 推送服务开发指南

    从 SDK 2.9.9 版本开始,融云推送功能进行升级,集成方式请参考以下文档说明。如使用的是 2.9.9 之前的 SDK 集成可参考集成文档

    概述

    融云推送是通过在云端和客户端之间维护一条稳定可靠的长链接通道,从云端发送各类消息至客户端并以通知形式展现的服务。

    使用场景

    默认有两种使用场景:

    1. 集成 IM SDK 后默认具备的推送能力。

      集成 IM SDK 并连接到服务器后,客户端会和云端建立两个连接通道:消息通道和推送通道。

      当消息通道断开后,收到新消息时我们会通过推送通道下发通知给用户,提醒用户消息到达。此时客户端显示的通知即推送通知。

      消息通道断开具体有以下几个场景:

      a. 客户端调用 SDK 的断开方法,即 disconnect() 方法。

      b. 应用长时间在后台,被系统回收后。

      以上两种场景下会通过推送通道下发推送通知。您也可以参考 通知概念 了解本地通知和推送通知的具体区别。

      备注:应用退到后台,但没被系统回收时,收到新消息时弹出的通知属于本地通知,是由消息通道下发的,不是推送通知。请不要混淆。

    2. 在融云开发者后台广播推送-广播消息-推送中,发起远程推送,并进行推送效果追踪。

      该类型的推送始终通过推送通道下发,和消息通道无关。

    关于第三方推送

    鉴于目前国内各手机厂商对 ROM 进行了深度定制化,应用级别的推送进程基本不可能达到永久保活,所以我们引进了几个主要厂家系统级别的推送。您在集成 IM SDK 的基础上,只需要简单几步,既可完成第三方推送的集成。

    推送通道选择策略

    融云在使用推送服务时,会根据应用在融云开发者平台设置的第三方推送情况和终端用户使用的具体机型,智能选择推送通道。通道选择策略如下:

    1. 如应用设置了第三方推送,终端用户在使用对应的设备时,则使用第三方的推送通道,目前融云支持的第三方推送如下:

      • 小米推送:在小米 ROM 上使用。

      • 华为推送:在华为 ROM 上使用。

      • 魅族推送:在魅族 ROM 上使用。

      • OPPO 推送:在支持 OPPO 推送的 OPPO ROM 上使用。

      • vivo 推送:在支持 vivo 推送的 vivo ROM 上使用。

      • FCM 推送 (谷歌官方推送):如果您的应用在海外运营或者有较大比率海外用户,融云建议您开通 FCM 推送。融云会根据终端用户的 IP 判断用户是否为海外用户,如果为海外用户,则使用 FCM 推送。

    2. 应用没有设置上述第三方推送或终端用户使用的手机不是以上第三方推送所属机型,默认使用融云推送服务。

      由于融云推送属于应用级别的推送,会受系统各种权限限制,我们建议您在使用时,在设置里打开自启动权限和通知权限,或者勾选“信任此应用”等,以提高推送到达率。各手机上面的权限设置可以参考各类机型权限设置说明

    消息推送的流程

    App / App Server -> RongCloud Server: 应用或应用服务端向目标用户发送消息 RongCloud Server -> RongCloud Server: 判断用户在线状态 RongCloud Server -> RongCloud Push Server: 向未在线目标用户,发消息到 RongCloud Push Server RongCloud Push Server -> RongCloud Push Server: 判断是否设置了第三方推送 RongCloud Push Server -> 第三方 Push Server: 已设置,则发送到第三方推送服务 第三方 Push Server -> App: 向目标用户,发送远程通知至客户端 RongCloud Push Server -> App: 未设置,则直接向目标用户,发送远程通知至客户端

    融云推送集成指南

    前提条件

    使用融云推送前,必须先集成融云 IM SDK。您可以参考 融云 SDK 介绍 集成对应的 SDK。

    设置应用唯一标识

    在 “融云开发者后台 -> 应用标识 -> Android -> ApplicationID” 一栏填写您应用的唯一标识。

    配置推送通知点击事件

    点击融云推送通知时,融云 SDK 会以隐式调用的方式发出相应 intent,从而唤起对应 activity。您需要在 AndroidManifest.xml 里进行如下配置:

    a. 只有一个联系人发来一条或多条通知时,点击通知默认跳转到会话 activity。在会话 activity 中配置如下 intnt-filter 即可拦截该事件。

    <activity
    android:name="您的会话 activity"
    android:exported="true">
    <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <data
            android:host=""${applicationId}""
            android:pathPrefix="/conversation/"
            android:scheme="rong" />
    </intent-filter>
    </activity>
    

    b. 多个联系人发来多条通知时,这些通知会折叠显示,点击该通知会跳转到会话列表 activity。在 AndroidManifest.xml 的会话列表 activity 中配置如下 intent-filter 进行拦截。

    <activity
    android:name="您的会话列表 activity"
    android:exported="true">
    <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <data
            android:host=""${applicationId}""
            android:pathPrefix="/conversationlist"
            android:scheme="rong" />
    </intent-filter>
    </activity
    

    c. 当从融云开发者后台广播推送-广播消息-推送中,发起远程推送时,该推送通知会独立显示,在 AndroidManifest.xml 里进行如下配置来拦截该类型通知的点击事件。

    <activity
    android:name="自定义 activity"
    android:exported="true"
    android:launchMode="singleTask"
    android:screenOrientation="portrait">
    
    <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
    
        <data
            android:host=""${applicationId}""
            android:pathPrefix="/push_message"
            android:scheme="rong" />
    </intent-filter>
    </activity>
    

    配置第三方推送

    在应用的 onCreate() 方法中, 初始化方法之前参考如下方法进行第三方推送的配置。如果您不需要使用第三方推送,可以跳过此步骤。

    PushConfig config = new PushConfig.Builder()
            .enableHWPush(true)
            .enableMiPush("小米 appId", "小米 appKey")
            .enableMeiZuPush("魅族 appId", "魅族 appKey")
            .enableFCM(true)
            .build();
    RongPushClient.setPushConfig(config);
    

    通过以上步骤,即完成了融云推送服务的基本集成。您还可以参考下面的文档,继续进行第三方推送的详细集成。

    小米推送集成指南

    准备工作

    一 前往小米开放平台 注册账号,通过认证后创建应用,并记录下应用的 AppID、AppKey、AppSecret。

    二 前往融云开发者后台,在“应用标识 -> Android -> 小米推送设置” 一栏中,填写上一步在小米开放平台申请的应用 AppSecret 以及通知标题。

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

    小米推送通知标题,是指手机端接收到小米推送后需要展示的通知标题。

    接入流程

    导入小米推送客户端 SDK

    请从小米开放平台 或者融云官网下载小米 SDK ,并将小米 SDK jar 导入到你的应用 module 的 libs 目录下,然后右键-》Add as library

    配置 AndroidManifest.xml 文件

    在应用 module 的 Androidmanifest.xml 文件下增加如下配置

    <!-- 小米 配置开始 < -->
    <permission
    android:name="${applicationId}.permission.MIPUSH_RECEIVE"
    android:protectionLevel="signature" />
    <uses-permission android:name="${applicationId}.permission.MIPUSH_RECEIVE" /> <!-- 小米 配置结束 < -->
    

    application 节点增加配置如下的服务和广播:

    <!-- 小米 配置开始 < -->
     <service android:name="com.xiaomi.push.service.XMPushService" android:enabled="true" />
     <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" />
     <!--注:此service必须在2.2.5版本以后(包括2.2.5版本)加入-->
    
     <service
         android:name="com.xiaomi.push.service.XMJobService"
         android:enabled="true"
         android:exported="false"
         android:permission="android.permission.BIND_JOB_SERVICE" />
     <!--注:此service必须在3.0.1版本以后(包括3.0.1版本)加入-->
    
     <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">
       <intent-filter>
         <action android:name="com.xiaomi.push.PING_TIMER" />
       </intent-filter>
     </receiver>
     <receiver android:name="io.rong.push.platform.mi.MiMessageReceiver" 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>
     <!-- 小米 配置结束 < -->
    

    客户端配置小米推送

    最后,在调用融云初始化 API (即RongIM.init() 或 RongIMClient.init()) 之前,新建一个 PushConfig 对象,通过 PushConfig.Builder.enableMiPush() 配置小米推送,并通过 RongPushCient.setPushConfig() 设置到 SDK 中。

    PushConfig config = new PushConfig.Builder()
            .enableMiPush("", "")
            .build();
    RongPushClient.setPushConfig(config);
    RongIM.init(this);
    

    至此,小米推送适配完成。 现在您可以将 APP 安装至小米设备上,进行消息推送的测试。

    小米推送通知说明

    一 通知方式

    由于小米的透传推送,要求应用在后台处于启动状态,这样不能保证推送的及时性,所以在使用小米推送时,我们默认使用的是小米通知栏推送方式,即由小米系统直接弹出通知。所以不支持自定义通知显示。

    二 捕捉通知到达事件

    您可以通过融云 SDK 快速集成时,自定义的广播接收器的 onNotificationMessageArrived() 来捕捉通知到达事件。如下所示:

      public class 自定义的广播接收器 extends PushMessageReceiver {
        @Override
        public boolean onNotificationMessageArrived(Context context, PushType pushType, PushNotificationMessage pushNotificationMessage) {
          //此时通知已由小米系统弹出并显示,仅可以在此处捕捉 pushNotificationMessage 中的相关信息。
          return false;
        }
        ...
      }
    

    备注 :上面事件的回调,需要用户打开自启动权限。

    三 自定义通知点击事件

    使用小米推送时,在小米手机上点击推送通知,默认打开会话列表页面。

    您也可以通过融云 SDK 快速集成时,自定义的广播接收器的 onNotificationMessageClicked() 回调中,自定义通知点击事件。如下所示:

    public class 自定义的广播接收器 extends PushMessageReceiver {
      ...
      @Override
      public boolean onNotificationMessageClicked(Context context, PushType pushType, NotificationMessage message) {
        //实现您自定义的通知点击跳转逻辑
        return true; // 此处返回 true. 代表不触发 SDK 默认实现,您自定义处理通知点击跳转事件。
      }
    }
    

    冲突处理

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

    华为推送集成指南

    准备工作

    一 参考华为推送集成文档 注册和创建应用后,开通 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”用实际的应用包名替换。

    客户端配置 HMS

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

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

    处理 HMS 异常事件

    您可以在自定义的继承自 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 在推送到达时,没有回调事件,所以 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 {*;}
    

    魅族推送集成指南

    在进行魅族推送适配之前,请确保您已经按照融云 Push 集成文档集成了融云 SDK;这是对魅族设备进行特殊适配的前提条件,融云 SDK 2.9.0 版本开始支持魅族推送功能。

    前期准备

    1. 前往 Flyme 开放平台 注册账号并通过认证.

    2. 开发者身份认证后,进入 魅族推送平台 创建应用,并记录下应用的 AppID、AppKey、AppSecret。

    3. 登录融云开发者后台在应用标识中设置 Android 第三方推送,将第 2 步获取的魅族 AppSecret 填入魅族推送设置项并保存。

    推送接入流程

    1、在应用的 builg.gradle 下面添加如下依赖

    dependencies {
      compile 'com.meizu.flyme.internet:push-internal:3.6.+@aar'
    }
    

    2、在应用的 AndroidManifest.xml 里增加如下配置。

    <!-- MeiZu 配置开始 < -->
    <!-- 兼容 flyme5.0 以下版本,魅族内部集成 pushSDK 必填,不然无法收到 消息-->
    <uses-permission
        android:name="com.meizu.flyme.push.permission.RECEIVE"/>
    <permission
        android:name="您的包名.push.permission.MESSAGE"
        android:protectionLevel="signature"/>
    <uses-permission android:name="您的包名.push.permission.MESSAGE"/>
    <!-- 兼容 flyme3.0 配置权限-->
    <uses-permission android:name="com.meizu.c2dm.permission.RECEIVE" />
    <!-- MeiZu 配置结束 < -->
    
    <application
    <!-- MeiZu 配置开始 < -->
            <receiver android:name="io.rong.push.platform.meizu.MeiZuReceiver">
            <intent-filter>
                <!-- 接收 push 消息 -->
                <action android:name="com.meizu.flyme.push.intent.MESSAGE"/>
                <!-- 接收 register 消息 -->
                <action
                    android:name="com.meizu.flyme.push.intent.REGISTER.FEEDBACK" />
                <!-- 接收 unregister 消息-->
                <action
                    android:name="com.meizu.flyme.push.intent.UNREGISTER.FEEDBACK"/>
                />
                <!-- 兼容低版本 Flyme3 推送服务配置 -->
                <action android:name="com.meizu.c2dm.intent.REGISTRATION"/>
                <action android:name="com.meizu.c2dm.intent.RECEIVE" />
                <category android:name="您的包名"/>
            </intent-filter>
             </receiver>
            <!-- MeiZu 配置结束 < -->
    </application>
    

    3、客户端配置魅族推送

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

    PushConfig config = new PushConfig.Builder()
            .enableMiPush("", "") //配置小米推送
            .enableHWPush(true)  // 配置华为推送
            .enableMeiZuPush("","") //配置魅族推送
            .build();
    RongPushClient.setPushConfig(config);
    RongIM.init(this);
    

    OPPO 推送集成指南

    在进行 OPPO 推送适配之前,请确保您已经按照融云 Push 集成文档集成了融云 SDK;这是对 OPPO 设备进行特殊适配的前提条件。

    前期准备

    1. 前往 OPPO 开放平台 注册企业开发者账号并进行认证。

    2. 开发者身份认证后,使用 OPPO 企业开发者账号,登陆 OPPO 开放平台 ,在“管理中心-软件&游戏-应用列表-选择应用-移动服务-消息推送”中完成 OPPO PUSH 权限申请。在完成权限申请后可在申请界面可获取接入所需的 AppKey、AppSecret、MasterSecret 等验证信息。

    3. 登录融云开发者后台在 应用标识 中设置 Android 第三方推送,将第 2 步获取的 AppKey 和 MasterSecret 填入 OPPO 推送设置项并保存。

    推送接入流程

    1、导入推送 jar 包

    进入 OPPO 开放平台-推送服务,下载 OPPO Push 客户端 SDK。将解压后将文件夹中 jar 包拷贝到您的工程的 libs 文件夹中。

    2、配置 AndroidManifest 文件

    OPPO 推送服务 SDK 支持的最低安卓版本为 Android 4.0 系统。

    在当前工程的 AndroidManifest.xml 文件中,添加权限列表和推送服务组件注册

    权限列表

    <uses-permission android:name="com.coloros.mcs.permission.RECIEVE_MCS_MESSAGE"/>
    

    推送服务组件注册

    <service
       android:name="com.coloros.mcssdk.PushService"
       android:permission="com.coloros.mcs.permission.SEND_MCS_MESSAGE">
        <intent-filter>
         <action android:name="com.coloros.mcs.action.RECEIVE_MCS_MESSAGE"/>
        </intent-filter>
    </service>
    `
    

    3、启用 OPPO 推送服务

    在 Application 中调用融云初始化接口之前,若没有开启其他推送则加入以下代码启用 OPPO 推送,并填入在申请界面获取的 AppKey、AppSecret。

    PushConfig.Builder builder = new PushConfig.Builder();
    builder.enableOppoPush(OPPO_App_KEY, OPPO_App_Secret);
    RongPushClient.setPushConfig(builder.build());
    

    注:若同时使用其他推送请在 builder 中启用其他推送,若使用旧版本的 RongPushClient 的 register 方式启用的推送,请改用此 RongPushClient#setPushConfig 方式由 builder 启用推送。

    推送通道选择策略

    由于并非所有的 OPPO 手机都支持 OPPO 推送,所以仅在支持的手机上使用 OPPO 推送,在不支持的手机上使用融云默认推送。

    由于融云推送属于应用级别的推送,会受系统各种权限限制,我们建议您在使用时,在设置里打开自启动权限和通知权限,或者勾选“信任此应用”等,以提高推送到达率。

    常见问题

    接收 OPPO 推送需要用户的 OPPO 手机开启应用的通知权限。

    OPPO 推送暂时只支持通知栏消息的推送。消息下发到 OS 系统模块并由系统通知模块展示,在用户点击通知前,不启动应用。

    OPPO 推送的机型和规则等相关内容请参考 OPPO Push FAQ

    vivo 推送集成指南

    在进行 vivo 推送适配之前,请确保您已经按照融云 Push 集成文档集成了融云 SDK;这是对 vivo 设备进行特殊适配的前提条件。

    前期准备

    1. 前往 vivo 开发者平台 注册账号并进行认证。

    2. 开发者身份认证后,进入 vivo 开发者平台-推送服务器平台 创建应用,并记录下应用的 AppID、AppKey。

    3. 登录融云开发者后台在 应用标识 中设置 Android 第三方推送,将第 2 步获取的 AppID 和 AppKey 填入 vivo 推送设置项并保存。

    推送接入流程

    1、导入推送 jar 包

    进入 vivo 文档中心,下载 Push SDK 接入文档。将解压后的 libs 文件夹中 vivo_pushsdk-VERSION.jar ( VERSION 为版本名称) 拷贝到您的工程的 libs 文件夹中。

    2、配置 AndroidManifest 文件

    在当前工程的 AndroidManifest.xml 文件中添加权限和声明信息,详见:

    <!-- 推送需要的权限列表 -->           
    <uses-permission android:name="android.permission.INTERNET"/>
    
    <!-- vivo 推送服务需要配置的 service、activity -->        
    <service           
        android:name="com.vivo.push.sdk.service.CommandClientService"           
        android:exported="true"/>       
    <activity           
        android:name="com.vivo.push.sdk.LinkProxyClientActivity"       
        android:exported="false"       
        android:screenOrientation="portrait"       
        android:theme="@android:style/Theme.Translucent.NoTitleBar"/>
    
    <!-- vivo push 推送 receiver 声明 -->           
    <receiver android:name="io.rong.push.platform.vivo.VivoPushMessageReceiver" >           
        <intent-filter>       
            <!-- 接收 vivo push 消息 -->   
            <action android:name="com.vivo.pushclient.action.RECEIVE" />   
        </intent-filter>       
    </receiver>
    

    并在 AndroidManifest.xml 文件中添加 vivo 推送配置项,将 vivo 推送平台生成的 AppID、AppKey 填入 vivo 推送配置项中

    <!-- vivo 推送配置项 -->           
    <meta-data           
        android:name="com.vivo.push.api_key"       
        android:value="您的 vivo 推送平台生成 AppKey"/>       
    <meta-data           
        android:name="com.vivo.push.app_id"       
        android:value="您的 vivo 推送平台生成 AppID"/>
    

    3、启用 vivo 推送服务

    在 Application 中调用融云初始化接口之前,若没有开启其他推送则加入以下代码启用 vivo 推送。

    PushConfig.Builder builder = new PushConfig.Builder();
    builder.enableVivoPush(true);
    RongPushClient.setPushConfig(builder.build());
    

    注:若同时使用其他推送请在 builder 中启用其他推送,若使用旧版本的 RongPushClient 的 register 方式启用的推送,请改用此 RongPushClient#setPushConfig 方式由 builder 启用推送。

    推送通道选择策略

    由于并非所有的 vivo 手机都支持 vivo 推送,所以仅在支持的手机上使用 vivo 推送,在不支持的手机上使用融云默认推送。

    由于融云推送属于应用级别的推送,会受系统各种权限限制,我们建议您在使用时,在设置里打开自启动权限和通知权限,或者勾选“信任此应用”等,以提高推送到达率。

    常见问题

    接收 vivo 推送需要用户的 vivo 手机开启应用的通知权限。

    关于 vivo 推送相关的内容,包括适用推送的时间和支持的手机型号请参考 vivo 开发平台的 vivo 推送服务指南

    FCM 推送集成指南

    准备工作

    首先,要有个 Google 开发者账号,然后登录到 Firebase 控制台创建 Firebase 项目,如下图:

    image

    1、如果已经有一个与您的移动应用关联的现有 Google 项目(之前集成过 GCM),请点击 Import Google Project。 否则,请点击 Create New Project。

    2、创建之后,点击 Add Firebase to your Android app 并按设置步骤进行操作。如果在导入现有 Google 项目,这可能是自动进行的,您只需下载配置文件即可。

    image

    3、出现提示时,输入您的应用的包名称。输入您应用使用的包名称十分重要。只有当您将一个应用添加至您的 Firebase 项目时才能进行此设置。 4、最后,您将下载一个 google-services.json 文件。您可以随时重新下载此文件。 5、最后将下载的 json 文件 copy 到你的 App 的目录下。

    上述步骤之后,你可以进入 project setting,之后点击 CLOUD MESSAGING 查看 Server key,将它设置到融云开发者平台上 FCM 密钥配置中

    image
    image

    接入流程

    导入 SDK

    首先在根级别的 build.gradle 文件添加一条规则。以包含 Google 服务插件

    // ...
    dependencies {
        // ...
        classpath 'com.google.gms:google-services:4.2.0'
    }
    

    然后在模块 Gradle 文件(通常是app/build.gradle)中,添加 firebase 依赖

    apply plugin: 'com.android.application'
    
    android {
      // ...
    }
    
    dependencies {
      // ...
      api 'com.google.android.gms:play-services:12.0.1'
      api 'com.google.firebase:firebase-messaging:17.6.0'
    }
    

    之后再你 app module 下最后一行加入下面一句,底部 添加 apply plugin 行,以启用 Gradle 插件:

    // ADD THIS AT THE BOTTOM
    apply plugin: 'com.google.gms.google-services'
    

    需要注意的是该 build.gradle 文件和之前下载的 google-services.json 文件应该处于同一个目录下面。

    如果 AndroidStudio 版本是 2.2+ 的话,则可以通过 Tools->Firebase. 点击 Cloud Messaging->set up Firebase Cloud Messaging. 之后从准备工作步骤 2 开始集成。不要忘了api 'com.google.android.gms:play-services:12.0.1'

    配置清单文件

    在你 App 下的 AndroidManifest.xml 中加入

    <!-- [START firebase_service] -->
      <meta-data
        android:name="firebase_messaging_auto_init_enabled"
        android:value="false" />
      <meta-data
        android:name="firebase_analytics_collection_enabled"
        android:value="false" />
    
      <service
        android:name="io.rong.push.platform.google.RongFirebaseMessagingService"
        android:stopWithTask="false"
        android:exported="false">
             <intent-filter>
                  <action android:name="com.google.firebase.MESSAGING_EVENT"/>
              </intent-filter>
       </service>
       <!-- [END firebase_service] -->
    

    客户端配置 FCM 推送

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

    PushConfig config = new PushConfig.Builder()
            .enableMiPush("", "") //配置小米推送
            .enableHWPush(true)  // 配置华为推送
            .enableFCM(true) //配置 FCM 推送
            .build();
    RongPushClient.setPushConfig(config);
    RongIM.init(this);
    

    异常处理

    和 HMS 相似。您可以在自定义的继承自 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.GOOGLE_FCM 时, 您可根据 resultCode 到 com.google.android.gms.common.ConnectionResult 中查看错误码具体含义,根据需要,选择是否弹出对话框提醒用户安装对应环境等。

    至此,FCM 推送集成完毕。

    混淆脚本

    -dontwarn com.xiaomi.mipush.sdk.**
    -keep public class com.xiaomi.mipush.sdk.* {*; }
    -keep public class com.google.firebase.* {*;}
    

    API 说明

    RongPushCient API 说明

      /**
       * 设置 push 相关配置。
       *
       * @param config push 配置。{@link PushConfig.Builder}
       */
      public static void setPushConfig(PushConfig config) {
          pushConfig = config;
      }
    
     /**
      * 处理华为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 {}
    
     /**
      * 清除通知栏所有通知消息。
      *
      * @param context 上下文
      */
     public static void clearAllNotifications(Context context) {}
    
     /**
      * <p>清除所有的推送通知和后台消息通知。ex: A 账号离线或者退到后台,B 账号给 A 发送消息,A 设备会收到该消息的通知,调用此函数会清除该类型的通知。
      * 但是,如果是从开发者后台使用广播推送服务发送的推送通知,仍然会保留,不会清除   </p>。
      *
      * @param context 上下文。
      */
     public static void clearAllPushNotifications(Context context) {}
    
     /**
      * 清除所有后台推送服务的推送通知。后台推送服务,是指开发者后台的广播推送服务。
      *
      * @param context 上下文。
      */
     public static void clearAllPushServiceNotifications(Context context) {}
    
     /**
      * 根据 notification id 清除通知栏。
      *
      * @param context        上下文。
      * @param notificationId 通知栏消息 id。
      */
     public static void clearNotificationById(Context context, int notificationId) {}
    
     /**
      * <p>记录在开发者后台使用后台推送功能时,对应的推送通知的点击事件。开发者后台的推送打开率既根据客户端上传的该事件进行相应统计和计算。
      * 2.6.0之前版本,推送打开率的使用请在知识库里搜索标签 push,有相关说明。
      * 2.6.0之后版本,如果用户使用的 SDK 内置的通知实现,则不需要调用该方法来统计推送打开率,SDK 内部已经帮用户做了统计。
      * 但是如果用户自己定义了推送时通知栏的显示,则需要在点击通知时,调用此方法,来向服务器上传推送打开事件。</p>
      *
      * @param pushId push 通知的 Id。只有使用开发者后台广播消息和开发者后台推送服务时,pushId 才会有值,其余非后台情况下都为空。
      */
     public static void recordNotificationEvent(String pushId){}
    
     /**
      * 停止融云 push 服务,如果用的第三方推送,也会断掉和第三方推送的连接。
      *
      * @param context 应用上下文
      */
     public static void stopService(Context context){}
    
     /**
      * 发送通知。如果使用 IMLib 开发,当应用在后台需要弹后台通知时,可以直接调用此函数弹出通知。
      *
      * @param context             上下文
      * @param notificationMessage 融云对外公开的通知消息。
      */
     public static void sendNotification(Context context, PushNotificationMessage notificationMessage) {}
    

    PushNotificationMessage 成员列表

    API 功能 备注
    getPushId() 获取标识该推送消息的唯一 Id。 当使用开发者后台的广播推送服务时,该 Id 用来追踪推送打开率。只有当使用开发者后台的广播推送服务时,返回有效字符串。 其余情况,返回 null。 如果您自定义了推送通知的展示,在点击通知时需要调用 RongPushClient.recordNotificationEvent() 来上传推送打开事件,以便融云后台正确的帮您统计推送打开率。如果您没有自定义通知,则不需要额外操作,SDK 内部已经帮您做了打开率的统计。
    getConversationType() 获取该推送消息所属的会话类型。比如单聊,群组,讨论组等。
    getTargetId() 获取该推送消息的目标 Id。 比如单聊时,是对方的 Id ; 群组时,是群 Id ; 讨论组时,是该讨论组 Id。
    getTargetUserName() 获取该推送消息的目标名称。 单聊时,返回对方的名称; 群组时,返回群名称; 讨论组时,返回该讨论组的名称。
    getReceivedTime() 获取该推送消息的到达时间。 该时间是此条消息到达融云服务器的时间。
    getObjectName() 获取该推送消息的消息类型。 比如文本消息为 “RC:TxtMsg”,图片消息为“RC:ImgMsg”,语音消息为 “RC:VcMsg”,或者如果是自定义消息,则此处对应自定义消息的注解 MessageTag 里 value 的值。
    getSenderId() 获取该推送消息的发送者 Id。
    getSenderName() 获取该推送消息的发送者名称。
    getSenderPortrait() 获取该推送消息的发送者头像。
    getPushTitle() 推送标题,目前此字段暂未启用。
    getPushContent() 获取推送通知的显示内容。 当该推送消息是自定义消息时,此处的值对应 sendMessage() 的参数 pushContent 的内容。如果您在发送自定义消息时,没有填写 pushContent,则收不到推送。
    getPushData() 获取推送消息携带的附加信息。此处的值对应 sendMessage() 的参数 pushData 的内容。 发送自定义消息时,如果在 sendMessage() 时填写参数 pushData, 则收到这条消息的推送时,可以通过该方法获取 pushData 的内容。
    getExtra() 获取从开发者后台使用推送服务时,自定义的附加信息键值对。 该字段仅为开发者后台的推送服务使用,其余情况为 null。
    getPushFlag() 标识该消息是推送消息还是后台消息。

    收不到消息提醒解决方案

    部分 Android 手机系统在黑屏待机后自动清理后台运行的软件,这样影响了应用正常接收新的消息,需要将应用设置为后台运行应用。查看各类机型的设置说明

    为解决此类问题,融云为开发者提供了 Android 推送权限设置组件源码,用于检测融云 Push 所需的权限状态。如需要开通权限,则提示选择跳转到对应的权限设置界面进行设置,此组件也可单独集成到您工程中使用。

    常见问题

    错误码