目录

Android SDK 基础功能


SDK 中相关异步/同步处理方法介绍

取本地log

以Demo为例,获取本地的log

adb pull /sdcard/Android/data/com.hyphenate.chatuidemo/easemob-demo#chatdemoui/core_log/easemob.log

其中com.hyphenate.chatuidemo是packagename, easemob-demo#chatdemoui是appkey,需要替换成自己对应的路径。

初始化 SDK

要求在 application 的oncreate方法中做初始化,初始化的时候需要传入设置好的 options。

EMOptions options = new EMOptions();
// 默认添加好友时,是不需要验证的,改成需要验证
options.setAcceptInvitationAlways(false);
// 是否自动将消息附件上传到环信服务器,默认为True是使用环信服务器上传下载,如果设为 false,需要开发者自己处理附件消息的上传和下载
options.setAutoTransferMessageAttachments(true);
// 是否自动下载附件类消息的缩略图等,默认为 true 这里和上边这个参数相关联
options.setAutoDownloadThumbnail(true);
...
//初始化
EMClient.getInstance().init(applicationContext, options);
//在做打包混淆时,关闭debug模式,避免消耗不必要的资源
EMClient.getInstance().setDebugMode(true);

注:如果你的 APP 中有第三方的服务启动,请在初始化 SDK(EMClient.getInstance().init(applicationContext, options))方法的前面添加以下相关代码(相应代码也可参考 Demo 的 application),使用 EaseUI 库的就不用理会这个。

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(appContext.getPackageName())) {
    Log.e(TAG, "enter the service process!");
    
    // 则此application::onCreate 是被service 调用的,直接返回
    return;
}

如何获取processAppName请参考以下方法。

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) {
				processName = info.processName;
				return processName;
			}
		} catch (Exception e) {
			// Log.d("Process", "Error>> :"+ e.toString());
		}
	}
	return processName;
}

注册

注册模式分两种,开放注册和授权注册。只有开放注册时,才可以客户端注册。

注册用户名会自动转为小写字母,所以建议用户名均以小写注册。

强烈建议开发者通过后台调用 REST 接口去注册环信 ID,客户端注册方法不建议使用。

//注册失败会抛出HyphenateException
EMClient.getInstance().createAccount(username, pwd);//同步方法

登录

注意:

EMClient.getInstance().login(userName,password,new EMCallBack() {//回调
	@Override
	public void onSuccess() {
		EMClient.getInstance().groupManager().loadAllGroups();
		EMClient.getInstance().chatManager().loadAllConversations();
	        Log.d("main", "登录聊天服务器成功!");		
	}

	@Override
	public void onProgress(int progress, String status) {

	}

	@Override
	public void onError(int code, String message) {
		Log.d("main", "登录聊天服务器失败!");
	}
});

使用token登录

SDK也支持使用token登录,比如在app的服务器获取token,然后交给应用使用token登录。

请注意: 使用token 登录时需要处理token过期的问题,比如在每次登录时更新token 等机制。

public void loginWithToken(String username, String token, final EMCallBack callback)

自动登录

即首次登录成功后,不需要再次调用登录方法,在下次 APP 启动时,SDK 会自动为您登录。并且如果您自动登录失败,也可以读取到之前的会话信息(以上情况是在未调用登出的情况下实现的)。

SDK 中自动登录属性默认是 true 打开的,如果不需要自动登录,在初始化 SDK 初始化的时候,调用options.setAutoLogin(false);设置为 false 关闭。

自动登录在以下几种情况下会被取消:

退出登录

同步方法

EMClient.getInstance().logout(true);

异步方法

EMClient.getInstance().logout(true, new EMCallBack() {
            
	@Override
	public void onSuccess() {
	    // TODO Auto-generated method stub
	    
	}
	
	@Override
	public void onProgress(int progress, String status) {
	    // TODO Auto-generated method stub
	    
	}
	
	@Override
	public void onError(int code, String message) {
	    // TODO Auto-generated method stub
	    
	}
});

如果集成了FCM等第三方推送,方法里第一个参数需要设为true,这样退出的时候会解绑设备token,否则可能会出现退出了,还能收到消息的现象。
有时候可能会碰到网络问题而解绑失败,app处理时可以弹出提示框让用户选择,是否继续退出(弹出框提示继续退出能收到消息的风险),如果用户选择继续退出,传false再调用logout方法退出成功;
当然也可以失败后还是返回退出成功,然后在后台起个线程不断调用logout方法直到成功,这样有个风险是:用户kill了app,然后网络恢复,用户还是会继续收到消息。

还有一个需要注意的是:如果调用异步退出方法,在收到onsucess的回调后才去调用IM相关的方法,比如login

用户被封禁后的提示

IM管理后台可以对用户进行管理,例如可以在后台封禁用户。 用户被封禁后会提示SDK登录会返回 SERVER_SERVING_DISABLED(305), 可以根据用户这个返回值来进行相应的提示或者处理。

需要注意的是app整个被禁用时也会返回上述错误码,由于app一般不会被禁用,所以可以用来提示用户被封禁。

注册连接状态监听

当掉线时,Android SDK 会自动重连,无需进行任何操作,通过注册连接监听来知道连接状态。

//注册一个监听连接状态的listener
EMClient.getInstance().addConnectionListener(new MyConnectionListener());

//实现ConnectionListener接口
private class MyConnectionListener implements EMConnectionListener {
    @Override
	public void onConnected() {
	}
	@Override
        public void onDisconnected(int error) {
            EMLog.d("global listener", "onDisconnect" + error);
            if (error == EMError.USER_REMOVED) {
                onUserException(Constant.ACCOUNT_REMOVED);
            } else if (error == EMError.USER_LOGIN_ANOTHER_DEVICE) {
                onUserException(Constant.ACCOUNT_CONFLICT);
            } else if (error == EMError.SERVER_SERVICE_RESTRICTED) {
                onUserException(Constant.ACCOUNT_FORBIDDEN);
            } else if (error == EMError.USER_KICKED_BY_CHANGE_PASSWORD) {
                onUserException(Constant.ACCOUNT_KICKED_BY_CHANGE_PASSWORD);
            } else if (error == EMError.USER_KICKED_BY_OTHER_DEVICE) {
                onUserException(Constant.ACCOUNT_KICKED_BY_OTHER_DEVICE);
            }
        }
}


 /**
     * user met some exception: conflict, removed or forbidden, goto login activity
     */
    protected void onUserException(String exception){
        EMLog.e(TAG, "onUserException: " + exception);
        Intent intent = new Intent(appContext, MainActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.addFlags(Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
        intent.putExtra(exception, true);
        appContext.startActivity(intent);

        showToast(exception);
    }