目录

Android SDK 基础功能


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

具体是异步还是同步,也可以参考相关文档介绍的方法,每一个方法后边都有注释信息提示开发者,未注释的则认为同步执行。

注:对于没有回调的异步方法执行过程,是通过 try catch 来判断异步方法执行成功或者失败。

初始化 SDK

要求在 application 的 oncreate 方法中做初始化。

EMChat.getInstance().init(applicationContext);

/**
 * debugMode == true 时为打开,SDK会在log里输入调试信息
 * @param debugMode
 * 在做代码混淆的时候需要设置成false
 */
EMChat.getInstance().setDebugMode(true);//在做打包混淆时,要关闭debug模式,避免消耗不必要的资源

注:如果你的 APP 中有第三方的服务启动,请在初始化 SDK(EMChat.getInstance().init(applicationContext))方法的前面添加以下相关代码(相应代码也可参考 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;
}

如何获取 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) {
				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;
}

注册

注册模式分两种,开放注册和授权注册。可以登录环信管理后台,在“应用概况”页,切换注册模式。

注册用户名会自动转为小写字母,所以建议用户名均以小写注册(强烈建议开发者通过后台调用 REST API 去注册环信 ID,客户端注册方法不提倡使用)。

new Thread(new Runnable() {
    public void run() {
      try {
         // 调用sdk注册方法
         EMChatManager.getInstance().createAccountOnServer(username, pwd);
      } catch (final EaseMobException e) {
      //注册失败
		int errorCode=e.getErrorCode();
		if(errorCode==EMError.NONETWORK_ERROR){
		    Toast.makeText(getApplicationContext(), "网络异常,请检查网络!", Toast.LENGTH_SHORT).show();
		}else if(errorCode==EMError.USER_ALREADY_EXISTS){
		    Toast.makeText(getApplicationContext(), "用户已存在!", Toast.LENGTH_SHORT).show();
		}else if(errorCode==EMError.UNAUTHORIZED){
			Toast.makeText(getApplicationContext(), "注册失败,无权限!", Toast.LENGTH_SHORT).show();
		}else{
			Toast.makeText(getApplicationContext(), "注册失败: " + e.getMessage(), Toast.LENGTH_SHORT).show();
      }
   }
}).start();

登录

登录聊天服务器。

注意:登录成功后需要调用 EMGroupManager.getInstance().loadAllGroups();EMChatManager.getInstance().loadAllConversations();

以上两个方法是为了保证进入主页面后本地会话和群组都 load 完毕。

另外如果登录过,APP 长期在后台再进的时候也可能会导致加载到内存的群组和会话为空,可以在主页面的 oncreate 里也加上这两句代码,当然,更好的办法应该是放在程序的开屏页,可参考 Demo 的 SplashActivity。

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

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

	}

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

自动登录

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

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

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

重连

当掉线时,Android SDK 会自动重连,无需进行任何操作。

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

//实现ConnectionListener接口
private class MyConnectionListener implements EMConnectionListener {
    @Override
	public void onConnected() {
	//已连接到服务器
	}
	@Override
	public void onDisconnected(final int error) {
		runOnUiThread(new Runnable() {

			@Override
			public void run() {
				if(error == EMError.USER_REMOVED){
					// 显示帐号已经被移除
				}else if (error == EMError.CONNECTION_CONFLICT) {
					// 显示帐号在其他设备登录
				} else {
				if (NetUtils.hasNetwork(MainActivity.this))
					//连接不到聊天服务器
				else
					//当前网络不可用,请检查网络设置
				}
			}
		});
	}
}

退出聊天登录

//此方法为同步方法
EMChatManager.getInstance().logout();
//此方法为异步方法
EMChatManager.getInstance().logout(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
	    
	}
});

注册监听

监听事件注册(建议做成全局监听)

注册接收新消息的监听广播

//只有注册了广播才能接收到新消息,目前离线消息,在线消息都是走接收消息的广播(离线消息目前无法监听,在登录以后,接收消息广播会执行一次拿到所有的离线消息)
NewMessageBroadcastReceiver msgReceiver = new NewMessageBroadcastReceiver();
IntentFilter intentFilter = new IntentFilter(EMChatManager.getInstance().getNewMessageBroadcastAction());
intentFilter.setPriority(3);
registerReceiver(msgReceiver, intentFilter);

