目录

Android 第三方推送设置

更新时间:2022-07-27

环信即时通讯 IM 支持集成第三方厂商的消息推送服务,为 Android 开发者提供低延时、高送达、高并发、不侵犯用户个人数据的离线消息推送服务。

当客户端应用进程被关闭等原因导致用户离线,环信即时通讯 IM 服务会通过第三方厂商的消息推送服务向该离线用户的设备推送消息通知。当用户再次上线时,会收到离线期间所有消息。

目前支持的手机厂商推送服务包括:华为、小米、魅族、OPPO、VIVO、GOOGLE,本文以集成小米、华为的消息推送服务为例,介绍如何在客户端应用中实现消息推送。

技术原理

 推送

  1. 判断设备支持哪种推送(App 配置了第三方推送且满足该推送的使用条件);
  2. 根据集成第三方推送 SDK 获取推送 token;
  3. 上传证书名称(环信服务器用来判断使用哪种推送通道)和推送 token 到环信服务器;
  4. 向某设备发送消息时,环信服务器会先判断目标设备是否在线,如果目标设备不在线,则判断目标设备使用了哪种推送通道(根据目标设备上传的证书名称),使用该推送通道通过第三方推送服务器将消息推送至目标设备。
环信服务器应具备的能力:
Android 设备需要做的事:

前提条件

1. 已开启环信即时通讯服务,详见 开启和配置即时通讯服务
2. 若使用 3.9.2 及以上版本提供的推送高级功能,包括设置推送通知模式、免打扰模式和自定义推送模板,你需要在环信即时通讯云控制后台中激活推送高级功能。

各推送使用条件:

SDK 内部会按照这个顺序去检测设备的推送支持情况。

如果未设置第三方推送或者不满足使用第三方推送的条件,环信 IM SDK 会通过一些保活手段尽可能的保持与环信服务器的长连接,以确保消息及时送达。

建议:如果你的 App 有海外使用场景,建议开启 FCM 推送;由于各推送使用条件不同,建议尽可能同时支持各家推送。

使用消息推送前,需要你在对应的手机厂商推送服务上注册工程,并将设备的推送证书上传到环信即时通讯云控制台。

上传到设备证书到环信即时通讯云控制台

在客户端实现推送

1. 配置推送接口

你需要在 SDK 初始化的时候进行推送接口的配置。

EMOptions options = new EMOptions();
...
EMPushConfig.Builder builder = new EMPushConfig.Builder(this);
// 设置支持哪家手机厂商推送。
builder.enableMiPush(String appId, String appKey)
       //开发者需要调用该方法开启华为推送。
       .enableHWPush(); 
// Sets pushconfig to ChatOptions.
options.setPushConfig(builder.build());
// Initializes IM SDK.
EMClient.getInstance().init(this, options);

2. 混淆

-keep class com.hyphenate.** {*;}
-dontwarn  com.hyphenate.**

3. 手机厂商推送集成

FCM 推送集成

  1. Firebase 控制台创建项目
  1. 上传推送证书

  1. FCM 推送集成

dependencies {
        // Google Firebase cloud messaging
        classpath 'com.google.gms:google-services:4.3.8'
    }
dependencies {
    // ...

    // FCM: Import the Firebase BoM
    implementation platform('com.google.firebase:firebase-bom:28.4.1')
    // FCM: Declare the dependencies for the Firebase Cloud Messaging
    // When using the BoM, you don't specify versions in Firebase library dependencies
    implementation 'com.google.firebase:firebase-messaging'

}
// Add the following line:
apply plugin: 'com.google.gms.google-services'  // Google Services plugin
<service
    android:name=".java.MyFirebaseMessagingService"
    android:exported="false">
    <intent-filter>
        <action android:name="com.google.firebase.MESSAGING_EVENT" />
    </intent-filter>
</service>
EMOptions options = new EMOptions();
...
EMPushConfig.Builder builder = new EMPushConfig.Builder(this);
// Replace to Your FCM sender id
builder.enableFCM("Your FCM sender id");
// Set pushconfig to EMOptions
options.setPushConfig(builder.build());
// To initialize Easemob IM SDK
EMClient.getInstance().init(this, options);
// After the SDK is initialized
EMPushHelper.getInstance().setPushListener(new EMPushListener() {
    @Override
    public void onError(EMPushType pushType, long errorCode) {
        EMLog.e("PushClient", "Push client occur a error: " + pushType + " - " + errorCode);
    }
    @Override
    public boolean isSupportPush(EMPushType pushType, EMPushConfig pushConfig) {
        // Set whether FCM is supported
        if(pushType == EMPushType.FCM) {
            return GoogleApiAvailabilityLight.getInstance().isGooglePlayServicesAvailable(MainActivity.this)
                        == ConnectionResult.SUCCESS;
        }
        return super.isSupportPush(pushType, pushConfig);
    }
});
// Check whether FCM is supported
if(GoogleApiAvailabilityLight.getInstance().isGooglePlayServicesAvailable(MainActivity.this) != ConnectionResult.SUCCESS) {
    return;
}
FirebaseMessaging.getInstance().getToken().addOnCompleteListener(new OnCompleteListener<String>() {
    @Override
    public void onComplete(@NonNull Task<String> task) {
        if (!task.isSuccessful()) {
            EMLog.d("PushClient", "Fetching FCM registration token failed:"+task.getException());
            return;
        }
        // Get new FCM registration token
        String token = task.getResult();
        EMClient.getInstance().sendFCMTokenToServer(token);
    }
});
public class EMFCMMSGService extends FirebaseMessagingService {
    private static final String TAG = "EMFCMMSGService";

    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        super.onMessageReceived(remoteMessage);
        if (remoteMessage.getData().size() > 0) {
            String message = remoteMessage.getData().get("alert");
            Log.d(TAG, "onMessageReceived: " + message);
        }
    }

    @Override
    public void onNewToken(@NonNull String token) {
        Log.i("MessagingService", "onNewToken: " + token);
        // If you want to send messages to this application instance or
        // manage this apps subscriptions on the server side, send the
        // FCM registration token to your app server.
        if(EMClient.getInstance().isSdkInited()) {
            EMClient.getInstance().sendFCMTokenToServer(token);
        }
    }
}

华为 HMS 推送集成

  1. 华为开发者后台创建应用

在华为开发者后台创建应用,并开启 push 服务,并上传对应的证书指纹,具体可以看下华为官方介绍: 华为 HMS 消息推送服务集成

  1. 上传推送证书

注册完成后,需要在环信即时通讯云控制台上传推送证书,选择你的应用 —> 即时推送 —> 配置证书 —> 添加推送证书 —> 华为,然后输入你在 华为开发者后台 创建的应用信息中的 APP ID 和 SecretKey 以及程序的包名;

  1. 华为推送集成

<!--华为 HMS Config-->
<service android:name=".service.HMSPushService"
    android:exported="false">
    <intent-filter>
        <action android:name="com.huawei.push.action.MESSAGING_EVENT" />
    </intent-filter>
</service>
<!-- huawei push end -->
EMOptions options = new EMOptions();
...
EMPushConfig.Builder builder = new EMPushConfig.Builder(this);
builder.enableHWPush(); 
// Set pushconfig to ChatOptions
options.setPushConfig(builder.build());
// To initialize Agora Chat SDK
EMClient.getInstance().init(this, options);

小米推送集成

环信即时通讯 IM SDK 中已经集成了小米推送(基于 MiPush_SDK_Client_3_6_12.jar)相关逻辑,你还需要完成以下步骤:

  1. 在小米开发者站创建应用

小米开发者站 创建应用,并开启 push 服务,具体可以看下小米官方介绍: 推送服务接入指南

  1. 上传推送证书

注册完成后,需要在环信即时通讯云控制台上传推送证书,选择你的应用 —> 即时推送 —> 配置证书 —> 添加推送证书 —> 小米,然后输入你在 小米开发者站 创建的应用信息中的 App ID 和 Secret Key 以及程序的包名。

  1. 小米推送集成

<!--注:以下三个权限在小米推送 SDK 4.8.0 及以上版本不再依赖-->
<!-- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />-->
<!-- <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />-->
<!-- <uses-permission android:name="android.permission.READ_PHONE_STATE" />-->

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.VIBRATE"/> 
<permission android:name="com.xiaomi.mipushdemo.permission.MIPUSH_RECEIVE"
android:protectionLevel="signature" /> <!--这里 `com.xiaomi.mipushdemo` 改成 app 的包名-->
<uses-permission android:name="com.xiaomi.mipushdemo.permission.MIPUSH_RECEIVE" /><!--这里 `com.xiaomi.mipushdemo` 改成 app 的包名-->
<service
    android:name="com.xiaomi.push.service.XMPushService"
    android:enabled="true"
    android:process=":pushservice" />

<!--注:此 service 必须在小米推送 SDK 3.0.1 版本以后(包括小米推送 SDK 3.0.1 版本)加入-->
<service
    android:name="com.xiaomi.push.service.XMJobService"
    android:enabled="true"
    android:exported="false"
    android:permission="android.permission.BIND_JOB_SERVICE"
    android:process=":pushservice" />

<!--注:com.xiaomi.xmsf.permission.MIPUSH_RECEIVE 这里的包名不能改为 app 的包名-->
<service
    android:name="com.xiaomi.mipush.sdk.PushMessageHandler"
    android:enabled="true"
    android:exported="true" 
    android:permission="com.xiaomi.xmsf.permission.MIPUSH_RECEIVE" />

<!--注:此 service 必须在小米推送 SDK 2.2.5 版本以后(包括小米推送 SDK 2.2.5 版本)加入-->
<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>
<receiver android:name=".common.receiver.MiMsgReceiver">
    <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>
EMOptions options = new EMOptions();
...
EMPushConfig.Builder builder = new EMPushConfig.Builder(this);
builder.enableMiPush(String appId, String appKey); 
// Set pushconfig to ChatOptions
options.setPushConfig(builder.build());
// To initialize Agora Chat SDK
EMClient.getInstance().init(this, options);

OPPO 推送集成

环信即时通讯 IM SDK 中已经集成了 OPPO 推送相关逻辑,你还需要完成以下步骤:

  1. 在 OPPO 开发者后台创建应用
  1. 上传推送证书

- 注册完成后,需要在环信即时通讯云控制台上传推送证书,选择你的应用 —> 即时推送 —> 配置证书 —> 添加推送证书 —> OPPO,然后输入你在 OPPO 开发者后台创建的应用的 appkeymastersecret 以及程序的 包名,MasterSecret 需要到 OPPO 推送平台 - 配置管理 - 应用配置 页面查看。

  1. OPPO 推送集成

<!-- OPPO 推送配置 start -->
<uses-permission android:name="com.coloros.mcs.permission.RECIEVE_MCS_MESSAGE"/>
<uses-permission android:name="com.heytap.mcs.permission.RECIEVE_MCS_MESSAGE"/>
<!-- OPPO 推送配置 end -->
<!-- OPPO 推送配置 start -->
<service
   android:name="com.heytap.msp.push.service.CompatibleDataMessageCallbackService"
   android:permission="com.coloros.mcs.permission.SEND_MCS_MESSAGE">
   <intent-filter>
      <action android:name="com.coloros.mcs.action.RECEIVE_MCS_MESSAGE"/>
   </intent-filter>
</service> <!--兼容 Q 以下版本-->

<service
   android:name="com.heytap.msp.push.service.DataMessageCallbackService"
   android:permission="com.heytap.mcs.permission.SEND_PUSH_MESSAGE">
   <intent-filter>
      <action android:name="com.heytap.mcs.action.RECEIVE_MCS_MESSAGE"/>
      <action android:name="com.heytap.msp.push.RECEIVE_MCS_MESSAGE"/>
   </intent-filter>
</service> <!--兼容 Q 版本-->
<!-- OPPO 推送配置 end -->
EMOptions options = new EMOptions();
...
EMPushConfig.Builder builder = new EMPushConfig.Builder(this);
builder.enableOppoPush(String appKey,String appSecret);
// Set pushconfig to ChatOptions
options.setPushConfig(builder.build());
// To initialize Agora Chat SDK
EMClient.getInstance().init(this, options);
HeytapPushManager.init(context, true);

VIVO 推送集成

环信即时通讯 IM SDK 中已经集成了 VIVO 推送(基于 vivo_push_v2.3.1.jar)相关逻辑,你还需要完成以下步骤:

  1. 在 VIVO 开发者后台创建应用
  1. 上传推送证书

  1. VIVO 推送集成

