IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Android小项目——聊天室 -> 正文阅读

[移动开发]Android小项目——聊天室

activity_main.xml

<?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="@drawable/hhh"
    android:orientation="vertical">

    <androidx.appcompat.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#318A9898">

        <TextView
            android:id="@+id/tv_room"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:text="登录聊天室"
            android:textColor="#9EF6F0F0"
            android:textSize="20sp" />
    </androidx.appcompat.widget.Toolbar>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:layout_gravity="center_vertical"
        android:paddingTop="120dp">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:orientation="horizontal">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:id="@+id/tv_name"
                android:text="用户名"
                android:gravity="center"
                android:textSize="20sp"
                android:textColor="#9EFFFFFF"/>

            <EditText
                android:layout_width="150dp"
                android:layout_height="wrap_content"
                android:id="@+id/edittext1"
                android:gravity="center"
                android:textColor="#fff"
                android:textSize="19sp"
                android:theme="@style/CretateRoomEditTextTheme"/>

        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:orientation="horizontal">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:id="@+id/tv2_name"
                android:text="IP地址"
                android:gravity="center"
                android:textSize="20sp"
                android:textColor="#9EFFFFFF"/>

            <EditText
                android:layout_width="150dp"
                android:layout_height="wrap_content"
                android:id="@+id/edittext2"
                android:gravity="center"

                android:textColor="#fff"
                android:textSize="19sp" />

        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:orientation="horizontal">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:id="@+id/tv3_name"
                android:text="端口    "
                android:gravity="center"
                android:textSize="20sp"
                android:textColor="#9EFFFFFF"/>

            <EditText
                android:layout_width="150dp"
                android:layout_height="wrap_content"
                android:id="@+id/edittext3"
                android:gravity="center"
                android:textColor="#fff"
                android:textSize="19sp"
                />

        </LinearLayout>


    </LinearLayout>

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="right"
        android:layout_marginEnd="30dp"
        android:layout_marginTop="20dp"
        android:text="登   录"
        android:textSize="16sp"
        android:textColor="#fff"
        android:background="#318A9898"/>


</LinearLayout>

在这里插入图片描述
MainActivity

public class MainActivity extends AppCompatActivity implements View.OnClickListener{
    private Button button;
    private EditText editText1;
    private EditText editText2;
    private EditText editText3;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //注册
        button = (Button)findViewById(R.id.button);
        editText1 = findViewById(R.id.edittext1);
        editText2 = findViewById(R.id.edittext2);
        editText3 = findViewById(R.id.edittext3);
        button.setOnClickListener(MainActivity.this);
        editText2.setText("192.168.1.200");
        editText3.setText("9999");

    }

    @Override
    public void onClick(View view) {
        //获取用户输入的名字
        String name = editText1.getText().toString();
        if("".equals(name)) {
            Toast.makeText(this, "请输入用户名", Toast.LENGTH_SHORT).show();
        }else {
            //通过显式Intent关联下一个活动 并传递数据给下一个活动
            Intent intent = new Intent(MainActivity.this, ChatRoom.class);
            intent.putExtra("name", editText1.getText().toString());
            intent.putExtra("ip", editText2.getText().toString());
            intent.putExtra("port",editText3.getText().toString());
            startActivity(intent);
        }

    }
}

activity_chat_room

<?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:orientation="vertical"
    android:background="@drawable/qqq">

    <androidx.appcompat.widget.Toolbar
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/toolbar2"
        android:background="#579BA5A5">

        <Button
            android:layout_width="45dp"
            android:layout_height="45dp"
            android:id="@+id/back"
            android:background="@drawable/f"/>

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/chat_room"
            android:text="ChatRoom"
            android:layout_gravity="center"
            android:textSize="20sp"/>



    </androidx.appcompat.widget.Toolbar>

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/msg_recyclerview"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"/>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <EditText
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:id="@+id/input_text"
            android:hint="Type Something..."
            android:maxLines="2"/>

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/send"
            android:text="Send"
            android:textAllCaps="false"
            android:textSize="18sp"
            android:background="#579BA5A5"/>
    </LinearLayout>



</LinearLayout>

在这里插入图片描述
Msg

