代码实现的过程中参考了博客上几篇优秀的文章和其中的代码,本想放连接但是找不到了,如果大佬们看见了可以告知我,感谢大佬们。因为各种原因,没有使用网易云信自带的UI库,有兴趣的大佬可以试试,也在开发者文档种。
本文建立在基本网易云信依赖已经部署好的情况下,可详见网易云信官网开发者手册
https://doc.yunxin.163.com/docs/TM5MzM5Njk/TY1OTU4NDQ?platformId=600
也可以参考我上一篇博客
https://blog.csdn.net/qq_45796133/article/details/121236550
先上效果图,对方信息的发送利用的是网易云信自带的API调试台


上代码,首先是SendMessageActivity

package com.example.mycampus;import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;import androidx.appcompat.app.AppCompatActivity;import com.example.mycampus.Adapter.ChatAdapter;
import com.example.mycampus.Utils.IMService;
import com.example.mycampus.bean.PersonChat;
import com.netease.nimlib.sdk.NIMClient;
import com.netease.nimlib.sdk.RequestCallback;
import com.netease.nimlib.sdk.msg.MessageBuilder;
import com.netease.nimlib.sdk.msg.MsgService;
import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum;
import com.netease.nimlib.sdk.msg.model.IMMessage;import java.util.ArrayList;
import java.util.List;public class SendMessageActivity extends AppCompatActivity implements View.OnClickListener {private static IMService mImService;private LinearLayout mLlReturn;EditText et_chat_message;
//    private EditText mEdSendText;
//    private EditText mPrSendText;/*** 发消息*/
//    private Button mBtnSendText;
//    private static TextView mTvReceiveMessage;private static ChatAdapter chatAdapter;/*** 声明ListView*/private static ListView lv_chat_dialog;/*** 集合*///  static PersonChat personChat = new PersonChat();private  static List<PersonChat> personChats = new ArrayList<PersonChat>();private static Handler handler = new Handler() {public void handleMessage(android.os.Message msg) {int what = msg.what;switch (what) {case 1:/*** ListView条目控制在最后一行*/lv_chat_dialog.setSelection(personChats.size());break;default:break;}};};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_send_message);initView();init();}private void init() {// 绑定服务Intent service = new Intent(SendMessageActivity.this, IMService.class);bindService(service, mMyServiceConnection, BIND_AUTO_CREATE);}@Overridepublic void onDestroy() {super.onDestroy();// 解绑服务if (mMyServiceConnection != null) {unbindService(mMyServiceConnection);}}MyServiceConnection mMyServiceConnection = new MyServiceConnection();private void initView() {PersonChat personChat = new PersonChat();
//        mLlReturn = (LinearLayout) findViewById(R.id.ll_return);lv_chat_dialog = (ListView) findViewById(R.id.lv_chat_dialog);Button btn_chat_message_send = (Button) findViewById(R.id.btn_chat_message_send);et_chat_message = (EditText) findViewById(R.id.et_chat_message);/***setAdapter*/chatAdapter = new ChatAdapter(this, personChats);lv_chat_dialog.setAdapter(chatAdapter);btn_chat_message_send.setOnClickListener(this::onClick);
//        mEdSendText = (EditText) findViewById(R.id.ed_send_text);
//        mBtnSendText = (Button) findViewById(R.id.btn_send_text);
//         mPrSendText=(EditText) findViewById(R.id.ed_send_person);
//        mBtnSendText.setOnClickListener(this);//        mTvReceiveMessage = (TextView) findViewById(R.id.tv_receive_message);}@Overridepublic void onClick(View v) {switch (v.getId()) {default:break;
//            case R.id.ll_return:
//                finish();
//                break;case R.id.btn_chat_message_send:final String content =et_chat_message.getText().toString();//消息文本String account = "2";//目前这里是写死的账号,可以根据自己的需求改SessionTypeEnum type =  SessionTypeEnum.P2P;//会话类型final IMMessage textMessage = MessageBuilder.createTextMessage(account, type, content);NIMClient.getService(MsgService.class).sendMessage(textMessage, false).setCallback(new RequestCallback<Void>() {@Overridepublic void onSuccess(Void param) {Toast.makeText(SendMessageActivity.this, "发送成功~", Toast.LENGTH_SHORT).show();PersonChat personChat = new PersonChat();//代表自己发送personChat.setMeSend(true);//得到发送内容personChat.setChatMessage(et_chat_message.getText().toString());//加入集合personChats.add(personChat);//清空输入框et_chat_message.setText("");//刷新ListViewchatAdapter.notifyDataSetChanged();handler.sendEmptyMessage(1);}@Overridepublic void onFailed(int code) {}@Overridepublic void onException(Throwable exception) {}});// mEdSendText.setText("");break;}}public static void updateData(String message){System.out.println("更新成功");//update();PersonChat personChat = new PersonChat();//代表自己发送personChat.setMeSend(false);//得到发送内容personChat.setChatMessage(message);//加入集合personChats.add(personChat);//清空输入框//et_chat_message.setText("");//刷新ListViewchatAdapter.notifyDataSetChanged();handler.sendEmptyMessage(1);// et_.setText(message);// PersonChat personChat = new PersonChat();//代表自己发送//  personChat.setMeSend(false);//得到发送内容//  personChat.setChatMessage(message);//加入集合// personChatss.add(personChat);//清空输入框// et_chat_message.setText("");//刷新ListView//  chatAdapter.notifyDataSetChanged();//  handler.sendEmptyMessage(1);}class MyServiceConnection implements ServiceConnection {@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {System.out.println("--------------onServiceConnected--------------");IMService.MyBinder binder = (IMService.MyBinder) service;mImService = binder.getService();}@Overridepublic void onServiceDisconnected(ComponentName name) {System.out.println("--------------onServiceDisconnected--------------");}}}`

然后是IMservice类,用于通信服务

package com.example.mycampus.Utils;import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;import com.example.mycampus.SendMessageActivity;
import com.example.mycampus.bean.PersonChat;
import com.google.gson.Gson;
import com.netease.nimlib.sdk.NIMClient;
import com.netease.nimlib.sdk.Observer;
import com.netease.nimlib.sdk.friend.model.AddFriendNotify;
import com.netease.nimlib.sdk.msg.MsgServiceObserve;
import com.netease.nimlib.sdk.msg.SystemMessageObserver;
import com.netease.nimlib.sdk.msg.constant.MsgTypeEnum;
import com.netease.nimlib.sdk.msg.constant.SystemMessageType;
import com.netease.nimlib.sdk.msg.model.IMMessage;
import com.netease.nimlib.sdk.msg.model.SystemMessage;import java.util.List;public class IMService extends Service {private static ACache aCache;private Gson gson;@Overridepublic IBinder onBind(Intent intent) {return new MyBinder();}public class MyBinder extends Binder {// 返回server的实例public IMService getService() {return IMService.this;}}@Overridepublic void onCreate() {super.onCreate();aCache = ACache.get(this);gson = new Gson();//  NIMClient.getService(SystemMessageObserver.class).observeReceiveSystemMsg(systemMessageObserver, true);NIMClient.getService(MsgServiceObserve.class).observeReceiveMessage(incomingMessageObserver, true);}@Overridepublic void onDestroy() {super.onDestroy();// NIMClient.getService(SystemMessageObserver.class).observeReceiveSystemMsg(systemMessageObserver, false);NIMClient.getService(MsgServiceObserve.class).observeReceiveMessage(incomingMessageObserver, false);}private Observer<List<IMMessage>> incomingMessageObserver =new Observer<List<IMMessage>>() {@Overridepublic void onEvent(List<IMMessage> messages) {// 处理新收到的消息,为了上传处理方便,SDK 保证参数 messages 全部来自同一个聊天对象。for (IMMessage message : messages) {Log.i("message", "onEvent===========: " + message.getContent());if (message.getMsgType() == MsgTypeEnum.text) {SendMessageActivity.updateData(message.getContent());// personChats.add(personChat);}}}};}

然后是适配器ChatAdapter

public class ChatAdapter extends BaseAdapter {private Context context;private List<PersonChat> lists;public ChatAdapter(Context context, List<PersonChat> lists) {super();this.context = context;this.lists = lists;}/*** 是否是自己发送的消息* * @author cyf* */public static interface IMsgViewType {int IMVT_COM_MSG = 0;// 收到对方的消息int IMVT_TO_MSG = 1;// 自己发送出去的消息}@Overridepublic int getCount() {// TODO Auto-generated method stubreturn lists.size();}@Overridepublic Object getItem(int arg0) {// TODO Auto-generated method stubreturn lists.get(arg0);}@Overridepublic long getItemId(int arg0) {// TODO Auto-generated method stubreturn arg0;}/*** 得到Item的类型,是对方发过来的消息,还是自己发送出去的*/public int getItemViewType(int position) {PersonChat entity = lists.get(position);if (entity.isMeSend()) {// 收到的消息return IMsgViewType.IMVT_COM_MSG;} else {// 自己发送的消息return IMsgViewType.IMVT_TO_MSG;}}@Overridepublic View getView(int arg0, View arg1, ViewGroup arg2) {// TODO Auto-generated method stubHolderView holderView = null;PersonChat entity = lists.get(arg0);boolean isMeSend = entity.isMeSend();if (holderView == null) {holderView = new HolderView();if (isMeSend) {arg1 = View.inflate(context, R.layout.chat_dialog_right_item,null);holderView.tv_chat_me_message = (TextView) arg1.findViewById(R.id.tv_chat_me_message);holderView.tv_chat_me_message.setText(entity.getChatMessage());} else {arg1 = View.inflate(context, R.layout.chat_dialog_left_item,null);holderView.tv_name = (TextView) arg1.findViewById(R.id.tvname);holderView.tv_name.setText(entity.getChatMessage());}arg1.setTag(holderView);} else {holderView = (HolderView) arg1.getTag();}return arg1;}class HolderView {TextView tv_chat_me_message;TextView tv_name;}@Overridepublic boolean isEnabled(int position) {return false;}
}

接下来是布局文件,左对话框与右对话框

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:background="#c2c2c2"android:orientation="vertical"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_weight="1"android:background="@drawable/app_lvjian_rbtn_normal_background"android:orientation="vertical"android:padding="8dp" ><ListViewandroid:id="@+id/lv_chat_dialog"android:layout_width="match_parent"android:layout_height="wrap_content"android:divider="#0000"android:dividerHeight="8dp"android:scrollbars="none" ></ListView></LinearLayout><LinearLayoutandroid:layout_width="match_parent"android:layout_height="32dp"android:layout_marginTop="8dp"android:orientation="horizontal" ><EditTextandroid:id="@+id/et_chat_message"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:textSize="14sp"android:background="@drawable/app_lvjian_rbtn_normal_background"android:gravity="center|left"android:padding="8dp" /><Buttonandroid:id="@+id/btn_chat_message_send"android:textColor="#fff"android:text="发送"android:layout_width="64dp"android:layout_marginLeft="8dp"android:layout_height="match_parent"android:layout_gravity="center|right"android:layout_marginRight="4dp"android:background="#EA6A6A" /></LinearLayout></LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="horizontal" ><TextViewandroid:id="@+id/tv_chat_me_message"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginRight="8dp"android:layout_marginTop="8dp"android:layout_toLeftOf="@+id/iv_chat_imagr_right"android:background="@drawable/app_lvjian_chat_right"android:padding="8dp"android:text="test222" /><ImageViewandroid:id="@+id/iv_chat_imagr_right"android:layout_width="24dp"android:layout_height="24dp"android:layout_alignParentRight="true"android:layout_gravity="top"android:src="@mipmap/person" /></RelativeLayout>

activity_send_message

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:background="#c2c2c2"android:orientation="vertical"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_weight="1"android:background="@drawable/app_lvjian_rbtn_normal_background"android:orientation="vertical"android:padding="8dp" ><ListViewandroid:id="@+id/lv_chat_dialog"android:layout_width="match_parent"android:layout_height="wrap_content"android:divider="#0000"android:dividerHeight="8dp"android:scrollbars="none" ></ListView></LinearLayout><LinearLayoutandroid:layout_width="match_parent"android:layout_height="32dp"android:layout_marginTop="8dp"android:orientation="horizontal" ><EditTextandroid:id="@+id/et_chat_message"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:textSize="14sp"android:background="@drawable/app_lvjian_rbtn_normal_background"android:gravity="center|left"android:padding="8dp" /><Buttonandroid:id="@+id/btn_chat_message_send"android:textColor="#fff"android:text="发送"android:layout_width="64dp"android:layout_marginLeft="8dp"android:layout_height="match_parent"android:layout_gravity="center|right"android:layout_marginRight="4dp"android:background="#EA6A6A" /></LinearLayout></LinearLayout>

大功告成,因为代码写了有点久,所以如果有什么问题欢迎提问,错误或者可以改进的地方也欢迎指正!

安卓网易云信实现仿QQ双方聊天界面功能(附UI界面相关推荐

  1. 高仿QQ即时聊天软件开发系列之三登录窗口用户选择下拉框

    上一篇高仿QQ即时聊天软件开发系列之二登录窗口界面写了一个大概的布局和原理 这一篇详细说下拉框的实现原理 先上最终效果图 一开始其实只是想给下拉框加一个placeholder效果,让下拉框在未选择未输 ...

  2. android人脸识显示头像自定义,Android 仿QQ头像自定义截取功能

    看了Android版QQ的自定义头像功能,决定自己实现,随便熟悉下android绘制和图片处理这一块的知识. 先看看效果: 思路分析: 这个效果可以用两个View来完成,上层View是一个遮盖物,绘制 ...

  3. 蓝牙聊天App设计1:Android Studio制作蓝牙聊天通讯软件(UI界面设计)

    前言:蓝牙聊天App设计全部有三篇文章(一.UI界面设计,二.蓝牙搜索配对连接实现,三.蓝牙连接聊天),这篇文章是一.UI界面设计 课程1:Android Studio小白安装教程,以及第一个Andr ...

  4. 使用网易云信实现的文字图片聊天Demo

    一个单聊demo,可以收发文字消息和图片消息,基于网易云信实现 文件:590m.com/f/25127180-487136158-31fc8a(访问密码:551685) 记得在初学Android时,自 ...

  5. 网易云信深度优化解决移动聊天室“痼疾”

    本文源于云信移动技术专家项望烽在开源中国源创会2016年终盛典的题为<聊天室场景下的移动网络优化>分享. (网易云信移动端技术 项望烽) 突破传统群组思维和架构,实现无人数上限的聊天室 步 ...

  6. java实现仿QQ即时聊天

    这是我的java大作业,这里就直接贴上我的实验报告了. 2.0版已更新地址:Java仿QQ2.0版 项目已开源:github地址:imitate-qq 欢迎fork与star 仿微信App:canar ...

  7. Android仿QQ实现聊天功能

    前段时间下载了Android仿QQ界面和聊天的Demo,发现很有意思,于是研究了一下并自己在此基础上集成环信实现了在线聊天功能,可以实现注册.加人.审核通知.推送.创建群组.群组聊天,并加入了炫酷的背 ...

  8. WPF编程;上位机编程;C#编程;仿QQ基础实现(一)之界面预览

    简介 一.摘要 1.描述 2.关键字 二.什么是WPF 三.为什么选择WPF 四.仿QQ的登录界面 五.仿QQ联系人界面 六.源码下载 七.其他 八.参考 一.摘要 1.描述 本文主要描述的是如何通过 ...

  9. 【网易云信】自行实现陌生人防打扰功能

    网易云信实现陌生人防打扰功能,即屏蔽陌生人消息.不可以给陌生人发消息 要求如下: 1.如对方开启了陌生人消息保护且你不是对方关注的用户,则发送给对方消息时系统通知:对方开启了陌生人消息保护,您发出的消 ...

最新文章

  1. java中的匿名内部类
  2. javafx中css选择器_JavaFX技巧12:在CSS中定义图标
  3. 用几张图片教你,财务分析的平台、架构、指标体系、模型
  4. AjAx下拉列表框(SELECT)jquery插件
  5. 数学连乘和累加运算符号_期中复习:小学数学各年级知识点和重点、难点大全!...
  6. 【论文写作】文献资料的作用只是添砖加瓦
  7. C/C++[PAT B level 1004,1012]
  8. 华为HCNA之配置RIPv2认证实验
  9. 抖音昵称html,抖音个性网名带特殊符号 带漂亮符号的抖音昵称
  10. 使用eclipse时出现cannot access compilation unit的解决方法
  11. 解决Google浏览器打不开宝塔登录页面——阿里云服务器
  12. 如何删除设备和驱动器中的百度网盘
  13. 开源之夏 2022 重磅来袭,欢迎报名 Casbin社区项目
  14. 搭建自有HTTPS环境
  15. 许奔创新社-第56问:创意洞见的基础是什么?
  16. 抽丝剥茧C语言(中阶)分支与循环练习
  17. csgo进创意工坊显示专用服务器,国服CSGO加载Steam创意工坊的图
  18. 案例分享|方形锂电池铝壳外观缺陷检测
  19. AtCoder Beginner Contest 205 A~E 题解
  20. win10系统如何启动sql服务器,win10在装SQLServer时提示服务没有法启动如何办?

热门文章

  1. 免费算力平台——九天毕昇
  2. 小米4x刷android9.0,小米-红米-4X-LOS-安卓9.0.0-稳定版Stable2.0-来去电归属-农历等-本地化增强适配...
  3. E. AC Challenge ACM-ICPC 2018 南京赛区网络预赛 状压dp + 枚举状态
  4. VHDL数字频率计的设计
  5. 小程序实现语音识别歌曲的功能,对接讯飞的api,踩坑篇!!
  6. 关于docker报错:No connection could be made because the target machine actively refused it.
  7. 关于Tomcat服务器无法打开tomcat7w.exe的解决办法
  8. 在火星上,我们能种哪些菜?
  9. 渣基础:比照Hawstein学Cracking the coding interview(4)
  10. [UWP] ExReaderPlus 英语阅读软件