视频学习地址
本内容接上篇文章
我的源码:
码云
github
大加有需要可以下载来参照一下。
参考视频学习。
在学习过程中,总结了一些遇到的问题记录在这里。
android {
......
//指定jdk版本
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
android {
//use legacy for android 6.0(3.6.8版本之后移除apache library)
//useLibrary 'org.apache.http.legacy'
//自3.6.0开始需要java8的支持
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
//其他必要依赖
......
implementation 'io.hyphenate:hyphenate-chat:xxx版本号'
}
Duplicate class android.support.v4.app.INotificationSideChannel
found in modules classes?
解决方法:
需要在gradle.properties中添加下面两行代码
这是因为混合支持库。通过添加这些行选择androidX作为您的支持库
android.useAndroidX=true
android.enableJetifier=true
登录的时候报错
FATAL EXCEPTION: pool-3-thread-2
是因为Android Studio版本更新导致这个类没有了,在build.gradle中添加一句
implementation ‘com.android.support:support-v4:30.4.1’
注册的时候失败,报错
java.io.IOException: Cleartext HTTP traffic to 114.116.241.109 not permitted
原因是Android 9.0是默认禁止所有http请求的,需要在代码中设置如以下代码才可以正常进行网络请求。
在AndroidManifest.xml中添加,
android:usesCleartextTraffic=“true”
在导入v4包发现Fragment冲突
Duplicate class androidx.collection.ArrayMap found in modules collection-1.1.0 (androidx.collection:collection:1.1.0) and jetified-android-support-v4 (android-support-v4.jar)
可以不需要v4包,直接用androidx包下的也能实现一样的效果
如果用,导入v4包 后要把冲突包删掉
基于视频,说明一下环信EaseIMKit的使用与EaseUI的差别。
不同的是我们使用的Kit库继承EaseContactListFragment。实现的页面并没有标题栏,这个需要我们自己加上去。
可以在activity_main.xml中直接添加,这样的好处是,当我们切换三个fragment的时候就都可以有标题栏了,就不用每个页面都去加一次(我代码里的方法),挺麻烦的。
<com.hyphenate.easeui.widget.EaseTitleBar
android:id="@+id/fragment_title_bar1"
android:layout_width="match_parent"
android:layout_height="@dimen/ease_common_title_bar_height"
app:titleBarTitle="我"
android:ellipsize="marquee"
android:layout_gravity="center_horizontal|center"
android:background="@color/white"
app:titleBarDisplayHomeAsUpEnabled="true"/>
这样子就完成了三个页面的标题栏,但是想要对应页面,应该如何设置标题栏的字体呢。
参考开发文档,只要当我们的layout中使用的是环信提供的标题栏,那么下面的方法我们就可以用,包括到后面设计聊天窗口界面的时候。
在Java代码中,设置标题栏之前,也就是使用上面的标题栏方法的时候,需要先将标题栏的layout文件添加进当前的layout。关键代码
View searchView =LayoutInflater.form(mContext).inflate(R.layout.你的layout的文件名,root)
llRoot.addView(searchView,0)
...
...
看下一张图
然后就可以用上面的方法设置操作你的标题栏啦。
在对应的的fragment中调用上面的api就可以设置标题的文字了。
比如:在ContractListFragment中想要将联系人列表页面的标题栏设置为“联系人”
(添加右侧图标)是添加➕的方法,和➕的点击事件
添加搜索框的方法就是框出来这一段,我当时是直接在搜索框的layout中添加头部栏,这不太好,破环了搜索框的layout,建议大家用上面的方法添加头部栏
完成这两部分,就实现了添加头部栏和搜索框啦。
直接重写该方法,不需要像视频里那样 绑定各种东西
menuHelper.addItemMenu() 可以添加多个弹出的选项
case代表选择了弹出的选项是是哪一个
这些都可以去开发文档找到
ChatFragment继承了EaseConversationListFragment后**已经实现了监听会话消息变化和刷新,**所以这个不用再重复做了。主要是点击条目跳转待对应的聊天窗口。
这里与视频的差距是EaseIMKit重写onItemClick(View view, int position)方法的参数和EaseUI不一样,这里需要去得到相应的参数,就可以实现同样的功能。
在会话列表界面,如何实现点击某个联系人能跳转到与该联系人的会话窗口界面?
会话列表使用listView实现,每个联系人对应着一个list条目,从上往下条目为序序列,从0到n。重写条目的点击事件方法 OnItemClick(View view,int positon),view是条目的视图,position是点击的条目在listview中的位置,是第几条。
传入position来调用conversationListLayout.getItem(position)方法可以拿到该条目的所有信息。
//获取到该条目的所有数据
EaseConversationInfo conversationInfo = conversationListLayout.getItem(position);
从所有信息中取出该条目的会话的信息
//拿到该条目的会话信息
EMConversation conversation = (EMConversation) conversationInfo.getInfo();
从会话信息中取出该条目的唯一标识hxid
//传递参数 会话信息id =hxid
intent.putExtra(EaseConstant.EXTRA_CONVERSATION_ID, conversation.conversationId());
然后startActivity()就能跳转到对应的朋友的聊天窗口了
ChatFragment完整代码:
package com.example.im.controller.fragment;
import android.content.Intent;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import androidx.core.content.ContextCompat;
import com.example.im.R;
import com.example.im.controller.activity.AddContactActivity;
import com.example.im.controller.activity.ChatActivity;
import com.hyphenate.chat.EMConversation;
import com.hyphenate.easeui.constants.EaseConstant;
import com.hyphenate.easeui.modules.conversation.EaseConversationListFragment;
import com.hyphenate.easeui.modules.conversation.model.EaseConversationInfo;
import com.hyphenate.easeui.utils.EaseCommonUtils;
import com.hyphenate.easeui.widget.EaseTitleBar;
import static com.hyphenate.easeui.widget.EaseImageView.ShapeType.RECTANGLE;
//会话列表页面
public class ChatFragment extends EaseConversationListFragment {
@Override
public void initView(Bundle savedInstanceState) {
super.initView(savedInstanceState);
//添加搜索布局和标题栏
addSearchView();
//设置默认头像
conversationListLayout.setAvatarDefaultSrc(ContextCompat.getDrawable(mContext,R.drawable.toux));
//设置头像样式:0为默认,1为圆形,2为方形(设置方形时,需要配合设置avatarRadius,默认的avatarRadius为50dp)
conversationListLayout.setAvatarShapeType(RECTANGLE);
//设置圆角半径
conversationListLayout.setAvatarRadius((int) EaseCommonUtils.dip2px(mContext, 5));
}
private void addSearchView() {
//添加搜索会话布局
View searchView = LayoutInflater.from(mContext).inflate(R.layout.contract_search, null);
llRoot.addView(searchView,0);
//获取控件
EaseTitleBar titleBar=findViewById(R.id.fragment_title_bar);
//设置标题
titleBar.setTitle("会话列表");
//添加右侧图标
titleBar.setRightImageResource(R.drawable.em_contact_menu_add);
}
/**
* 逻辑:点击第position个条目触发该条目的监听器
*
* @param view
* @param position 该参数是条目的位置,从上往下,从零开始计数
*/
//设置条目的点击事件
@Override
public void onItemClick(View view, int position) {
super.onItemClick(view, position);
Intent intent = new Intent(getActivity(), ChatActivity.class);
//获取到该条目的所有数据
EaseConversationInfo conversationInfo = conversationListLayout.getItem(position);
//拿到该条目的会话信息
EMConversation conversation = (EMConversation) conversationInfo.getInfo();
//传递参数 会话信息id =hxid
intent.putExtra(EaseConstant.EXTRA_CONVERSATION_ID, conversation.conversationId());
//会话类型,是否是群聊
if (conversationInfo.isGroup()) {
intent.putExtra(EaseConstant.EXTRA_CHAT_TYPE, EaseConstant.CHATTYPE_GROUP);
}
startActivity(intent);
}
//刷新消息
}
使用的控件:
·ImageView,图片充满
·TextView,布局在上级控件的中间,
距离底部100dp
·设置顶部状态栏为透明:
getWindow().getDecorView().setSystemUiVisibility
(View.SYSTEM_UI_FLAG_LAYOUT_
HIDE_NAVIGATION);
整体为线性布局,垂直排列。
头像、设置、关于都是插入线性布局,放入
ImageView显示图片和显示字体的TextView
退出为Button按钮。
功能:
①显示当前用户的名称:
·获取名称:EMClient.getInstance().getCurrentUser()
·然后用TextView控件的setText()方法将当前用户的
·名称显示出来。
②点击退出按钮注销登录,回到登录界面:
·因为这是一个联网操作,需要开一个线程,去登录
环信服务器告诉服务器要执行退出登录
EMClient.getInstance().logout(false, new EMCallBack() ) 这里重写了三个方法,在退出成功的方法里onSuccess()实现回到登录界面,同时finish()当前的Activity。
Layout的textAllCaps=”false” 让模拟器显示英文大小写。
①设计:
·用ListView将历史记录(其他用户点击发送邀请信息广播后,将邀请信息保存在本地的数据库)展示出来。
·每个条目带有两个按钮,绑定了监听器,用来实现逻辑处理。
·注册了联系人变化的监听器,当前页面有新的邀请时,或者点击接受或拒绝时,刷新该页面。
·用适配器初始化ListView,
·按钮的变化:当有新的邀请时,设置当前条目的两个按钮显示,默认是隐藏。点击接受后,成功添加,并设置隐藏两个按钮,并刷新页面;点击拒绝,则直接删除该条记录,并刷新页面。
②用了适配器,且配置了ViewHolder。
·ViewHolder通常出现在适配器里,为的是listview滚动的时候快速设置值,而不必每次都重新创建很多对象,从而提升性能。当convertView不为空的时候直接重新使用
convertView从而减少了很多不必要的View的创建,然后加载数据。
·这些邀请信息和接受拒绝的信息都是通过环信的服务器来传递。
·点击接受按钮,通知环信服务器点击了接受按钮
EMClient.getInstance().contactManager().acceptInvitation(invitationInfo.getUser().getHxid());
·然后更新本地数据库。
Model.getInstance().getDbManager().getInviteTableDao().updateInvitationStatus(InvitationInfo.InvitationStatus.INVITE_ACCEPT,invitationInfo.getUser().getHxid());
图3.1整体布局
布局与功能
·头部栏左右两边添加了ImaButton,点击可以触发事件,不过还没有设置,中间用来显示当前聊天的用户、或者群组的名字。图3.1。
·底部为聊天栏这是环信提供的,布局是一个水平的线性布局,三个ImageButton和一个ImageView组成。图3.1。
·点击麦克风按钮后将其切换到图3.2的另一个水平线性布局,这是由四个ImageButton组成。
·点击笑脸按钮,弹出一个循环视图(RecyclerView)里面放置了线性排列的表情,点击进行匹配后会在ImageView中显示该表情。
·加号按钮同理。
图3.2 底部栏(1)
当ImageView里有内容时,出发监听器将加号按钮改成发送图3.3。
·聊天记录的展示用的时ListView来实现,因为聊天信息需要联网发送到服务器。所以开启消息漫游,先从服务器中获取聊天记录,然后保存到本地数据库,再从本的
图3.3 底部栏(2)
数据库加载信息展示出来。
·当第二次打开该页面的时候,会先判断本地数据库
中是否有聊天记录,如果有就直接加载,没有的话再开启
消息漫游。当一直往上翻聊天记录时只会去加载数据库中的记录。
还可以设置消息条目的展示位置
EaseChatFragment类下的initView()方法
chatLayout.getChatMessageListLayout().setItemShowType(EaseChatMessageListLayout.ShowType.NORMAL)
* normal:区分发送方(在右侧)和接收方(在左侧)
* left发送方和接收方在左侧
* right发送方和接收方在右侧
public enum ShowType {
NORMAL, LEFT/*, RIGHT*/
}