public class Msg {
    public static final int TYPE_RECEIVED = 0;      //这是一条接收的消息
    public static final int TYPE_SEND = 1;          //这是一条发送的消息

    private String content;     //表示消息的内容
    private int type;           //表示消息的类型
    private String data;        //表示消息的时间
    private String name;       //表示发送的用户名


    public Msg(String content, int type, String name, String data) {
        this.content = content;
        this.type = type;
        this.name = name;
        this.data = data;
    }

    public String getContent() {
        return content;
    }

    public int getType() {
        return type;
    }

    public String getData() {
        return data;
    }

    public String getName() {
        return name;
    }
}

MsgAdapter

public class MsgAdapter extends RecyclerView.Adapter<MsgAdapter.ViewHolder> {
    private List<Msg> list;

    public MsgAdapter(List<Msg> list1) {
        list = list1;

    }


    static class ViewHolder extends RecyclerView.ViewHolder {
        LinearLayout leftLinearLayout;
        LinearLayout rightLinearLayout;
        TextView item_data;
        TextView item_leftname;
        TextView item_rightname;
        TextView item_leftcontent;
        TextView item_rightcontent;

        public ViewHolder(View itemView) {
            super(itemView);
            leftLinearLayout = (LinearLayout) itemView.findViewById(R.id.item_leftLinearLayout);
            rightLinearLayout = (LinearLayout) itemView.findViewById(R.id.item_rightLinearLayout);
            item_data = (TextView) itemView.findViewById(R.id.item_data);
            item_leftname = (TextView) itemView.findViewById(R.id.item_leftname);
            item_rightname = (TextView) itemView.findViewById(R.id.item_rightname);
            item_leftcontent = (TextView) itemView.findViewById(R.id.item_leftcontent);
            item_rightcontent = (TextView) itemView.findViewById(R.id.item_rightcontent);
        }
    }

    @Override
    public MsgAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        //加载布局
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.msg_item, parent, false);
        //创建一个ViewHolder实例
        ViewHolder holder = new ViewHolder(view);
        return holder;
    }

    @Override
    //用于对RecyclerView子项数据进行赋值的 会在每个子项滚到屏幕内执行
    public void onBindViewHolder(MsgAdapter.ViewHolder holder, int position) {
        //通过position参数获得当前项Msg实例
        Msg msg = list.get(position);
        //设置显示
        if(msg.getType() == msg.TYPE_RECEIVED) {
            holder.leftLinearLayout.setVisibility(View.VISIBLE);        //显示左边的
            holder.rightLinearLayout.setVisibility(View.GONE);          //隐藏右边的
            holder.item_data.setText(msg.getData());
            holder.item_leftcontent.setText(msg.getContent());
            holder.item_leftname.setText(msg.getName());
        }else if(msg.getType() == Msg.TYPE_SEND) {
            holder.leftLinearLayout.setVisibility(View.GONE);           //隐藏左边的
            holder.rightLinearLayout.setVisibility(View.VISIBLE);       //显示右边的
            holder.item_data.setText(msg.getData());
            holder.item_rightcontent.setText(msg.getContent());
            holder.item_rightname.setText(msg.getName());
        }

    }

    @Override
    //返回RecyclerView子项数
    public int getItemCount() {
        return list.size();
    }
}

ChatRoom

