当app在后台运行时环信IM SDK默认通过一个后台服务保持一条连接环信服务器的长连接,但Android为了解决系统待机性能差的问题,随着Android版本的升级逐渐禁止了app级别的后台服务的运行.所以在一些版本比较高的Android系统上会有接收不到消息的情况.为了提高消息的到达率,我们SDK增加了对第三方推送服务的支持,包括小米推送,华为推送,Google FCM推送.
建议:如果你的App有海外使用场景,建议开启FCM推送;由于各推送使用条件不同,建议尽可能同时支持小米和华为推送。
证书名称必须与Android终端设备上传的证书名称一致
SDK 3.4.2 版本开始默认优先使用FCM推送,在一些带Google Play Service的华为设备上,开发者可通过设置EMOptions#setUseFCM(false)关闭FCM推送的使用,来达到使用华为推送的目的。
1.登录Firebase管理后台
2.在Firebase欢迎界面点击 Add Project,输入相应内容并点击 Create Project。
3.在Firebase欢迎界面选择 Add Firebase to your Android App。
4.选择应用类型后需要输入包名、项目昵称、SHA-1,然后点击 Register App。
5.进入引导页,如下图,点击按钮下载google-services.json文件到本地。注意该json文件在Android项目中的放置位置。
6.跳过引导页,点击Cloud Messaging tab页,复制Server Key和Sender ID。
7.登录环信管理后台,选择你的应用—选择推送证书—新增证书,证书的名称要求填上方复制Sender ID,证书秘钥填写上方复制的Server Key。
1.添加Google Play Service相关依赖库
用于检查设备是否支持Google FCM推送,该步骤在FCM官方集成文档上不存在,由于国内特殊的使用环境,所以我们增加了该配置用于辅助检测
。
把compile 'com.google.android.gms:play-services-base:11.4.0
'该行配置添加到项目相应的build.gradle文件中,SDK demo中的配置在easeui/build.gradle中,如下:
dependencies {
// 添加此行
compile 'com.google.android.gms:play-services-base:11.4.0'
}
注意:Google推送相关依赖库版本必须对应(该文档中均为:11.4.0),否则可能会出现类冲突的错误。
2.在project-level的build.gradle中添加FCM相关库文件配置:
buildscript {
repositories {
jcenter()
}
dependencies {
// 添加此行
classpath 'com.google.gms:google-services:3.1.1'
}
}
allprojects {
repositories {
// 添加此行
maven { url 'https://maven.google.com' }
}
}
3.在app-level的build.gradle中添加FCM相关库文件配置:
dependencies {
// 添加此行,Google Firebase cloud messaging
compile 'com.google.firebase:firebase-messaging:11.4.0'
}
// 此行添加在文件末尾
apply plugin: 'com.google.gms.google-services'
注意:Google推送相关依赖库版本必须对应(该文档中均为:11.4.0),否则可能会出现类冲突的错误。
4.放置下载的google-services.json在app-level的根目录下
5.实现一个继承自FirebaseInstanceIdService的自定义service,该类用于监听FCM token的创建和更新。一个设备对应一个FCM token,该token用于服务端向该设备推送消息,所以该token创建或更新后需及时上传至环信服务器。
自定义FirebaseInstanceIdService:
public class EMFCMTokenRefreshService extends FirebaseInstanceIdService {
private static final String TAG = "FCMTokenRefreshService";
@Override
public void onTokenRefresh() {
super.onTokenRefresh();
String token = FirebaseInstanceId.getInstance().getToken();
Log.i(TAG, "onTokenRefresh: " + token);
// Important, send the fcm token to the server
EMClient.getInstance().sendFCMTokenToServer(token);
}
}
AndroidManifest.xml:
<service android:name=".fcm.EMFCMTokenRefreshService">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
</intent-filter>
</service>
6.实现一个继承自FirebaseMessagingService的自定义service,该类用于FCM在后台进行接收应用推送消息的处理。并把该service注册到AndroidManifest.xml中。
自定义FirebaseMessagingService:
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.i(TAG, "onMessageReceived: " + message);
}
}
}
AndroidManifest.xml:
<service android:name=".fcm.EMFCMMSGService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
7.通过EMOptions#setUseFCM(true)接口设置允许使用FCM推送,SDK会进行FCM推送条件的检查,并在FCM推送条件满足的情况下使用FCM推送。接口使用可参考Demo中的DemoHelper。
8.通过EMOptions#setFCMNumber(String SenderID)接口设置证书名称(注意必须与通过环信后台设置的证书名称保持一致)。接口使用可参考Demo中的DemoHelper。
为了确保推送服务的成功集成,可按如下步骤进行测试,
通过 设置→应用→强行停止 结束app进程,app无法接收到FCM推送,详情请查阅Google官方对该操作的解释
。)首先就是去华为开发者后台创建应用,并开启 push 服务,并上传对应的证书指纹,具体可以看下华为官方介绍: 华为HMS消息推送服务集成
为了方便用户自己升级华为推送相关sdk,环信 SDK 在3.4.x
之后的版本中将华为推送的集成从SDK
中转移到应用层
,SDK提供上传华为推送token的接口供用户调用,方便华为推送升级时用户自行升级,以后的版本就需要开发者自己去集成华为推送相关功能,然后调用下边的方法将 token 发送到环信服务器:
// 上传 token 方法,token 是通过广播接收器接收到的
EMClient.getInstance().sendHMSPushTokenToServer("华为appId", "注册华为的 token");
PS:
需要注意,此方法必须是登录成功后才能调用,所以请求华为 token 需要放在登录成功之后,所以我们请求华为推送 token 一般放在 MainActivity 类中,环信 IM 的 Demo也已经集成了华为最新推送 SDK,开发者也可以参考 demo 进行集成,token 的获去就是在广播接收器中,Demo 中有实现HMSPushReceiver
类,可以看下 demo 的代码
这是华为官方集成文档,开发者可以自己根据华为官方文档进行集成华为推送
华为消息推送服务集成官方文档
Demo 中将华为的 HMSAgent 做成了一个 module 进行引用(这里没有对华为 HMSAgent 进行任何封装和修改
),开发者可以直接进行使用,也可以直接下载华为官方最新的HMSAgent
自己进行集成,如果使用 demo 中的 module 需要修改以下几个地方:
<application>
<!-- 接入HMSSDK 需要注册的appid参数。value的值中“10492024”用实际申请的appid替换,来源于开发者联盟网站应用的权益详情。格式 android:value="appid=xxxxxx"-->
<meta-data
android:name="com.huawei.hms.client.appid"
android:value="appid=10492024" />
<!-- 接入HMSSDK 需要注册的provider,authorities 一定不能与其他应用一样,所以这边 com.hyphenate.chatuidemo 要替换上您应用的包名-->
<provider
android:name="com.huawei.hms.update.provider.UpdateProvider"
android:authorities="com.hyphenate.chatuidemo.hms.update.provider"
android:exported="false"
android:grantUriPermissions="true" />
<!-- 接入HMSSDK 需要注册的provider,authorities 一定不能与其他应用一样,所以这边 com.hyphenate.chatuidemo 要替换上您应用的包名-->
<provider
android:name="com.huawei.updatesdk.fileprovider.UpdateSdkFileProvider"
android:authorities="com.hyphenate.chatuidemo.updateSdk.fileProvider"
android:exported="false"
android:grantUriPermissions="true"/>
...
</application>
Demo在集成华为推送时将调用华为推送的几个方法都放在了HMSPushHelper
类中,开发者可以进行参考使用
配置完这些之后,在满足条件的华为设备
上就可以使用华为推送接收离线推送通知了;
这里的满足条件是指:华为设备必须安装2.6.+以上的华为移动服务,以及开启当前 app 的自启动权限
;
当开发者做完这些之后如果在华为设备上还是收不到推送,可以看下控制台的输出,或者环信 sdcard 上保存的日志,是否有一下日志输出:
// 当设备的华为移动服务版本比较低的时候,无法启用华为推送,会有以下输出
huawei mobile services is not available. please upgrade
// 当注册 token 时,华为开发者后台证书不对应,或者没有开通 Push 服务,当所有的都确认没问题后,如果还是有这样的问题,这个需要联系华为技术支持查看下是否生效
hms service connection suspended. error: 6xxx 或 9xxxxxxxx
后边的 error 为华为官方错误码,更多错误码请参考华为官方错误表:表3-1 HMS 通用错误码及处理方式
使用第三方推送时需要在退出登录时解绑设备 token,调用EMClient#getInstance()#logout(true)
或者EMClient#getInstance()#logout(true,callback)
方法,如果是被踢的情况下,则要求设置为 false。
用户可以在消息扩展中增加特定的字段来实现消息的推送配置。
EMMessage message = EMMessage.createSendMessage(EMMessage.Type.TXT);
EMTextMessageBody txtBody = new EMTextMessageBody("test");
message.setTo("6006");
// 设置自定义扩展字段
message.setAttribute("em_ignore_notification", true);
// 设置消息回调
message.setMessageStatusCallback(new EMCallBack() {...});
// 发送消息
EMClient.getInstance().chatManager().sendMessage(message);
EMMessage message = EMMessage.createSendMessage(EMMessage.Type.TXT);
EMTextMessageBody txtBody = new EMTextMessageBody("test");
message.setTo("6006");
// 设置自定义扩展字段
message.setAttribute("em_force_notification", true);
// 设置消息回调
message.setMessageStatusCallback(new EMCallBack() {...});
// 发送消息
EMClient.getInstance().chatManager().sendMessage(message);
// 这里只是一 TXT 消息为例,IMAGE FILE 等类型的消息设置方法相同
EMMessage message = EMMessage.createSendMessage(EMMessage.Type.TXT);
EMTextMessageBody txtBody = new EMTextMessageBody("消息内容");
message.setTo("6006");
// 设置自定义推送提示
JSONObject extObject = new JSONObject();
try {
extObject.put("em_push_name", "离线推送标题");
extObject.put("em_push_content", "离线推送内容部分");
} catch (JSONException e) {
e.printStackTrace();
}
// 将推送扩展设置到消息中
message.setAttribute("em_apns_ext", extObject);
// 设置消息回调
message.setMessageStatusCallback(new EMCallBack() {...});
// 发送消息
EMClient.getInstance().chatManager().sendMessage(message);
您可以登录环信管理后台,在应用列表中选中相应的APP,再点击“IM用户”,在用户列表中搜索收不到推送的用户,找到相应的用户后,点击右侧的“操作”下拉菜单,再点击“测试离线推送”,系统会推送一条测试消息给这个用户,如果出现了问题会做出对应的错误原因提示来协助您排查问题,可能的错误提示有: