[EaseIMKit] EaseUI 的升级版 EaseIMKit 正式发布远程依赖库,版本号与 IM SDK 一致,详情请见:EaseIMKit 使用指南
在您阅读此文档时,我们假定您已经具备了基础的 Android 应用开发经验,并能够理解相关基础概念。此文档是针对导入EaseUI库的快速集成文档,如果只是导入SDK去集成使用,请移步 Android SDK集成
注册环信开发者账号并创建后台应用
详细操作步骤见 开发者注册及管理后台。 Appkey:一个 APP 的唯一标识
IM 用户:一个 appkey 下的唯一标识用户,用来登录环信服务器进行收发消息的用户。 可以在创建好的应用内注册两个 IM 用户(也可以称为环信 id),例如: 账号:user1,密码:123 ; 账号:user2,密码:123,用来通过 SDK 登录环信服务器,收发消息测试。
在环信 Console 后台,点击创建好的应用 → IM 用户 → 创建 IM 用户
建议创建两个 IM 用户,用于后面集成 SDK 之后聊天使用。例如登录 user1 ,在初始化聊天页面时传入 user2 ,user1 给 user2 发消息测试。
EaseUI是环信提供的UI库,封装了 IM 功能常用的控件、fragment 等等,旨在帮助开发者快速集成环信 SDK。 EaseUI里封装了三个fragment,分别是
具体了解详见 EaseUI使用指南
EaseUI 中用到的第三方库:
从 环信官网点击下载SDK+Demo源码
下载下来的压缩包解压后内容如下:
环信的EaseUI位置在examples路径下,与ChatDemoUI3.0平级,内部已经导入了带有实时音视频功能的IM SDK,不需要再去导入。
打开Android Studio,File–New–Import Module,选中demo路径下的easeui导入。
等待编译完成,然后将其添加依赖于app module下。
在清单文件 AndroidManifest.xml 里加入以下权限,以及写上你注册的 AppKey。
权限配置(实际开发中可能需要更多的权限,可参考 Demo):
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="Your Package"
android:versionCode="100"
android:versionName="1.0.0">
<!-- Required -->
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.GET_TASKS" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:name="Your Application">
<!-- 设置环信应用的AppKey -->
<meta-data android:name="EASEMOB_APPKEY" android:value="Your AppKey" />
<!-- 声明SDK所需的service SDK核心功能-->
<service android:name="com.hyphenate.chat.EMChatService" android:exported="true"/>
<service android:name="com.hyphenate.chat.EMJobService"
android:permission="android.permission.BIND_JOB_SERVICE"
android:exported="true"
/>
<!-- 声明SDK所需的receiver -->
<receiver android:name="com.hyphenate.chat.EMMonitorReceiver">
<intent-filter>
<action android:name="android.intent.action.PACKAGE_REMOVED"/>
<data android:scheme="package"/>
</intent-filter>
<!-- 可选filter -->
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.intent.action.USER_PRESENT" />
</intent-filter>
</receiver>
</application>
</manifest>
适配Android 7.0需在AndroidManifest.xml里配置FileProvider
<!-- 适配Android 7.0, 需要将下方的com.hyphenate.chatuidemo替换为你的app包名 -->
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.hyphenate.chatuidemo.fileProvider"
android:grantUriPermissions="true"
android:exported="false">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
file_paths.xml内容如下,需将com/hyphenate/chatuidemo替换为你的包名路径
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path path="Android/data/com/hyphenate/chatuidemo/" name="files_root" />
<external-path path="." name="external_storage_root" />
在application的onCreate下调用初始化EaseUI的方法。注:EaseUi初始化里已包含SDK的初始化,不需要再去调用SDK的初始化。
//EaseUI初始化
if(EaseUI.getInstance().init(context, options)){
//在做打包混淆时,关闭debug模式,避免消耗不必要的资源
EMClient.getInstance().setDebugMode(true);
//EaseUI初始化成功之后再去调用注册消息监听的代码
...
}
//传入在应用(appkey)下注册的IM用户的账号和密码,用于登录环信服务器
EMClient.getInstance().login(userName,password,new EMCallBack() {//回调
@Override
public void onSuccess() {
EMClient.getInstance().groupManager().loadAllGroups();
EMClient.getInstance().chatManager().loadAllConversations();
}
@Override
public void onProgress(int progress, String status) {
}
@Override
public void onError(int code, String message) {
}
});
EaseUI里提供的EaseChatFragment可以直接拿来使用,也可创建Fragment去继承EaseChatFragment实现,如:需实现实时音视频通话。可参考demo的ChatFragment。 在项目里创建ChatActivity去加载EaseChatFragment
public class ChatActivity extends BaseActivity {
public static ChatActivity activityInstance;
private EaseChatFragment chatFragment;
@Override
protected void onCreate(Bundle arg0) {
super.onCreate(arg0);
setContentView(R.layout.em_activity_chat);
activityInstance = this;
//use EaseChatFratFragment
chatFragment = new EaseChatFragment();
//pass parameters to chat fragment
chatFragment.setArguments(getIntent().getExtras());
getSupportFragmentManager().beginTransaction().add(R.id.container, chatFragment).commit();
}
}
之后就可以通过调用Intent携带聊天对方的环信id跳转ChatActivity实现聊天
Intent intent = new Intent(this, ChatActivity.class);
//username为对方的环信id
intent.putExtra(EaseConstant.EXTRA_USER_ID, username);
startActivity(intent);
需创建Fragment去继承EaseConversationFragment实现点击item跳转聊天界面,可参考demo的ConversationListFragment
conversationListView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
EMConversation conversation = conversationListView.getItem(position);
String username = conversation.conversationId();
if (username.equals(EMClient.getInstance().getCurrentUser()))
Toast.makeText(getActivity(), R.string.Cant_chat_with_yourself, Toast.LENGTH_SHORT).show();
else {
// start chat acitivity
Intent intent = new Intent(getActivity(), ChatActivity.class);
if(conversation.isGroup()){
if(conversation.getType() == EMConversationType.ChatRoom){
// it's group chat
intent.putExtra(EaseConstant.EXTRA_CHAT_TYPE, EaseConstant.CHATTYPE_CHATROOM);
}else{
intent.putExtra(EaseConstant.EXTRA_CHAT_TYPE, EaseConstant.CHATTYPE_GROUP);
}
}
// it's single chat
intent.putExtra(EaseConstant.EXTRA_USER_ID, username);
startActivity(intent);
}
}
});
好友列表同会话列表一样,都需要创建Fragment去继承EaseContactListFragment实现点击item跳转
listView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
EaseUser user = (EaseUser)listView.getItemAtPosition(position);
if (user != null) {
String username = user.getUsername();
// demo中直接进入聊天页面,实际一般是进入用户详情页
startActivity(new Intent(getActivity(), ChatActivity.class).putExtra("userId", username));
}
}
});
好友列表还需要去设置数据,通过调用setContactsMap(m)去设置,数据需要是Map<String, EaseUser>格式的,key是环信id。
注:会话列表和好友列表都需要对应的Activity来加载,也可以都加载在同一个activity里,然后根据导航栏的点击来切换,譬如环信的demo那样。
实时音视频通话这块在EaseUI里是没有实现的,需要在项目里自行实现。可以直接从demo中去copy相关的类来快速实现。 首先需要在初始化之后去注册通话广播接收者,来监听通话请求。
IntentFilter callFilter = new IntentFilter(EMClient.getInstance().callManager().getIncomingCallBroadcastAction());
if(callReceiver == null){
callReceiver = new CallReceiver();
}
//register incoming call receiver
appContext.registerReceiver(callReceiver, callFilter);
CallReceiver代码如下
public class CallReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
if(!DemoHelper.getInstance().isLoggedIn())
return;
//username
String from = intent.getStringExtra("from");
//call type
String type = intent.getStringExtra("type");
if("video".equals(type)){ //video call
context.startActivity(new Intent(context, VideoCallActivity.class).
putExtra("username", from).putExtra("isComingCall", true).
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
}else{ //voice call
context.startActivity(new Intent(context, VoiceCallActivity.class).
putExtra("username", from).putExtra("isComingCall", true).
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
}
EMLog.d("CallReceiver", "app received a incoming call");
}
}
接着将demo中的VideoCallActivity、VoiceCallActivity、CallActivity以及它们需要的文件到copy过来。 然后在ChatFragment中registerExtendMenuItem方法中添加发起音视频通话的图标,实现对应的点击事件–携带参数跳转通话界面。
//视频通话就是跳转VideoCallActivity
startActivity(new Intent(getActivity(), VoiceCallActivity.class).putExtra("username", toChatUsername)
.putExtra("isComingCall", false));
可参考demo的ChatFragment。