<!-- VIVO 推送配置 start -->
        <!--VIVO Push SDK 的版本信息-->
        <meta-data
            android:name="sdk_version_vivo"
            android:value="484"/>
        <meta-data
            android:name="local_iv"
            android:value="MzMsMzQsMzUsMzYsMzcsMzgsMzksNDAsNDEsMzIsMzgsMzcsMzYsMzUsMzQsMzMsI0AzNCwzMiwzMywzNywzMywzNCwzMiwzMywzMywzMywzNCw0MSwzNSwzNSwzMiwzMiwjQDMzLDM0LDM1LDM2LDM3LDM4LDM5LDQwLDQxLDMyLDM4LDM3LDMzLDM1LDM0LDMzLCNAMzQsMzIsMzMsMzcsMzMsMzQsMzIsMzMsMzMsMzMsMzQsNDEsMzUsMzIsMzIsMzI" />
        <service
            android:name="com.vivo.push.sdk.service.CommandClientService"
            android:permission="com.push.permission.UPSTAGESERVICE"
            android:exported="true" />
        <activity
            android:name="com.vivo.push.sdk.LinkProxyClientActivity"
            android:exported="false"
            android:screenOrientation="portrait"
            android:theme="@android:style/Theme.Translucent.NoTitleBar" />
        <!--推送配置项-->
        <meta-data
            android:name="com.vivo.push.api_key"
            android:value="开发者自己申请的 appKey" />
        <meta-data
            android:name="com.vivo.push.app_id"
            android:value="开发者自己申请的 appId" />

        <receiver android:name="com.hyphenate.push.platform.vivo.EMVivoMsgReceiver" >
            <intent-filter>
                <!-- 接收 push 消息 -->
                <action android:name="com.vivo.pushclient.action.RECEIVE" />
            </intent-filter>
        </receiver>
        <!-- VIVO 推送配置 end -->
EMOptions options = new EMOptions();
...
EMPushConfig.Builder builder = new EMPushConfig.Builder(this);
builder.enableVivoPush();
// Set pushconfig to ChatOptions
options.setPushConfig(builder.build());
// To initialize Agora Chat SDK
EMClient.getInstance().init(this, options);

VIVO 推送官方文档

魅族推送集成

  1. 在魅族开发者后台创建应用
  1. 上传推送证书

  1. 魅族推送集成

在 app level/build.gradle 中添加依赖。

dependencies{
// 该 aar 托管在 jcenter 中,请确保当前项目已配置 jcenter 仓库。
implementation 'com.meizu.flyme.internet:push-internal:3.7.0@aar'
}
<!-- 魅族推送配置 start-->
    <!-- 兼容 flyme5.0 以下版本,魅族内部集成 pushSDK 必填,不然无法收到消息-->
    <uses-permission android:name="com.meizu.flyme.push.permission.RECEIVE" />
    <permission
        android:name="${applicationId}.push.permission.MESSAGE"
        android:protectionLevel="signature" />
    <uses-permission android:name="${applicationId}.push.permission.MESSAGE" />
    <!-- 兼容 flyme3.0 配置权限-->
    <uses-permission android:name="com.meizu.c2dm.permission.RECEIVE" />
    <permission
        android:name="${applicationId}.permission.C2D_MESSAGE"
        android:protectionLevel="signature" />
    <uses-permission android:name="${applicationId}.permission.C2D_MESSAGE" />
<!-- 魅族推送配置 end-->
<!-- MEIZU 推送配置 start -->
        <receiver android:name="com.hyphenate.push.platform.meizu.EMMzMsgReceiver">
            <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="${applicationId}"></category>
            <   /intent-filter>
        </receiver>
        <!-- MEIZU 推送配置 end -->
EMOptions options = new EMOptions();
...
EMPushConfig.Builder builder = new EMPushConfig.Builder(this);
builder.enableVivoPush();
// Set pushconfig to ChatOptions
options.enableMeiZuPush(String appId,String appKey);
// To initialize Agora Chat SDK
EMClient.getInstance().init(this, options);

4. 设置离线推送

环信 IM 3.9.2 及以上版本对离线消息推送进行了优化。你可以对 app 以及各类型的会话开启和关闭离线推送功能,关闭时可设置关闭时长。

环信 IM 支持你对离线推送功能进行如下配置:

4.1 设置推送通知

为优化用户在处理大量推送通知时的体验,环信 IM 在 app 和会话层面提供了推送通知和免打扰(DND)模式的细粒度选项,如下表所示:

模式

选项

App

会话

推送通知方式

ALL:接收所有离线消息的推送通知。

MENTION_ONLY:仅接收提及消息的推送通知。

NONE:不接收离线消息的推送通知。

免打扰模式

SILENT_MODE_DURATION:在指定的持续时间内不接收推送通知。

SILENT_MODE_INTERVAL:在指定的时间范围内不接收推送通知。

推送通知方式

会话级别的推送通知方式设置优先于 app 级别的设置,未设置推送通知方式的会话默认采用 app 的设置。

例如,假设 app 的推送方式设置为 MENTION_ONLY,而指定会话的推送方式设置为 ALL。你会收到来自该会话的所有推送通知,而对于其他会话来说,你只会收到提及你的消息的推送通知。

免打扰模式

  1. 你可以在 app 级别指定 DND 时长和 DND 时间范围。环信 IM 在这两个时间段内不发送离线推送通知。
  2. 会话仅支持 DND 时长设置;DND 时间范围的设置不生效。

对于 app 和 app 中的所有会话,DND 模式的设置优先于推送通知方式的设置。

例如,假设在 app 级别指定了免打扰时间段,并将指定会话的推送通知方式设置为 ALL。免打扰模式与推送通知方式的设置无关,即在指定的免打扰时间段内,你不会收到任何推送通知。

或者,假设为会话指定了免打扰时间段,而 app 没有任何免打扰设置,并且其推送通知方式设置为 ALL。在指定的免打扰时间段内,你不会收到来自该会话的任何推送通知,而所有其他会话的推送保持不变。

4.1.1 设置 app 的推送通知

你可以调用 setSilentModeForAll 设置 app 级别的推送通知,并通过指定 EMSilentModeParam 字段设置推送通知方式和免打扰模式,如下代码示例所示:

//设置推送通知方式为 `MentionOnly`。
EMSilentModeParam param = new EMSilentModeParam(EMSilentModeParam.EMSilentModeParamType.REMIND_TYPE)
                                .setRemindType(EMPushManager.EMPushRemindType.MENTION_ONLY);

//设置离线推送免打扰时长为 15 分钟。
EMSilentModeParam param = new EMSilentModeParam(EMSilentModeParam.EMSilentModeParamType.SILENT_MODE_DURATION)
                                .setSilentModeDuration(15);

//设置离线推送的免打扰时间段为 8:30 到 15:00。
EMSilentModeParam param = new EMSilentModeParam(EMSilentModeParam.EMSilentModeParamType.SILENT_MODE_INTERVAL)
                                .setSilentModeInterval(new EMSilentModeTime(8, 30), new EMSilentModeTime(15, 0));

//设置 app 的离线推送免打扰模式。
EMClient.getInstance().pushManager().setSilentModeForAll(param, new EMValueCallBack<EMSilentModeResult>(){});
4.1.2 获取 app 的推送通知设置

你可以调用 getSilentModeForAll 获取 app 级别的推送通知设置,如以下代码示例所示:

EMClient.getInstance().pushManager().getSilentModeForAll(new EMValueCallBack<EMSilentModeResult>(){
    @Override
    public void onSuccess(EMSilentModeResult result) {
        //获取 app 的推送通知方式。
        EMPushManager.EMPushRemindType remindType = result.getRemindType();

        //获取 app 的离线推送免打扰过期的 Unix 时间戳。
        long timestamp = result.getExpireTimestamp();

        //获取 app 的离线推送免打扰时间段的开始时间。
        EMSilentModeTime startTime = result.getSilentModeStartTime();
        startTime.getHour();//免打扰时间段的开始时间中的小时数。
        startTime.getMinute();//免打扰时间段的开始时间中的分钟数。

        //获取 app 的离线推送免打扰时间段的结束时间。
        EMSilentModeTime endTime = result.getSilentModeEndTime();
    }

    @Override
    public void onError(int error, String errorMsg) {}
});
4.1.3 设置单个会话的推送通知

你可以调用 setSilentModeForConversation 设置指定会话的推送通知,并通过指定 EMSilentModeParam 字段设置推送通知方式和免打扰模式,如以下代码示例所示:

