Android开发聊天工具,实现了类似QQ微信的即时通讯功能

Posted 我永远信仰

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android开发聊天工具,实现了类似QQ微信的即时通讯功能相关的知识,希望对你有一定的参考价值。

视频学习地址
代码可以私聊问博主要哦

简介:

参考视频学习。
在学习过程中,总结了一些遇到的问题记录在这里。

问题、报错

在这里插入图片描述
在这里插入图片描述

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中使用的是环信提供的标题栏,那么下面的方法我们就可以用,包括到后面设计聊天窗口界面的时候。
在这里插入图片描述
在对应的的fragment中调用上面的api就可以设置标题的文字了。
比如:在ContractListFragment中想要将联系人列表页面的标题栏设置为“联系人”

(添加右侧图标)是添加➕的方法,和➕的点击事件
在这里插入图片描述
添加搜索框的方法就是框出来这一段,我当时是直接在搜索框的layout中添加头部栏,这不太好,破环了搜索框的layout,建议大家用上面的方法添加头部栏
在这里插入图片描述
完成这两部分,就实现了添加头部栏和搜索框啦。

在这里插入图片描述

视频的第38节,关于长按删除联系人,

直接重写该方法,不需要像视频里那样 绑定各种东西

menuHelper.addItemMenu() 可以添加多个弹出的选项
case代表选择了弹出的选项是是哪一个
在这里插入图片描述
这些都可以去开发文档找到
在这里插入图片描述

视频的39 点击联系人跳转到聊天窗口

也是直接重写封装好的点击联系人的方法,不需要像视频中那样。
在这里插入图片描述

视频40

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);
    }

    //刷新消息

}

总结了一些页面的设计和功能

(1)欢迎界面

使用的控件:
·ImageView,图片充满
·TextView,布局在上级控件的中间,
距离底部100dp

·设置顶部状态栏为透明:
getWindow().getDecorView().setSystemUiVisibility
(View.SYSTEM_UI_FLAG_LAYOUT_
HIDE_NAVIGATION);
在这里插入图片描述

(2)“我”页面

整体为线性布局,垂直排列。

头像、设置、关于都是插入线性布局,放入
ImageView显示图片和显示字体的TextView
退出为Button按钮。

功能:

①显示当前用户的名称:
·获取名称:EMClient.getInstance().getCurrentUser()
·然后用TextView控件的setText()方法将当前用户的
·名称显示出来。
②点击退出按钮注销登录,回到登录界面:
·因为这是一个联网操作,需要开一个线程,去登录
环信服务器告诉服务器要执行退出登录
EMClient.getInstance().logout(false, new EMCallBack() ) 这里重写了三个方法,在退出成功的方法里onSuccess()实现回到登录界面,同时finish()当前的Activity。

Layout的textAllCaps=”false” 让模拟器显示英文大小写。
在这里插入图片描述

(3)邀请页面

①设计:

·用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());

拒绝按钮同理。
在这里插入图片描述

(4)会话详情页面

  图3.1整体布局

布局与功能

·头部栏左右两边添加了ImaButton,点击可以触发事件,不过还没有设置,中间用来显示当前聊天的用户、或者群组的名字。图3.1。
·底部为聊天栏这是环信提供的,布局是一个水平的线性布局,三个ImageButton和一个ImageView组成。图3.1。
·点击麦克风按钮后将其切换到图3.2的另一个水平线性布局,这是由四个ImageButton组成。
·点击笑脸按钮,弹出一个循环视图(RecyclerView)里面放置了线性排列的表情,点击进行匹配后会在ImageView中显示该表情。
·加号按钮同理。

   图3.2 底部栏(1)

当ImageView里有内容时,出发监听器将加号按钮改成发送图3.3。
·聊天记录的展示用的时ListView来实现,因为聊天信息需要联网发送到服务器。所以开启消息漫游,先从服务器中获取聊天记录,然后保存到本地数据库,再从本的

图3.3 底部栏(2)
数据库加载信息展示出来。
·当第二次打开该页面的时候,会先判断本地数据库
中是否有聊天记录,如果有就直接加载,没有的话再开启
消息漫游。当一直往上翻聊天记录时只会去加载数据库中的记录。

  • 在EaseChatMessageListLayout中设置
  • 三种数据加载模式,local是从本地数据库加载,Roam是开启消息漫游,History是搜索本
  • 地消息/*
    public enum LoadDataType {
    LOCAL, ROAM, HISTORY
    }

还可以设置消息条目的展示位置
EaseChatFragment类下的initView()方法
chatLayout.getChatMessageListLayout().setItemShowType(EaseChatMessageListLayout.ShowType.NORMAL)

 * normal:区分发送方(在右侧)和接收方(在左侧)
 * left发送方和接收方在左侧
 * right发送方和接收方在右侧
public enum ShowType {
    NORMAL, LEFT/*, RIGHT*/
}

在这里插入图片描述

以上是关于Android开发聊天工具,实现了类似QQ微信的即时通讯功能的主要内容,如果未能解决你的问题,请参考以下文章

谁知道android 的那个类似微信的回复功能怎么做,

android微信的聊天记录长按某聊天弹出的页面是怎样实现的

[android]聊天语音导出,支持微信。QQ,TIM

JAVA编写的聊天工具

Android实现类似QQ聊天的功能 怎么实现

安卓开发 viewpage加fragment加listview. 我想实现一个类似微信的界面。