常见错误
前期 SDK 初始化工作
Q:环信的 AppKey 可以写到代码里面吗?
A:不可以,必须写在 AndroidManifest.xml 中,因为在 SDK 中取 AppKey 是指定到 AndroidManifest.xml 的。
Q:SDK 的初始化可以不写在 application 里面吗?
A:不允许,要写在 application 的 oncreate 方法里面,以保证初始化成功。(写在其他地方可能会造成自踢现象)
Q:自踢现象是什么?什么情况下会有?
A:自踢现象的产生为多次调用环信的初始化方法,可以通过环信 log 内搜索 ‘conflict’ 关键字,如果存在且没有在其他手机登录,则认为是自踢现象。
环信在手机端是单点登录的(也就是说同时只能在一台设备(手机)登录),需要添加在其他地方登录的监听,如果在其他地方登录,log 日志中即有 conflict 关键字。
严重的后果是:自己刚登录后就会收到被踢的回调。因此要多加注意此问题。
怎样避免:正确按照环信 demo 或者文档所写,在 application 中初始化,添加第三方服务启动 application 的检测。上线前测试和查看日志。
通过 adb 获取环信 log 的方法:
adb pull /sdcard/Android/data/your packagename/your appkey/log
your packagename:为你APP的包名,your appkey:为你在环信申请的 AppKey
登录
Q:SDK 默认是自动登录,我想手动登录,可以取消吗?
A:可以,只要调用 EMChat.getInstance().setAutoLogin(false) 放在 SDK 初始化的前边就行。
注:如果要实现每次手动登录,一定要关掉自动登录。
被踢下线
如果有这种 conflict 标志的日志出现那就是被踢了。
- 确认一下是否在 application 里面加了下面那个判断;
- 确认是否在成功登录以后调了创建用户的方法(不允许在登录以后还去调创建账户的方法)。
上图报的错多数情况因为判断没有加,参照 Demo 的 application 里面把下面这段代码加上:
appContext = this;
int pid = android.os.Process.myPid();
String processAppName = getAppName(pid);
// 如果APP启用了远程的service,此application:onCreate会被调用2次
// 为了防止环信SDK被初始化2次,加此判断会保证SDK被初始化1次
// 默认的app会在以包名为默认的process name下运行,如果查到的process name不是app的process name就立即返回
if (processAppName == null ||!processAppName.equalsIgnoreCase("com.easemob.chatuidemo")) {
Log.e(TAG, "enter the service process!");
//"com.easemob.chatuidemo"为Demo的包名,换到自己项目中要改成自己包名
// 则此application::onCreate 是被service调用的,直接返回
return;
}
private String getAppName(int pID) {
String processName = null;
ActivityManager am = (ActivityManager)this.getSystemService(ACTIVITY_SERVICE);
List l = am.getRunningAppProcesses();
Iterator i = l.iterator();
PackageManager pm = this.getPackageManager();
while (i.hasNext()) {
ActivityManager.RunningAppProcessInfo info = (ActivityManager.RunningAppProcessInfo) (i.next());
try {
if (info.pid == pID) {
CharSequence c = pm.getApplicationLabel(pm.getApplicationInfo(info.processName, PackageManager.GET_META_DATA));
// Log.d("Process", "Id: "+ info.pid +" ProcessName: "+
// info.processName +" Label: "+c.toString());
// processName = c.toString();
processName = info.processName;
return processName;
}
} catch (Exception e) {
// Log.d("Process", "Error>> :"+ e.toString());
}
}
return processName;
}
群组
未登录情况下群组是获取不到的,本地数据库中如果没有存储群组列表会从服务器获取,就调 EMGroupManager.getInstance().getGroupsFromServer(),如果本地已经存储了群组列表就要先调 EMGroupManager.getInstance().loadAllGroups() 从本地 db 获取群组放到内存中,在内存中获取群组列表调 EMGroupManager.getInstance().getAllGroups()
Q:屏蔽群组出现 forbidden(403) Owner privileges required 是什么原因?
A:检查你是否已经对该群组做了屏蔽,再次调用屏蔽的方法则会返回上述问题。
聊天记录存储
未登录情况下聊天记录是获取不到的,登录后先调用 EMChatManager.getInstance().loadAllConversations() 放到内存中,从内存中在调用 EMChatManager.getInstance().getAllConversations() 去获取所有会话,获取单个会话 EMChatManager.getInstance().getConversation(username)。
注册用户失败
createAccountOnServer 这个是注册用户的方法,如果出现了 not-allowed(405) 错误,那就让他去 http://console.easemob.com/ 找,把那个用户注册模式切换成开放模式,如下图:
消息透传
Q:注册了接收透传消息的广播,对方发送透传消息成功了,为什么收不到透传消息?
A:检查一下是否在注册完广播以后加上 EMChat.getInstance().setAppInited()