//设置推送通知方式为 `MENTION_ONLY`。
EMSilentModeParam param = new EMSilentModeParam(EMSilentModeParam.EMSilentModeParamType.REMIND_TYPE)
                                .setRemindType(EMPushManager.EMPushRemindType.MENTION_ONLY);

//设置离线推送免打扰时长为 15 分钟。
EMSilentModeParam param = new EMSilentModeParam(EMSilentModeParam.EMSilentModeParamType.SILENT_MODE_DURATION)
                                .setSilentDuration(15);
//设置会话的离线推送免打扰模式。目前,暂不支持设置会话免打扰时间段。
EMClient.getInstance().pushManager().setSilentModeForConversation(conversationId, conversationType, param, new EMValueCallBack<EMSilentModeResult>(){});
4.1.4 获取单个会话的推送通知设置

你可以调用 getSilentModeForConversation 获取指定会话的推送通知设置,如以下代码示例所示:

EMClient.getInstance().pushManager().getSilentModeForConversation(conversationId, conversationType, new EMValueCallBack<EMSilentModeResult>(){
    @Override
    public void onSuccess(EMSilentModeResult result) {
        //获取会话是否设置了推送通知方式。
        boolean enable = result.isConversationRemindTypeEnabled();
        //检查会话是否设置了推送通知方式。
        if(enable){
            //获取会话的推送通知方式。
            EMPushManager.EMPushRemindType remindType = result.getRemindType();
        }

        //获取会话的离线推送免打扰过期 Unix 时间戳。
        long timestamp = result.getExpireTimestamp();
    }

    @Override
    public void onError(int error, String errorMsg) {}
});
4.1.5 获取多个会话的推送通知设置
  1. 你可以在每次调用中最多获取 20 个会话的设置。
  2. 如果会话继承了 app 设置或其推送通知设置已过期,则返回的字典不包含此会话。

你可以调用 getSilentModeForConversations 获取多个会话的推送通知设置,如以下代码示例所示:

EMClient.getInstance().pushManager().getSilentModeForConversations(conversationList, new EMValueCallBack<Map<String, EMSilentModeResult>>(){
    @Override
    public void onSuccess(Map<String, SilentModeResult> value) {}

    @Override
    public void onError(int error, String errorMsg) {}
});
4.1.6 清除单个会话的推送通知方式的设置

你可以调用 clearRemindTypeForConversation 清除指定会话的推送通知方式的设置。清除后,默认情况下,此会话会继承 app 的设置。

以下代码示例显示了如何清除会话的推送通知方式:

//清除指定会话的推送通知方式设置。清除后,该会话会采取 app 的设置。
EMClient.getInstance().pushManager().clearRemindTypeForConversation(conversationId, conversationType, new EMCallBack(){});

4.2 设置显示属性

4.2.1 设置推送通知的显示属性

你可以调用 updatePushNickname 设置推送通知中显示的昵称,如以下代码示例所示:

//需要异步处理。
EMClient.getInstance().pushManager().updatePushNickname("pushNickname");

你也可以调用 updatePushDisplayStyle 设置推送通知的显示样式,如下代码示例所示:

//设置为简单样式。
EMPushManager.DisplayStyle displayStyle = EMPushManager.DisplayStyle.SimpleBanner;
//需要异步处理。
EMClient.getInstance().pushManager().updatePushDisplayStyle(displayStyle);

DisplayStyle 是枚举类型。

参数 描述
SimpleBanner 显示 “你有一条新消息”。
MessageSummary 显示消息内容。
4.2.2 获取推送通知的显示属性

你可以调用 getPushConfigsFromServer 获取推送通知中的显示属性,如以下代码示例所示:

EMPushConfigs pushConfigs = EMClient.getInstance().pushManager().getPushConfigsFromServer();
//获取推送显示昵称。
String nickname = pushConfigs.getDisplayNickname();
//获取推送通知的显示样式。
EMPushManager.DisplayStyle style = pushConfigs.getDisplayStyle();

4.3 设置推送翻译

如果用户启用 自动翻译 功能并发送消息,SDK 会同时发送原始消息和翻译后的消息。

推送通知与翻译功能协同工作。作为接收方,你可以设置你在离线时希望接收的推送通知的首选语言。如果翻译消息的语言符合你的设置,则翻译消息显示在推送通知中;否则,将显示原始消息。

以下代码示例显示了如何设置和获取推送通知的首选语言:

//设置离线推送的首选语言。
EMClient.getInstance().pushManager().setPreferredNotificationLanguage("en", new EMCallBack(){});

//获取设置的离线推送的首选语言。
EMClient.getInstance().pushManager().getPreferredNotificationLanguage(new EMValueCallBack<String>(){});

4.4 设置推送模板

环信 IM 支持自定义推送通知模板。使用前,你可参考以下步骤在环信即时通讯云管理后台上创建推送模板:

- 登录环信 IM Console,进入首页。 - 在 应用列表 区域中,点击对应 app 的 操作 一栏中的 查看 按钮。 - 在环信 IM 配置页面的左侧导航栏,选择 即时通讯 > 功能配置 > 消息推送 > 模板管理,进入推送模板管理页面。

- 点击 添加推送模板。弹出以下页面,进行参数配置。

在环信即时通讯云管理后台中完成模板创建后,用户可以在发送消息时选择此推送模板作为默认布局,如下代码示例所示:

//下面以文本消息为例,其他类型的消息设置方法相同。
EMMessage message = EMMessage.createSendMessage(EMMessage.Type.TXT);
EMTextMessageBody txtBody = new EMTextMessageBody("消息内容");
message.setTo("6006");
//设置推送模板。设置前需在环信即时通讯云管理后台上创建推送模板。
                    JSONObject pushObject = new JSONObject();
                    JSONArray titleArgs = new JSONArray();
                    JSONArray contentArgs = new JSONArray();
                    try {
                        //设置推送模板名称。
                        pushObject.put("name", "test7");
                        //设置填写模板标题的 value 数组。
                        titleArgs.put("value1");
                        //...
                        pushObject.put("title_args", titleArgs);
                        //设置填写模板内容的 value 数组。
                        contentArgs.put("value1");
                        //...
                        pushObject.put("content_args", contentArgs);
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                    //将推送扩展设置到消息中。
                    message.setAttribute("em_push_template", pushObject);
//设置消息状态回调。
message.setMessageStatusCallback(new EMCallBack() {...});
//发送消息。
EMClient.getInstance().chatManager().sendMessage(message);

5. 解析收到的推送字段

收到的推送字段解释

参数 描述
t 接收者 ID。
f 发送者 ID。
m 消息 ID。
g 群组 ID,当消息是群组消息时,这个值会被赋值。
e 用户自定义扩展。

其中 e 为完全用户自定义扩展,而数据来源为 em_apns_ext 或者 em_apns_ext.extern。

规则如下:

解析 FCM 推送字段

重写 FirebaseMessagingService.onMessageReceived 方法可以在 RemoteMessage 对象中获取自定义扩展:

public class EMFCMMSGService extends FirebaseMessagingService {
    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        super.onMessageReceived(remoteMessage);
        if (remoteMessage.getData().size() > 0) {
            String f = remoteMessage.getData().get("f");
            String t = remoteMessage.getData().get("t");
            String m = remoteMessage.getData().get("m");
            String g = remoteMessage.getData().get("g");
            Object e = remoteMessage.getData().get("e");
        }
    }
}

解析华为推送字段

华为推送字段默认在应用启动页的 onCreate 方法中可以获取到,如下:

public class SplashActivity extends BaseActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {        
        Bundle extras = getIntent().getExtras();
        if (extras != null) {
            String t = extras.getString("t");
            String f = extras.getString("f");
            String m = extras.getString("m");
            String g = extras.getString("g");
            Object e = extras.get("e");
            //handle
        }
    }
}

解析小米推送字段

重写 EMMiMsgReceiver.onNotificationMessageClicked 方法可以在 MiPushMessage 对象中获取自定义扩展:

public class MiMsgReceiver extends EMMiMsgReceiver {

    @Override
    public void onNotificationMessageClicked(Context context, MiPushMessage miPushMessage) {
        String extStr = miPushMessage.getContent();
        JSONObject extras = new JSONObject(extStr);
        if (extras !=null ){
          String t = extras.getString("t");
          String f = extras.getString("f");
          String m = extras.getString("m");
          String g = extras.getString("g");
          Object e = extras.get("e");
          //handle
        }
    }

}

