Android编程实战——仿微信群聊-3——客户端实现

来源:互联网 发布:多点网络超市 编辑:程序博客网 时间:2024/06/10 01:21

Android编程实战——仿微信群聊-3——客户端实现

项目源代码移步github

客户端类有:Client,ClientMsgThread,MyMessage。
Client用来发送消息,ClientMsgThread是一个不断等待接收消息的线程。

Client类:

public class Client {    private Socket client;    private ObjectOutputStream oos = null;    private ObjectInputStream ois = null;    private LinkedBlockingDeque<MyMessage> msgQueue = null;    private ClientMsgThread clientMsgThread = null;    private final int PORT = 4243;    private final String SERVICE_ADDRESS = "192.168.191.1";    public Client() {        msgQueue = new LinkedBlockingDeque<>(100);    }    /**     * 连接服务器     */    public void connect() {        if (client == null ) {            try {                System.out.println("请求连接服务器...");                client = new Socket(SERVICE_ADDRESS, PORT);                System.out.println("连接服务器成功");                oos = new ObjectOutputStream(client.getOutputStream());                ois = new ObjectInputStream(client.getInputStream());                clientMsgThread = new ClientMsgThread(ois);                clientMsgThread.start();            } catch (IOException e) {                e.printStackTrace();            }        }    }    /**     * 断开连接     */    public void disconnect() {        if (client != null) {            try {                client.close();            } catch (IOException e) {                e.printStackTrace();            }        }    }    /**     * 发送请求连接的消息     * @param name 登录姓名     * @return     */    public boolean login(String name) {        connect();        boolean b =false;        try {            MyMessage myMessage = new MyMessage(MyMessage.MSG_LOGIN, name);            oos.writeObject(myMessage);        } catch (IOException e) {            e.printStackTrace();        }        return b;    }    /**     * 发送语音的消息     * @param filePath     * @param time     */    public void sendAudioFile(String filePath, float time) {        connect();        int length = 0;        double sumL = 0;        byte[] sendBytes;        try {            File file = new File(filePath);            long l = file.length();            //读取文件数据            FileInputStream fis = new FileInputStream(file);            sendBytes = new byte[1024];            System.out.println("开始发送文件");            //发送语音文件的标志信息,表示客户端接下来发送的是语音文件            MyMessage startMessage = new MyMessage(MyMessage.MSG_AUDIO_MARK, "start");            startMessage.setTip(String.valueOf(time));            oos.writeObject(startMessage);            oos.flush();            //发送文件            while ((length = fis.read(sendBytes, 0, sendBytes.length)) > 0) {                MyMessage myMessage = new MyMessage(MyMessage.MSG_AUDIO, sendBytes.clone());                System.out.println("发送长度 " + length);                myMessage.setTip(String.valueOf(length));                oos.writeObject(myMessage);                oos.flush();            }            //文件发送完毕,发送结束标志信息            MyMessage stopMessage = new MyMessage(MyMessage.MSG_AUDIO_MARK, "end");            oos.writeObject(stopMessage);            oos.flush();            System.out.println("文件发送完毕");        } catch (IOException e) {            e.printStackTrace();        }    }    /**     * 发送文本信息     * @param text 文本内容     */    public void sendText(String text) {        connect();        MyMessage myMessage = new MyMessage(MyMessage.MSG_TEXT, text);        try {            System.out.println("发送文本信息: " + text);            oos.writeObject(myMessage);        } catch (IOException e) {            e.printStackTrace();        }    }    public boolean isClosed(){        return client.isClosed();    }}

ClientMsgClient类:

public class ClientMsgThread extends Thread {    private ObjectInputStream ois = null;    public ClientMsgThread(ObjectInputStream ois) {        this.ois = ois;    }    @Override    public void run() {        System.out.println("接收数据线程启动,等待接收");        while (true) {            try {                MyMessage myMessage = (MyMessage)ois.readObject();                System.out.println("接收到服务器传来数据,数据类型:" + myMessage.getMsgType());                int msgType = myMessage.getMsgType();                String content = myMessage.getMsgContent();                String sendName = myMessage.getSendName();                if (msgType == MyMessage.MSG_LOGIN) {                    Message message = new Message();                    message.what = 3;                    Bundle bundle = new Bundle();                    bundle.putString("text",content);                    message.setData(bundle);                    AudioActivity.handler.sendMessage(message);                } else if (msgType == MyMessage.MSG_TEXT) {                    Message message = new Message();                    message.what = 1;                    Bundle bundle = new Bundle();                    bundle.putString("name",sendName);                    bundle.putString("text",content);                    message.setData(bundle);                    AudioActivity.handler.sendMessage(message);                } else if (msgType == MyMessage.MSG_AUDIO_MARK && content.equals("start")) {                    receiveAudio(sendName, Float.valueOf(myMessage.getTip()));                }            } catch (IOException e) {                e.printStackTrace();            } catch (ClassNotFoundException e) {                e.printStackTrace();            }        }    }    private void receiveAudio(String username, float time) {        FileOutputStream fos = null;        String dirPath = AudioFile.RECEIVE_AUDIO_DIR_PATH;        //创建文件夹        File dir = new File(dirPath);        if (!dir.exists()) {            dir.mkdirs();        }        try {            String userName = username;            System.out.println(userName + " " + time);            String filePath = dirPath + "/"  + Time.getTime() + userName + ".amr";            fos = new FileOutputStream(new File(filePath));            byte[] inputByte;            System.out.println("开始接受文件");            while (true) {                MyMessage myMessage = (MyMessage) ois.readObject();                System.out.println(myMessage.getMsgType());                if (myMessage.getMsgType() == MyMessage.MSG_AUDIO_MARK                        && myMessage.getMsgContent().equals("end")) {                    break;                }                int length = Integer.valueOf(myMessage.getTip());                inputByte = myMessage.getMsgContentBinary().clone();                System.out.println("接收长度 " + length);                fos.write(inputByte, 0, length);                fos.flush();            }            System.out.println("完成接收");            System.out.println("文件保存路径:" + filePath);            //显示语音            Message message = new Message();            message.what = 2;            Bundle bundle = new Bundle();            bundle.putString("name",userName);            bundle.putString("filePath",filePath);            bundle.putFloat("time", time);            System.out.println(filePath);            message.setData(bundle);            AudioActivity.handler.sendMessage(message);        } catch (FileNotFoundException e) {            e.printStackTrace();        } catch (IOException e) {            e.printStackTrace();        } catch (ClassNotFoundException e) {            e.printStackTrace();        }    }}

MyMessage就是和之前相同的类。

public class MyMessage implements Serializable{    private static final long serialVersionUID = 1L;    public static final int MSG_AUDIO = 1; //消息类型,语音消息    public static final int MSG_LOGIN = 2; //消息类型,登录消息    public static final int MSG_TEXT = 3; //消息类型,文本消息    public static final int MSG_AUDIO_MARK= 4;// 消息类型,语音消息的标识    private String tip = ""; //额外附带的消息,这里也可以把所有消息放在一起然后通过分隔符区分    private int msgType = -1; //消息类型    private String sendName = ""; //发送者    private String msgContent = ""; //消息内容String    private byte[] msgContentBinary; //消息内容,用来传输文件    // Getter Setter    public String getTip() {        return tip;    }    public void setTip(String tip) {        this.tip = tip;    }    public void setMsgType(int msgType) {        this.msgType = msgType;    }    public void setMsgContent(String msgContent) {        this.msgContent = msgContent;    }    public byte[] getMsgContentBinary() {        return msgContentBinary;    }    public void setMsgContentBinary(byte[] msgContentBinary) {        this.msgContentBinary = msgContentBinary;    }    public void setSendName(String sendName) {        this.sendName = sendName;    }    public int getMsgType() {        return msgType;    }    public String getSendName() {        return sendName;    }    public String getMsgContent() {        return msgContent;    }    /**     * 构造方法     * @param msgType 消息类型     * @param msgContent 消息内容String     */    public MyMessage(int msgType, String msgContent) {        this.msgType = msgType;        this.msgContent = msgContent;    }    public MyMessage() {    }    /**     * 构造方法     * @param msgType 消息类型     * @param msgContentBinary 消息内容,文件数据     */    public MyMessage(int msgType, byte[] msgContentBinary) {        this.msgType = msgType;        this.msgContentBinary = msgContentBinary;    }}

在传输语音文件中需要注意的一点是,用数组传输二进制数据的时候需要说明数据长度。接收的时候才能正确接收。这里我是把数据长度记录在MyMessage中传输过去。

0 0