private class NewMessageBroadcastReceiver extends BroadcastReceiver {
	@Override
	public void onReceive(Context context, Intent intent) {
	    // 注销广播
		abortBroadcast();

		// 消息id(每条消息都会生成唯一的一个id,目前是SDK生成)
		String msgId = intent.getStringExtra("msgid");
		//发送方
		String username = intent.getStringExtra("from");
		// 收到这个广播的时候,message已经在db和内存里了,可以通过id获取message对象
		EMMessage message = EMChatManager.getInstance().getMessage(msgId);
		EMConversation	conversation = EMChatManager.getInstance().getConversation(username);
		// 如果是群聊消息,获取到group id
		if (message.getChatType() == ChatType.GroupChat) {
			username = message.getTo();
		}
		if (!username.equals(username)) {
			// 消息不是发给当前会话,return
			return;
		}
	}
}

注册接收 ack 回执消息的 BroadcastReceiver

EMChatManager.getInstance().getChatOptions().setRequireAck(flag)
//如果用到已读的回执需要把这个flag设置成true

IntentFilter ackMessageIntentFilter = new IntentFilter(EMChatManager.getInstance().getAckMessageBroadcastAction());
ackMessageIntentFilter.setPriority(3);
registerReceiver(ackMessageReceiver, ackMessageIntentFilter);

private BroadcastReceiver ackMessageReceiver = new BroadcastReceiver() {
	
	@Override
	public void onReceive(Context context, Intent intent) {
		abortBroadcast();
		String msgid = intent.getStringExtra("msgid");
		String from = intent.getStringExtra("from");
		EMConversation conversation = EMChatManager.getInstance().getConversation(from);
		if (conversation != null) {
			// 把message设为已读
			EMMessage msg = conversation.getMessage(msgid);
			if (msg != null) {
				msg.isAcked = true;
			}
		}
				
	}
};

注册一个消息送达的 BroadcastReceiver(在聊天界面注册)

EMChatManager.getInstance().getChatOptions().setRequireDeliveryAck(flag)
//如果用到已发送的回执需要把这个flag设置成true
     
IntentFilter deliveryAckMessageIntentFilter = new IntentFilter(EMChatManager.getInstance().getDeliveryAckMessageBroadcastAction());
deliveryAckMessageIntentFilter.setPriority(5);
registerReceiver(deliveryAckMessageReceiver, deliveryAckMessageIntentFilter);
		
/**
* 消息送达BroadcastReceiver
*/
private BroadcastReceiver deliveryAckMessageReceiver = new BroadcastReceiver() {
    @Override
	public void onReceive(Context context, Intent intent) {
		abortBroadcast();

		String msgid = intent.getStringExtra("msgid");
		String from = intent.getStringExtra("from");
		EMConversation conversation = EMChatManager.getInstance().getConversation(from);
		if (conversation != null) {
			// 把message设为已读
			EMMessage msg = conversation.getMessage(msgid);
			if (msg != null) {
				msg.isDelivered = true;
			}
		}
	}
};

监听联系人的变化等

EMContactManager.getInstance().setContactListener(new MyContactListener());

private class MyContactListener implements EMContactListener {

	@Override
	public void onContactAdded(List<String> usernameList) {
		// 保存增加的联系人
			
	}

	@Override
	public void onContactDeleted(final List<String> usernameList) {
		// 被删除

	}

	@Override
	public void onContactInvited(String username, String reason) {
		// 接到邀请的消息,如果不处理(同意或拒绝),掉线后,服务器会自动再发过来,所以客户端不要重复提醒
			
	}

	@Override
	public void onContactAgreed(String username) {
		//同意好友请求
	}

	@Override
	public void onContactRefused(String username) {
		// 拒绝好友请求

	}

}

注册一个监听连接状态的 listener

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

