上一条消息仍显示在聊天应用程序中

时间:2019-05-25 04:49:14

标签: android bluetooth android-bluetooth

我制作了一个简单的Android蓝牙聊天应用程序。问题在于无论第一条消息的长度如何,如果它长于第二条消息的长度,那么仍然会显示第一条消息的一部分。我猜我没有刷新缓冲区,因此它仍然包含先前的消息。例如,如果我先发送“ First test”,然后发送“ Hi”,则第二部电话将输出显示为“ Hirst test”。

这是主要活动:

package com.example.bluetoothmessenger;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

public class MainActivity extends AppCompatActivity {

    private static final int REQUEST_ENABLE_BT = 2;
    private static final String TAG = "debug";
    private static final int CLIENT_ACTIVITY_REQ_CODE = 1;

    private final String MY_UUID = "250baf40-7bc4-11e9-b475-0800200c9a66";
    String chosenDevice, chosenDeviceMacAddress;
    String[] chosenDeviceDetails;
    String friendlyName;

    Button serverButton, clientButton;
    BluetoothAdapter bluetoothAdapter;

    private Handler handler=new Handler(); // handler that gets info from Bluetooth service

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        friendlyName=bluetoothAdapter.getName();
        if (supportsBT(bluetoothAdapter)) {
            enableBT(bluetoothAdapter);
            bluetoothAdapter.cancelDiscovery();
            serverButton = findViewById(R.id.server_button);
            clientButton = findViewById(R.id.client_button);
            serverButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Server server = new Server();
                    server.start();
                    Toast.makeText(getApplicationContext(), "Server started", Toast.LENGTH_SHORT).show();
                }
            });
            clientButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Intent intent = new Intent(getApplicationContext(), ClientActivity.class);
                    startActivityForResult(intent, CLIENT_ACTIVITY_REQ_CODE);

                }
            });

        }
    }

    // This method is called when the second activity finishes
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        // Check that it is the SecondActivity with an OK result
        if (requestCode == CLIENT_ACTIVITY_REQ_CODE) {
            if (resultCode == RESULT_OK) {

                // Get String data from Intent
                chosenDevice = data.getStringExtra("keyName");
                chosenDeviceDetails = chosenDevice.split(" ");
                int length = chosenDeviceDetails.length;
                chosenDeviceMacAddress = chosenDeviceDetails[length - 1];

                try {
                    BluetoothDevice device = bluetoothAdapter.getRemoteDevice(chosenDeviceMacAddress);
                    Log.d(TAG, "onActivityResult: " + chosenDeviceMacAddress);
                    Client client = new Client(device);
                    client.start();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        } else if (requestCode == REQUEST_ENABLE_BT)
            if (resultCode == RESULT_OK)
                Toast.makeText(this, "Bluetooth enabled", Toast.LENGTH_SHORT).show();
    }

    boolean supportsBT(BluetoothAdapter bluetoothAdapter) {

        if (bluetoothAdapter == null) {
            // Device doesn't support Bluetooth
            Toast.makeText(this, "Bluetooth not supported", Toast.LENGTH_SHORT).show();
            return false;
        }
        return true;
    }

    void enableBT(BluetoothAdapter bluetoothAdapter) {

        if (!bluetoothAdapter.isEnabled()) {
            Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);

        }
    }
    String text;
    ConnectedThread connectedThread;
    private void manageMyConnectedSocket(BluetoothSocket socket) {
        connectedThread = new ConnectedThread(socket);
        connectedThread.start();


        runOnUiThread(new Runnable() {

            @Override
            public void run() {

                final EditText editText;
                Button sendButton;
                setContentView(R.layout.chat_layout);

                editText=findViewById(R.id.edit_text);
                sendButton=findViewById(R.id.send_button);

                sendButton.setOnClickListener( new View.OnClickListener() {

                    @Override
                    public void onClick(View v) {
                        text=editText.getText().toString();
                        if(text!=null)
                            connectedThread.write(text.getBytes());
                    }
                });
            }
        });


    }

    // Defines several constants used when transmitting messages between the
    // service and the UI.
    private interface MessageConstants {
        public static final int MESSAGE_READ = 0;
        public static final int MESSAGE_WRITE = 1;
        public static final int MESSAGE_TOAST = 2;


    }

    private class Client extends Thread {

        private final BluetoothSocket mmSocket;
        private final BluetoothDevice mmDevice;

        public Client(BluetoothDevice device) {
            // Use a temporary object that is later assigned to mmSocket
            // because mmSocket is final.
            BluetoothSocket tmp = null;
            mmDevice  = device;


            try {
                // Get a BluetoothSocket to connect with the given BluetoothDevice.
                // MY_UUID is the app's UUID string, also used in the server code.

                tmp = mmDevice.createRfcommSocketToServiceRecord(UUID.fromString(MY_UUID));
            } catch (IOException e) {
                Log.e(TAG, "Socket's create() method failed", e);
            }
            mmSocket = tmp;
        }

        public void run() {
            BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
            // Cancel discovery because it otherwise slows down the connection.
            bluetoothAdapter.cancelDiscovery();

            try {
                // Connect to the remote device through the socket. This call blocks
                // until it succeeds or throws an exception.
                mmSocket.connect();
            } catch (IOException connectException) {
                // Unable to connect; close the socket and return.
                try {
                    mmSocket.close();
                } catch (IOException closeException) {
                    Log.e(TAG, "Could not close the client socket", closeException);
                }
                return;
            }

            // The connection attempt succeeded. Perform work associated with
            // the connection in a separate thread.
            Log.d(TAG,  "Client Connected to " + mmDevice.getName());
            manageMyConnectedSocket(mmSocket);
        }

        // Closes the client socket and causes the thread to finish.
        public void cancel() {
            try {
                mmSocket.close();
            } catch (IOException e) {
                Log.e(TAG, "Could not close the client socket", e);
            }
        }

    }

    private class Server extends Thread {
        private static final String NAME = "BluetoothMessenger";
        private final BluetoothServerSocket mmServerSocket;


        public Server() {
            // Use a temporary object that is later assigned to mmServerSocket
            // because mmServerSocket is final.
            BluetoothServerSocket tmp = null;
            BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
            try {
                // MY_UUID is the app's UUID string, also used by the client code.
                tmp = bluetoothAdapter.listenUsingRfcommWithServiceRecord(NAME, UUID.fromString(MY_UUID));
            } catch (IOException e) {
                Log.e(TAG, "Socket's listen() method failed", e);
            }
            mmServerSocket = tmp;
        }

        public void run() {
            BluetoothSocket socket = null;
            // Keep listening until exception occurs or a socket is returned.
            while (true) {
                try {
                    socket = mmServerSocket.accept();
                } catch (IOException e) {
                    Log.e(TAG, "Socket's accept() method failed", e);
                    break;
                }

                if (socket != null) {
                    // A connection was accepted. Perform work associated with
                    // the connection in a separate thread.

                    manageMyConnectedSocket(socket);
                    try {
                        mmServerSocket.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    break;
                }
            }
        }


        // Closes the connect socket and causes the thread to finish.
        public void cancel() {
            try {
                mmServerSocket.close();
            } catch (IOException e) {
                Log.e(TAG, "Could not close the connect socket", e);
            }
        }
    }

    private class ConnectedThread extends Thread {
        private final BluetoothSocket mmSocket;
        private final InputStream mmInStream;
        private final OutputStream mmOutStream;
        private byte[] mmBuffer; // mmBuffer store for the stream



        public ConnectedThread(BluetoothSocket socket) {
            mmSocket = socket;
            InputStream tmpIn = null;
            OutputStream tmpOut = null;


            // Get the input and output streams; using temp objects because
            // member streams are final.
            try {
                tmpIn = socket.getInputStream();
            } catch (IOException e) {
                Log.e(TAG, "Error occurred when creating input stream", e);
            }
            try {
                tmpOut = socket.getOutputStream();
            } catch (IOException e) {
                Log.e(TAG, "Error occurred when creating output stream", e);
            }

            mmInStream = tmpIn;
            mmOutStream = tmpOut;
        }

        public void run() {
            mmBuffer = new byte[1024];
            int numBytes; // bytes returned from read()

            final StringBuilder stringBuilder=new StringBuilder();

            // Keep listening to the InputStream until an exception occurs.
            while (true) {
                try {

                    // Read from the InputStream.
                    numBytes = mmInStream.read(mmBuffer);


                    runOnUiThread(new Runnable() {

                                      @Override
                                      public void run() {
                                          String str = new String(mmBuffer);//should I have flushed mmBuffer?
                                          stringBuilder.append(str).append("\n");
                                          TextView tv = findViewById(R.id.message);
                                          tv.setText(stringBuilder.toString());
                                      }
                                  });
                    // Send the obtained bytes to the UI activity.
                    Message readMsg = handler.obtainMessage(
                            MessageConstants.MESSAGE_READ, numBytes, -1,
                            mmBuffer);
                    readMsg.sendToTarget();
                } catch (IOException e) {
                    Log.d(TAG, "Input stream was disconnected", e);
                    break;
                }
            }
        }

        // Call this from the main activity to send data to the remote device.
        public void write(byte[] bytes) {
            try {
                mmOutStream.write(bytes);

                // Share the sent message with the UI activity.
                Message writtenMsg = handler.obtainMessage(
                        MessageConstants.MESSAGE_WRITE, -1, -1, mmBuffer);
                writtenMsg.sendToTarget();
            } catch (IOException e) {
                Log.e(TAG, "Error occurred when sending data", e);

                // Send a failure message back to the activity.
                Message writeErrorMsg =
                        handler.obtainMessage(MessageConstants.MESSAGE_TOAST);
                Bundle bundle = new Bundle();
                bundle.putString("toast",
                        "Couldn't send data to the other device");
                writeErrorMsg.setData(bundle);
                handler.sendMessage(writeErrorMsg);
            }
        }

        // Call this method from the main activity to shut down the connection.
        public void cancel() {
            try {
                mmSocket.close();
            } catch (IOException e) {
                Log.e(TAG, "Could not close the connect socket", e);
            }
        }
    }
}

如何刷新以前的消息?

0 个答案:

没有答案