public class ChatRoom extends AppCompatActivity implements View.OnClickListener{
    private List<Msg> list = new ArrayList<>();
    private String name;
    private String ip;
    private String port;
    private Button send;
    private Button back;
    private EditText inputview;
    private RecyclerView recyclerView;
    private MsgAdapter adapter;
    private DataInputStream dataInputStream;
    private DataOutputStream dataOutputStream;
    private Socket socket;
    private boolean Istrue = false;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_chat_room);
        //用intent接收上一个活动传下来的信息
        Intent intent = getIntent();
        //获取名字 ip 端口号
        name = intent.getStringExtra("name");
        ip = intent.getStringExtra("ip");
        port = intent.getStringExtra("port");
        //获取控件的实例
        inputview = findViewById(R.id.input_text);
        send = findViewById(R.id.send);
        send.setOnClickListener(this);
        back = findViewById(R.id.back);
        //back的点击事件
        back.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //显示框 退出程序的选择框
                AlertDialog.Builder alertDialog = new AlertDialog.Builder(ChatRoom.this);
                //设置标题
                alertDialog.setTitle("退出");
                //设置内容
                alertDialog.setMessage("退出登录?");
                //点除按钮外的任何地方该显示框不会消失
                alertDialog.setCancelable(false);
                //点击按钮
                alertDialog.setPositiveButton("是", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        //销毁活动
                        finish();
                    }
                });
                alertDialog.setNegativeButton("否", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {

                    }
                });
                //开始启动
                alertDialog.show();
            }
        });
        //获取实例
        recyclerView = (RecyclerView) findViewById(R.id.msg_recyclerview);
        //创建LinearLayoutManager对象  LayoutManager用于指定RecyclerView的布局方式
        //LinearLayoutManager代表线性布局
        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        //并把它设置到RecyclerView中
        recyclerView.setLayoutManager(layoutManager);
        //创建适配器 并把数据传入适配器的有参构造中
        adapter = new MsgAdapter(list);
        //完成适配器的设置
        recyclerView.setAdapter(adapter);



        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    if("9999".equals(port) && "192.168.1.200".equals(ip)) {
                        socket = new Socket(ip, Integer.parseInt(port));
                        Istrue = true;
                        dataInputStream = new DataInputStream(socket.getInputStream());
                        dataOutputStream = new DataOutputStream(socket.getOutputStream());
                        //开一条线程接收服务器传来的消息
                        new Thread(new Revised()).start();
                    }else {
                        Looper.prepare();
                        Toast.makeText(ChatRoom.this, "连接服务器失败", Toast.LENGTH_SHORT).show();
                        Looper.loop();
                        socket = new Socket(ip, Integer.parseInt(port));
                        dataInputStream = new DataInputStream(socket.getInputStream());
                        dataOutputStream = new DataOutputStream(socket.getOutputStream());
                        //开一条线程接收服务器传来的消息
                        new Thread(new Revised()).start();
                    }

                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }).start();



        //判断是否连接到服务器
//        new Thread(new Runnable() {
//            @Override
//            public void run() {
//                try {
//                    if((socket = new Socket(ip, Integer.parseInt(port))) == null) {
//                        //连接服务器失败
//                        Toast.makeText(ChatRoom.this, "连接服务器失败", Toast.LENGTH_SHORT).show();
//                    }else {
//                        //连接服务器成功
//                        Istrue = true;
//                        //开启数据流 关联港口
//                        dataInputStream = new DataInputStream(socket.getInputStream());
//                        dataOutputStream = new DataOutputStream(socket.getOutputStream());
//                        //开一条线程接收服务器传来的消息
//                        new Thread(new Revised()).start();
//                    }
//                } catch (IOException e) {
//                    e.printStackTrace();
//                }
//            }
//        }).start();

    }
    //保证每页只能显示20条消息 自动删除最上面的一条
    private void AutoDelete() {
        //最多显示20条消息
        while(list.size() > 20) {
            //移除最上面的一条
            list.remove(0);
            //因为不能在主线程以外操作UI  所以将刷新UI放入runOnUiThread中
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    //调用适配器中的方法动态刷新recyclerView
                    adapter.notifyDataSetChanged();
                }
            });
        }
    }
    //接收服务器传来的消息
    class Revised implements Runnable{

        @Override
        public void run() {
            //System.out.println("I AM IS PRINTLN LINE");

            while(true) {
                String content = null;
                String name = null;
                char[] arr = null;
                int len = 0;
                char c = 0;
                try{
                    arr = new char[200];
                    while(((c = dataInputStream.readChar()) != '\t')) {
                        arr[len] = c;
                        len++;
                    }
                    content = new String(arr, 0 , len);
                    System.out.println(content);
                    len = 0;
                    while(((c = dataInputStream.readChar()) != '\t')) {
                        arr[len] = c;
                        len++;
                    }
                    name = new String(arr, 0 , len);
                    System.out.println(name);
                }catch (IOException e) {
                    e.printStackTrace();
                }
                String data = getdata();
                Msg msg = new Msg(content, Msg.TYPE_RECEIVED, name, data);
                list.add(msg);
                AutoDelete();
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        adapter.notifyDataSetChanged();
                    }
                });
            }


        }
    }
    //点击事件
    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.send:
                //获取输入框的内容
                final String content = inputview.getText().toString();
                //获取当前时间
                String data = getdata();
                if(!"".equals(inputview.getText().toString())) {
                    if(Istrue) {
                        //开启一条线程把数据传递给服务端
                        new Thread(new Runnable() {
                            @Override
                            public void run() {
                                try {
                                    System.out.println(dataOutputStream);
                                    System.out.println(content);
                                    System.out.println(name);
                                    dataOutputStream.writeChars(content);
                                    dataOutputStream.writeChar('\t');
                                    dataOutputStream.writeChars(name);
                                    dataOutputStream.writeChar('\t');
                                } catch (IOException e) {
                                    e.printStackTrace();
                                }
                            }
                        }).start();
                    }else {
                        Toast.makeText(ChatRoom.this, "发送失败", Toast.LENGTH_SHORT).show();
                    }
                    //把发出的信息封装成Msg对象 加入集合中
                    Msg msg = new Msg(content, Msg.TYPE_SEND, name, data);
                    list.add(msg);
                    AutoDelete();
                    //刷新
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            adapter.notifyDataSetChanged();
                        }
                    });
                    //清空编辑栏
                    inputview.setText("");
                }
        }

    }


    //获取时间
    private String getdata() {
        //新建一个时间对象
        Date data = new Date();
        //日期格式化
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd  HH:mm");
        //将给定的日期格式化后加入Data中 并返回该日期格式化后的字符串
        return simpleDateFormat.format(data);
    }