//实现ConnectionListener接口
private class MyConnectionListener implements EMConnectionListener {
    @Override
	public void onConnected() {
	}
	@Override
	public void onDisconnected(final int error) {
		runOnUiThread(new Runnable() {

			@Override
			public void run() {
				if(error == EMError.USER_REMOVED){
					// 显示帐号已经被移除
				}else if (error == EMError.CONNECTION_CONFLICT) {
					// 显示帐号在其他设备登录
				} else {
				if (NetUtils.hasNetwork(MainActivity.this))
					//连接不到聊天服务器
				else
					//当前网络不可用,请检查网络设置
				}
			}
		});
	}
}

注册群聊相关的 listener

EMGroupManager.getInstance().addGroupChangeListener(new MyGroupChangeListener());

private class MyGroupChangeListener implements GroupChangeListener {

	@Override
	public void onInvitationReceived(String groupId, String groupName,String inviter, String reason) {

		//收到加入群聊的邀请

		boolean hasGroup = false;
		for (EMGroup group : EMGroupManager.getInstance().getAllGroups()) {
			if (group.getGroupId().equals(groupId)) {
				hasGroup = true;
				break;
			}
		}
		if (!hasGroup)
			return;

		// 被邀请
		EMMessage msg = EMMessage.createReceiveMessage(Type.TXT);
		msg.setChatType(ChatType.GroupChat);
		msg.setFrom(inviter);
		msg.setTo(groupId);
		msg.setMsgId(UUID.randomUUID().toString());
		msg.addBody(new TextMessageBody(inviter + "邀请你加入了群聊"));
		// 保存邀请消息
		EMChatManager.getInstance().saveMessage(msg);
		// 提醒新消息
		EMNotifier.getInstance(getApplicationContext()).notifyOnNewMsg();

	}

	@Override
	public void onInvitationAccpted(String groupId, String inviter,
				String reason) {
			//群聊邀请被接受
	}

	@Override
	public void onInvitationDeclined(String groupId, String invitee,
				String reason) {
		//群聊邀请被拒绝
	}

	@Override
	public void onUserRemoved(String groupId, String groupName) {
		//当前用户被管理员移除出群聊
			
	}

	@Override
	public void onGroupDestroy(String groupId, String groupName) {
		//群聊被创建者解散
		// 提示用户群被解散

	}

	@Override
	public void onApplicationReceived(String groupId, String groupName,String applyer, String reason) {
		// 用户申请加入群聊,收到加群申请
	}

	@Override
	public void onApplicationAccept(String groupId, String groupName,String accepter) {
		// 加群申请被同意
		EMMessage msg = EMMessage.createReceiveMessage(Type.TXT);
		msg.setChatType(ChatType.GroupChat);
		msg.setFrom(accepter);
		msg.setTo(groupId);
		msg.setMsgId(UUID.randomUUID().toString());
		msg.addBody(new TextMessageBody(accepter + "同意了你的群聊申请"));
		// 保存同意消息
		EMChatManager.getInstance().saveMessage(msg);
		// 提醒新消息
		EMNotifier.getInstance(getApplicationContext()).notifyOnNewMsg();
	}

	@Override
	public void onApplicationDeclined(String groupId, String groupName,String decliner, String reason) {
		// 加群申请被拒绝
	}

}

注:最后要通知 SDK,UI 已经初始化完毕,注册了相应的 receiver 和 listener,可以接受 broadcast 了。

EMChat.getInstance().setAppInited();

回调监听事件注册

EMChatManager.getInstance().registerEventListener(new EMEventListener() {
			
	@Override
	public void onEvent(EMNotifierEvent event) {

		switch (event.getEvent()) {	
		case EventNewMessage: // 接收新消息
		{
		EMMessage message = (EMMessage) event.getData();
			break;
		}
		case EventDeliveryAck:{//接收已发送回执
			
			break;
		}
		
		case EventNewCMDMessage:{//接收透传消息
			
			break;
		}
		
		case EventReadAck:{//接收已读回执
			
			break;
		}

		case EventOfflineMessage: {//接收离线消息
			List<EMMessage> messages = (List<EMMessage>) event.getData();
			break;
		}

		case EventConversationListChanged: {//通知会话列表通知event注册(在某些特殊情况,SDK去删除会话的时候会收到回调监听)
		    
		    break;
		}
		
		default:
			break;
		}
	}
	}
});

注:以上两种方式都可以执行相同的操作,但是广播和监听事件不可同时混用。


上一页:Android SDK 导入

下一页:消息