解析 VIVO 推送字段

重写 EMVivoMsgReceiver.onNotificationMessageClicked 方法可以在 UPSNotificationMessage 对象中获取自定义扩展:

public class MyVivoMsgReceiver extends EMVivoMsgReceiver {
    @Override
    public void onNotificationMessageClicked(Context context, UPSNotificationMessage upsNotificationMessage) {
        Map<String, String> map = upsNotificationMessage.getParams();
        if(!map.isEmpty()) {
            String t = map.get("t");
            String f = map.get("f");
            String m = map.get("m");
            String g = map.get("g");
            Object e = map.get("e");
        }
    }
}

解析 OPPO 推送字段

解析方式同华为

解析魅族推送字段

解析方式同华为

更多功能

自定义字段

向推送中添加你自己的业务字段以满足业务需求,比如通过这条推送跳转到某个活动页面(需要应用在前台时)。

// 下面以 TXT 消息为例,IMAGE FILE 等类型的消息设置方法相同。
EMMessage message = EMMessage.createSendMessage(EMMessage.Type.TXT);
EMTextMessageBody txtBody = new EMTextMessageBody("message content");
// 设置要发送的用户 ID。
message.setTo("toChatUsername");
// 设置自定义推送提示。
JSONObject extObject = new JSONObject();
try {
    extObject.put("test1", "test 01");
} catch (JSONException e) {
    e.printStackTrace();
}
// 将推送扩展设置到消息中。
message.setAttribute("em_apns_ext", extObject);
// 设置消息体。
message.addBody(txtBody);
// 设置消息回调。
message.setMessageStatusCallback(new CallBack() {...});
// 发送消息。
EMClient.getInstance().chatManager().sendMessage(message);
参数 描述
txtBody 消息体。
toChatUsername 消息接收方 ID。
em_apns_ext 消息扩展,使用扩展的方式向推送中添加自定义字段,该值为固定值,不可修改。
test1 自定义 key,用户自定义。

应用端解析自定义字段,参见 解析收到的推送字段

自定义显示

自定义显示内容时,你可以随意设置通知时显示的内容。

// 这里只是以 TXT 消息为例,IMAGE FILE 等类型的消息设置方法相同。
EMMessage message = EMMessage.createSendMessage(EMMessage.Type.TXT);
EMTextMessageBody txtBody = new EMTextMessageBody("message content");
// 设置要发送用户的用户 ID。
message.setTo("toChatUsername");
// 设置自定义推送提示。
JSONObject extObject = new JSONObject();
try {
    extObject.put("em_push_title", "custom push title");
    extObject.put("em_push_content", "custom push content");
} catch (JSONException e) {
    e.printStackTrace();
}
// 将推送扩展设置到消息中。
message.setAttribute("em_apns_ext", extObject);
// 设置消息体。
message.addBody(txtBody);
// 设置消息回调。
message.setMessageStatusCallback(new CallBack() {...});
// 发送消息。
EMClient.getInstance().chatManager().sendMessage(message);
参数 描述
toChatUsername 消息接收方 ID。
em_apns_ext 消息扩展,使用扩展的方式向推送中添加自定义字段,该值为固定值,不可修改。
em_push_title 自定义字段 key,用于设置自定义的标题,该值为固定值,不可修改。
em_push_content 自定义字段 key,用于设置自定义的内容,该值为固定值,不可修改。

强制推送

使用该方式设置后,本条消息会忽略接收方的免打扰设置,不论是否处于免打扰时间段都会正常向对方推送通知;

// 下面以 TXT 消息为例,IMAGE FILE 等类型的消息设置方法相同。
EMMessage message = EMMessage.createSendMessage(EMMessage.Type.TXT);
EMTextMessageBody txtBody = new EMTextMessageBody("test");
// 设置要发送用户的用户 ID。
message.setTo("toChatUsername");
// 设置自定义扩展字段。
message.setAttribute("em_force_notification", true);
// 设置消息回调。
message.setMessageStatusCallback(new CallBack() {...});
// 发送消息。
EMClient.getInstance().chatManager().sendMessage(message);
参数 描述
txtBody 消息体。
toChatUsername 消息接收方用户 ID。
em_force_notification 标志是否为强制推送的关键字,不可修改。