仰天大笑出门去,我辈岂是蓬蒿人。这篇文章主要讲述Android实现简单的聊天功能相关的知识,希望能为你提供帮助。
【Android实现简单的聊天功能】---恢复内容开始---
一直想试试做一个两个客户端可以聊天的功能,上网查了查,这个IM聊天的好像还真的不那么容易,无奈deadline快到了,所以只能用一下第三方的库了
这里我用的是环信,然后花了一天,其中走了不少弯路,把这个功能做出来了,记录一下这个坎坷的过程
首先,一般这种第三方服务,像之前用的百度地图,都需要去注册成为他们的开发者,所以第一步自然是去环信官网注册
网址在这:https://www.easemob.com/,就是直接点击页面上的注册就可以了
注册成功后,就是创建应用然后拿到对应的APPKey了,进入后台管理,点击创建应用,就会有相应的APPKey了,这里不多说了
然后接下来就是集成到androidStudio里面了,参考官方的集成教程就可以了
http://docs.easemob.com/im/200androidclientintegration/10androidsdkimport
把权限都写好,并将里面的APPKey换成自己的就行了
然后点击sychron now,ok了
现在开始撸代码
先写界面,推荐参考郭霖大神的<
第一行代码>
第二版里面的聊天界面,之前有想法自己用ListView来写,但是性能很差体验也差
还是用RecyclerView好一些
聊天主界面
< ?xml version="1.0" encoding="utf-8"?> < LinearLayout xmlns:android = "http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_height="match_parent" android:layout_width="match_parent" android:background="#d8e0e8"> < android.support.v7.widget.RecyclerView android:id="@+id/msg_recycler_view" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1"/> < LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content"> < EditText android:id="@+id/input_text" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:hint="Type something here" android:maxLines="2"/> < Button android:id="@+id/send" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Send"/> < /LinearLayout> < /LinearLayout>
消息的布局
< ?xml version="1.0" encoding="utf-8"?> < LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="10dp"> < LinearLayout android:id="@+id/left_layout" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="left" android:background="@drawable/message_left"> < TextView android:id="@+id/left_msg" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:layout_margin="10dp" android:textColor="#fff"/> < /LinearLayout> < LinearLayout android:id="@+id/right_layout" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="right" android:background="@drawable/message_right"> < TextView android:id="@+id/right_msg" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="10dp" android:layout_gravity="center"/> < /LinearLayout> < /LinearLayout>
消息类
package Tool; /** * Created by 31786 on 2018/5/15. */public class Msg { public static final int TYPE_RECIEVED = 0; //表示这是一条收到的消息 public static final int TYPE_SENT = 1; //表示这是一条发出去的消息 private String content; //消息的内容 private int type; //消息的类型 public Msg(String content,int type){ this.content = content; this.type = type; } public String getContent(){ return content; } public int getType(){ return type; } }
适配器
package Tool; import android.support.v7.widget.RecyclerView; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.LinearLayout; import android.widget.TextView; import com.example.car.R; import java.util.List; /** * Created by 31786 on 2018/5/15. */public class MsgAdapter extends RecyclerView.Adapter< MsgAdapter.ViewHolder> {private List< Msg> mMsgList; //消息列表 static class ViewHolder extends RecyclerView.ViewHolder{ LinearLayout leftLayout; LinearLayout rightLayout; TextView leftMsg; TextView rightMsg; ViewHolder(View view){ super(view); Log.d("ViewHolder","初始化了"); leftLayout =(LinearLayout) view.findViewById(R.id.left_layout); rightLayout = (LinearLayout) view.findViewById(R.id.right_layout); leftMsg = (TextView) view.findViewById(R.id.left_msg); rightMsg = (TextView) view.findViewById(R.id.right_msg); } } public MsgAdapter(List< Msg> msgList){ Log.d("MsgAdapter","初始化了"); mMsgList = msgList; } @Override public ViewHolder onCreateViewHolder(ViewGroup parent,int viewType){ Log.d("ViewHolder","初始化了"); View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.msg_item,parent,false); return new ViewHolder(view); } @Override public void onBindViewHolder(ViewHolder holder,int position){ Msg msg = mMsgList.get(position); if(msg.getType()==Msg.TYPE_RECIEVED){ Log.d("RECIEVED......",msg.getContent()); holder.leftLayout.setVisibility(View.VISIBLE); holder.rightLayout.setVisibility(View.GONE); holder.leftMsg.setText(msg.getContent()); }else if(msg.getType()==Msg.TYPE_SENT){ Log.d("SEND......",msg.getContent()); holder.rightLayout.setVisibility(View.VISIBLE); holder.leftLayout.setVisibility(View.GONE); holder.rightMsg.setText(msg.getContent()); } } @Override public int getItemCount(){ Log.d("Item的数量是",String.valueOf(mMsgList.size())); return mMsgList.size(); } }
然后开始写逻辑
由于我这里是个子功能,我SDK的初始化和注册并没有放在当前这个聊天的活动里面,所以建议最好将SDK的初始化放在工程里面靠前的活动里面
因为如果初始化两次,那么第二次就会新建一个新的连接,就会出现问题,注册的话也是为了避免重复注册,我把注册和我APP本身的注册放在一起了
初始化代码
public void initMob(){ Context 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(appContext.getPackageName())) { Log.e("YTH", "enter the service process!"); // 则此application::onCreate 是被service 调用的,直接返回 return; } EMClient.getInstance().init(this,new EMOptions()); EMClient.getInstance().setDebugMode(true); } 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) { processName = info.processName; return processName; } } catch (Exception e) { // Log.d("Process", "Error> > :"+ e.toString()); } } return processName; }
注册代码
public static void registerMob(){ new Thread(new Runnable() { @Override public void run() { try{ EMClient.getInstance().createAccount(userNumber.getText().toString(), passWord.getText().toString()); }catch (HyphenateException e){ Log.e("聊天功能","注册失败"); } } }).start(); }
主界面的逻辑
package com.example.car; import android.net.Uri; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; import com.google.android.gms.appindexing.Action; import com.google.android.gms.appindexing.AppIndex; import com.google.android.gms.appindexing.Thing; import com.google.android.gms.common.api.GoogleApiClient; import com.hyphenate.EMCallBack; import com.hyphenate.EMMessageListener; import com.hyphenate.chat.EMClient; import com.hyphenate.chat.EMMessage; import com.hyphenate.chat.EMTextMessageBody; import com.hyphenate.util.EasyUtils; import java.util.ArrayList; import java.util.List; import Tool.Msg; import Tool.MsgAdapter; public class Chatting extends AppCompatActivity implements View.OnClickListener, EMMessageListener {private List< Msg> msgList = new ArrayList< > (); //消息列表 private EditText inputText; //输入框 private Button send; //发送 private RecyclerView msgViewRecyclerView; private MsgAdapter adapter; private String chatId; //自己传进来的跟自己聊天的人的ID @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_chatting); initEvents(); addListener(); }public void addListener() { send.setOnClickListener(this); }public void initEvents() { inputText = (EditText) findViewById(R.id.input_text); send = (Button) findViewById(R.id.send); msgViewRecyclerView = (RecyclerView) findViewById(R.id.msg_recycler_view); LinearLayoutManager layoutManager = new LinearLayoutManager(this); msgViewRecyclerView.setLayoutManager(layoutManager); adapter = new MsgAdapter(msgList); msgViewRecyclerView.setAdapter(adapter); }public void sendMessage(String content,String chatWithId) { EMMessage message = EMMessage.createTxtSendMessage(content,chatWithId); //如果是群聊,设置chattype,默认是单聊 message.setChatType(EMMessage.ChatType.Chat); //发送消息 EMClient.getInstance().chatManager().sendMessage(message); message.setMessageStatusCallback(new EMCallBack() { @Override public void onSuccess() { Log.d("发送信息成功","发送信息成功"); //Toast.makeText(Chatting.this, "发送信息成功", Toast.LENGTH_SHORT).show(); }@Override public void onError(int code, String error) { Log.d("发送信息失败",error); //Toast.makeText(Chatting.this, "发送信息失败", Toast.LENGTH_SHORT).show(); }@Override public void onProgress(int progress, String status) { //Toast.makeText(Chatting.this, "发送信息中"+status, Toast.LENGTH_SHORT).show(); Log.d("发送信息中",status); } }); }@Override public void onClick(View view) { switch (view.getId()) { case R.id.send: Log.d("MainActivity", "Send......"); String content = inputText.getText().toString(); if (!"".equals(content)) { Msg msg = new Msg(content, Msg.TYPE_SENT); Log.d("Send", content); msgList.add(msg); adapter.notifyItemInserted(msgList.size() - 1); //刷新 msgViewRecyclerView.scrollToPosition(msgList.size() - 1); //定位 inputText.setText(""); sendMessage(content,chatId); } break; default: break; } }@Override public void onMessageReceived(List< EMMessage> messages) { //将恢复的信息加入到消息列表里面并刷新 for (int i = 0; i < messages.size(); i++) { String content = ((EMTextMessageBody) messages.get(i).getBody()).getMessage(); msgList.add(new Msg(content, Msg.TYPE_RECIEVED)); //Toast.makeText(getApplicationContext(), content, Toast.LENGTH_SHORT).show(); Log.d("size="+messages.size(),"回复的信息"+content); } adapter.notifyItemInserted(msgList.size() - 1); adapter.notifyDataSetChanged(); msgViewRecyclerView.scrollToPosition(msgList.size() - 1); }@Override public void onCmdMessageReceived(List< EMMessage> messages) {}@Override public void onMessageRead(List< EMMessage> messages) {}@Override public void onMessageDelivered(List< EMMessage> messages) {}@Override public void onMessageChanged(EMMessage message, Object change) {}@Override public void onResume(){ super.onResume(); EMClient.getInstance().chatManager().addMessageListener(this); } public void onStop(){ super.onStop(); EMClient.getInstance().chatManager().removeMessageListener(this); } }
出来的效果还行,凑合着能用
文章图片
---恢复内容结束---
推荐阅读
- Android View之布局加载流程
- Android Studio 第八十二期 - Android Glide3.8.0用法大全支持九宫格
- android内嵌html5页面不能播放视频
- 连载神器测评|更专业的连载小说追书App
- Android Service用法知识点的讲解
- HDU-6333 Problem B. Harvest of Apples莫队
- mybatis根据数据库表结构自动生成实体类,dao,mapper
- Android第五课 编译错误分析
- Android第六课 安装异常处理