实现离线消息推送的过程如下:
MIUI 为深度定制 Android 系统,对于第三方 App 自启动权限管理很严格,默认情况下第三方 App 都不会在系统的自启动白名单内,App 在后台时容易被系统 kill,因此推荐在小米设备上集成小米推送 MiPush,MiPush 是 MIUI 的系统级服务,推送到达率较高。目前,即时通信 IM 仅支持小米推送的通知栏消息。
注意:
- 此指引文档是直接参考小米官方文档所写,若小米推送有变动,请以 小米推送官网文档 为准。
- 如果不需要对小米设备做专门的离线推送适配,可以忽略此章节。
说明:
认证过程大约需要2天左右,请务必提前阅读 小米推送服务启用指南,以免影响您的接入进度。
主包名
、AppID
、AppSecret
信息。说明:
如果您原来已有证书只需变更信息,可以单击【Android平台推送设置】区域的【编辑】进行修改更新。
ID
。说明:
- 即时通信 IM 默认推送的通知标题为
a new message
。- 阅读此小节前,请确保您已经正常集成并使用即时通信 IM SDK。
- 您可以在我们的 demo 里找到小米推送的实现示例,请注意:小米推送版本更新时有可能会有功能调整,若您发现本节内容存在差异,烦请您及时查阅 小米推送官网文档,并将文档信息差异反馈给我们,我们会及时跟进修改。
MiPush_SDK_client_**.jar
库文件。MiPush_SDK_client_**.jar
库文件添加到您项目的libs
目录下,并且在项目中添加引用。添加小米推送必须的权限:
<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"/>
<!--这里的 com.tencent.qcloud.tim.tuikit 改成您的 App 的包名-->
<permission
android:name="com.tencent.qcloud.tim.tuikit.permission.MIPUSH_RECEIVE"
android:protectionLevel="signature" />
<uses-permission android:name="com.tencent.qcloud.tim.tuikit.permission.MIPUSH_RECEIVE" />
<!--这里的 com.tencent.qcloud.tim.tuikit 改成您的 App 的包名-->
配置小米推送服务需要的 service 和 receiver:
<service
android:enabled="true"
android:process=":pushservice"
android:name="com.xiaomi.push.service.XMPushService" />
<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 必须在3.0.1版本以后(包括3.0.1版本)加入-->
<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版本)加入-->
<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>
为了接收消息,您需要自定义一个继承自PushMessageReceiver
类的 BroadcastReceiver,并实现其中的onReceiveRegisterResult
方法,然后将此 receiver 注册到 AndroidManifest.xml 中。
以下为 Demo 中的示例代码:
public class XiaomiMsgReceiver extends PushMessageReceiver {
private static final String TAG = "XiaomiMsgReceiver";
private String mRegId;
@Override
public void onReceiveRegisterResult(Context context, MiPushCommandMessage miPushCommandMessage) {
Log.d(TAG, "onReceiveRegisterResult is called. " + miPushCommandMessage.toString());
String command = miPushCommandMessage.getCommand();
List<String> arguments = miPushCommandMessage.getCommandArguments();
String cmdArg1 = ((arguments != null && arguments.size() > 0) ? arguments.get(0) : null);
Log.d(TAG, "cmd: " + command + " | arg: " + cmdArg1
+ " | result: " + miPushCommandMessage.getResultCode() + " | reason: " + miPushCommandMessage.getReason());
if (MiPushClient.COMMAND_REGISTER.equals(command)) {
if (miPushCommandMessage.getResultCode() == ErrorCode.SUCCESS) {
mRegId = cmdArg1;
}
}
Log.d(TAG, "regId: " + mRegId);
ThirdPushTokenMgr.getInstance().setThirdPushToken(mRegId); // regId 在此处传入,后续推送信息上报时需要使用
ThirdPushTokenMgr.getInstance().setPushTokenToTIM();
}
}
将自定义的 BroadcastReceiver 注册到 AndroidManifest.xml:
<!--这里的 com.tencent.qcloud.uipojo.thirdpush.XiaomiMsgReceiver 修改成您 App 中的完整类名-->
<receiver
android:name="com.tencent.qcloud.uipojo.thirdpush.XiaomiMsgReceiver"
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>
如果您选择启用小米离线推送,需要向小米服务器注册推送服务,通过调用MiPushClient.registerPush
来对小米推送服务进行初始化MiPushClient.registerPush
可在任意地方调用,为了提高注册成功率,小米官方建议在 Application 的onCreate
中调用。
注册成功后,您将在 步骤3.3 自定义的 BroadcastReceiver 的onReceiveRegisterResult
中收到注册结果。其中regId
为当前设备上当前 App 的唯一标识,请记录regId
信息。
以下为 Demo 中的示例代码:
public class DemoApplication extends Application {
private static DemoApplication instance;
@Override
public void onCreate() {
super.onCreate();
//判断是否是在主线程
if (SessionWrapper.isMainProcess(getApplicationContext())) {
/**
* TUIKit的初始化函数
*
* @param context 应用的上下文,一般为对应应用的 ApplicationContext
* @param sdkAppID 您在腾讯云注册应用时分配的 SDKAppID
* @param configs TUIKit 的相关配置项,一般使用默认即可,需特殊配置参考 API 文档
*/
long current = System.currentTimeMillis();
TUIKit.init(this, Constants.SDKAPPID, BaseUIKitConfigs.getDefaultConfigs());
System.out.println(">>>>>>>>>>>>>>>>>>"+(System.currentTimeMillis()-current));
//添加自定初始化配置
customConfig();
System.out.println(">>>>>>>>>>>>>>>>>>"+(System.currentTimeMillis()-current));
if(IMFunc.isBrandXiaoMi()){
// 小米离线推送
MiPushClient.registerPush(this, Constants.XM_PUSH_APPID, Constants.XM_PUSH_APPKEY);
}
if(IMFunc.isBrandHuawei()){
// 华为离线推送
HMSAgent.init(this);
}
if(MzSystemUtils.isBrandMeizu(this)){
// 魅族离线推送
PushManager.register(this, Constants.MZ_PUSH_APPID, Constants.MZ_PUSH_APPKEY);
}
if(IMFunc.isBrandVivo()){
// vivo 离线推送
PushClient.getInstance(getApplicationContext()).initialize();
}
}
instance = this;
}
}
若您需要通过小米推送进行即时通信 IM 消息的推送通知,必须在用户登录成功后通过TIMManager
中的setOfflinePushToken
方法将您托管到即时通信 IM 控制台生成的证书 ID 及小米推送服务端生成的 regId 上报到即时通信 IM 服务端。
注意:
正确上报 regId 与证书 ID 后,即时通信 IM 服务才能将用户与对应的设备信息绑定,从而使用小米推送服务进行推送通知。
以下为 Demo 中的示例代码:
/**
* 我们先定义一些常量信息在 Constants.java
*/
/****** 小米离线推送参数 start ******/
// 使用您在即时通信 IM 控制台上小米推送证书信息里的证书 ID
public static final long XM_PUSH_BUZID = 6666;
// 小米开放平台分配的应用 APPID 及 APPKEY
public static final String XM_PUSH_APPID = "1234512345123451234";
public static final String XM_PUSH_APPKEY = "1234512345123";
/****** 小米离线推送参数 end ******/
/**
* 在 ThirdPushTokenMgr.java 中对推送的证书 ID 及设备信息进行上报操作
*/
public class ThirdPushTokenMgr {
private static final String TAG = "ThirdPushTokenMgr";
private String mThirdPushToken;
public static ThirdPushTokenMgr getInstance () {
return ThirdPushTokenHolder.instance;
}
private static class ThirdPushTokenHolder {
private static final ThirdPushTokenMgr instance = new ThirdPushTokenMgr();
}
public void setThirdPushToken(String mThirdPushToken) {
this.mThirdPushToken = mThirdPushToken; // regId 在此处传值,结合上文自定义 BroadcastReciever 类文档说明
}
public void setPushTokenToTIM(){
String token = ThirdPushTokenMgr.getInstance().getThirdPushToken();
if(TextUtils.isEmpty(token)){
QLog.i(TAG, "setPushTokenToTIM third token is empty");
return;
}
TIMOfflinePushToken param = null;
if(IMFunc.isBrandXiaoMi()){ // 判断厂商品牌,根据不同厂商选择不同的推送服务
param = new TIMOfflinePushToken(Constants.XM_PUSH_BUZID, token);
}else if(IMFunc.isBrandHuawei()){
param = new TIMOfflinePushToken(Constants.HW_PUSH_BUZID, token);
}else if(IMFunc.isBrandMeizu()){
param = new TIMOfflinePushToken(Constants.MZ_PUSH_BUZID, token);
}else if(IMFunc.isBrandOppo()){
param = new TIMOfflinePushToken(Constants.OPPO_PUSH_BUZID, token);
}else if(IMFunc.isBrandVivo()){
param = new TIMOfflinePushToken(Constants.VIVO_PUSH_BUZID, token);
}else{
return;
}
TIMManager.getInstance().setOfflinePushToken(param, new TIMCallBack() {
@Override
public void onError(int code, String desc) {
Log.d(TAG, "setOfflinePushToken err code = " + code);
}
@Override
public void onSuccess() {
Log.d(TAG, "setOfflinePushToken success");
mIsTokenSet = true;
}
});
}
}
成功上报证书 ID 及 regId 后,即时通信 IM 服务端会在该设备上的即时通信 IM 用户 logout 之前、App 被 kill 之后将消息通过小米推送通知到用户端。
说明:
- 小米推送并非100%必达。
- 小米推送可能会有一定延时,通常与 App 被 kill 的时机有关,部分情况下与小米推送服务有关。
- 若即时通信 IM 用户已经 logout 或被即时通信 IM 服务端主动下线(例如在其他端登录被踢等情况),则该设备上不会再收到消息推送。
您可以选择点击通知栏消息后打开应用、打开网页或打开应用内指定界面。
设置为点击通知栏消息打开应用时,会回调小米的 onNotificationMessageClicked 方法,App 可以在此方法中自行处理打开应用。
您需要在 添加证书 时选择【打开网页】并输入以http://
或https://
开头的网址,例如https://www.tencentcloud.com/document/product/269?from_cn_redirect=1
。
在 manifest 中配置需要打开的 Activity 的intent-filter
,示例代码如下:
<activity
android:name="com.tencent.qcloud.tim.demo.chat.ChatActivity"
android:launchMode="singleTask"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustResize|stateHidden">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<data
android:host="com.tencent.qcloud.tim"
android:path="/detail"
android:scheme="pushscheme" />
</intent-filter>
</activity>
获取 intent URL,方式如下:
Intent intent = new Intent(this, ChatActivity.class);
intent.setData(Uri.parse("pushscheme://com.tencent.qcloud.tim/detail"));
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
String intentUri = intent.toUri(Intent.URI_INTENT_SCHEME);
Log.i(TAG, "intentUri = " + intentUri);
// 打印结果
intent://com.tencent.qcloud.tim/detail#Intent;scheme=pushscheme;launchFlags=0x4000000;component=com.tencent.qcloud.tim.tuikit/com.tencent.qcloud.tim.demo.chat.ChatActivity;end
在 添加证书 时选择【打开应用内指定界面】并输入上述打印结果。
添加证书 时设置【点击通知后】为【打开应用】或【打开应用内指定界面】操作才支持透传自定义内容。
在发消息前设置每条消息的通知栏自定义内容。
Android 端示例:
String extContent = "ext content";
TIMMessageOfflinePushSettings settings = new TIMMessageOfflinePushSettings();
settings.setExt(extContent.getBytes());
timMessage.setOfflinePushSettings(settings);
mConversation.sendMessage(false, timMessage, callback);
服务端示例请参见 OfflinePushInfo 的格式示例
若 添加证书 时设置【点击通知后】的操作为【打开应用】,当点击通知栏的消息时,会触发小米推送 SDK 的 onNotificationMessageClicked(Context context, MiPushMessage miPushMessage)
回调,自定义内容可以从 miPushMessage
中获取。
Map extra = miPushMessage.getExtra();
String extContent = extra.get("ext");
若 添加证书 时设置【点击通知后】的操作为【打开应用内指定界面】,封装消息的 MiPushMessage
对象通过 Intent
传到客户端,客户端在相应的 Activity
中获取自定义内容。
Bundle bundle = getIntent().getExtras();
MiPushMessage miPushMessage = (MiPushMessage)bundle.getSerializable(PushMessageHelper.KEY_MESSAGE);
Map extra = miPushMessage.getExtra();
String extContent = extra.get("ext");
如果您的应用使用了混淆,为了防止小米离线推送功能异常,您需要 keep 自定义的 BroadcastReceiver,参考添加以下混淆规则:
说明:
以下代码为小米官方示例,请根据实际情况修改后再使用。
# 请将 com.tencent.qcloud.tim.demo.thirdpush.XiaomiMsgReceiver 改成您 App 中定义的完整类名
-keep com.tencent.qcloud.tim.demo.thirdpush.XiaomiMsgReceiver {*;}
# 如果编译使用的 Android 版本是23,添加这个可以防止一个误报的 warning 导致无法成功编译
-dontwarn com.xiaomi.push.**
目前小米推送不支持自定义的提示音。
本页内容是否解决了您的问题?