ChatServer

public class ChatServer {
    //自定义端口号
    private final static int port = 9999;
    public static ArrayList<Socket> list;

    public static void main(String[] args) {
        //开启一条线程启动服务器
        new Thread(new startServer()).start();
    }

    static class startServer implements Runnable {

        @Override
        public void run() {
            try {
                ServerSocket serverSocket = new ServerSocket(port);
                list = new ArrayList<>();
                while (true) {
                    Socket socket = serverSocket.accept();      //接受客户端请求
                    System.out.println(socket);
                    //只要有人连接此服务器就将该港口存入list集合中
                    list.add(socket);
                    //开启一条线程传输数据
                    //传入参数 第一个参数是当前的socket 通过它来获取用户传入的数据
                    //第二个是list集合 通过它给每个连接上的用户发送数据
                    new send(socket, list).start();
                }


            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }
}
//发送端线程
class send extends Thread {
    private Socket socket;
    private DataInputStream dataInputStream;
    private DataOutputStream dataOutputStream;
    public ArrayList<Socket> list;
    //有参构造
    public send(Socket socket, ArrayList<Socket> list) {
        this.socket = socket;
        this.list = list;
    }

    @Override
    public void run() {
        try {
            dataInputStream = new DataInputStream(socket.getInputStream());
            while (true) {
                String content;
                String name;
                char[] arr = new char[200];
                int len = 0;
                char c = 0;
                while((c = dataInputStream.readChar()) != '\t'){
                    arr[len] = c;
                    len++;
                }
                content = new String(arr, 0, len);
                System.out.println(content);
                len = 0;
                while((c = dataInputStream.readChar()) != '\t'){
                    arr[len] = c;
                    len++;
                }
                name = new String(arr, 0, len);
                System.out.println(name);

                //遍历集合 拿出每一个连接的Socket 并像他们发送消息
                for(Socket socket : list) {
                    if(socket == this.socket) {
                        continue;
                    }
                    dataOutputStream = new DataOutputStream(socket.getOutputStream());
                    try {
                        dataOutputStream.writeChars(content);
                        dataOutputStream.writeChar('\t');
                        dataOutputStream.writeChars(name);
                        dataOutputStream.writeChar('\t');
                        System.out.println(content);
                        System.out.println(name);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }

                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }


    }
}
  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章           查看所有文章
加:2021-08-08 11:27:20  更:2021-08-08 11:29:31 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/17 11:11:20-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码