如何解决蓝牙connect()套接字失败的问题可能是关闭的

时间:2019-07-03 15:26:46

标签: android sockets bluetooth android-bluetooth

我正在尝试制作一个与附近设备通信的应用程序。 我的应用程序由要求启用蓝牙并设置可发现模式的主要活动组成,因此它等待建立连接。

第二项活动是寻找附近的设备并进行配对。 配对之后,交换一些配置消息,然后两者都启动处理两个设备之间通信的ThirdActivity。

我可以成功交换这些消息,但是问题是我需要将BluetoothService对象(保留通信信息)传递给Third Activity。

由于我认为我无法实现可拆分的,因此我只是在不消除配对的情况下关闭了连接,然后通过创建一个新的BluetoothService对象但始终传递相同的BluetoothDevice来在thirdActivity中重新创建AcceptThread和ConnectThread。

从各种日志中可以看到,AcceptThread等待accept(),而ConnectThread使connect()无法报告此错误。

W/System.err: java.io.IOException: read failed, socket might closed or timeout, read ret: -1
        at android.bluetooth.BluetoothSocket.readAll(BluetoothSocket.java:762)
        at android.bluetooth.BluetoothSocket.readInt(BluetoothSocket.java:776)
        at android.bluetooth.BluetoothSocket.connect(BluetoothSocket.java:399)
        at com.crossthebox.progetto.BluetoothService$ConnectThread.run(BluetoothService.java:118)

我该怎么办?

这是BluetoothService类

public class BluetoothService {
    private UUID myid = UUID.fromString("fa87c0d0-afac-11de-8a39-0800200c9a66");
    private static final String appName = "myapp";

    private static final int STATE_NONE = 0;       // we're doing nothing
    private static final int STATE_LISTEN = 1;     // now listening for incoming connections
    private static final int STATE_CONNECTING = 2; // now initiating an outgoing connection
    private static final int STATE_CONNECTED = 3;
    private static final int STATE_BUFFER_NOT_EMPTY = 4;
    private String message ="";

    private int mState;
    private final BluetoothAdapter mBluetoothAdapter;
    Context mContext;

    private AcceptThread mAcceptThread;

    private ConnectThread mConnectThread;
    private BluetoothDevice mDevice;
    private UUID deviceUUID;


    private ConnectedThread mConnectedThread;

    public BluetoothService(Context context) {
        mContext = context;
        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        mState = STATE_NONE;
    }

    private class AcceptThread extends Thread {

        private final BluetoothServerSocket bluetoothServerSocket;

        public AcceptThread(){
            BluetoothServerSocket tmp = null;

            try{
                tmp = mBluetoothAdapter.listenUsingRfcommWithServiceRecord(appName, myid);
            }catch (IOException e){

            }
            bluetoothServerSocket = tmp;
            mState  = STATE_LISTEN;
        }

        public void run() {
            BluetoothSocket socket = null;

            try {
                socket = bluetoothServerSocket.accept();

            } catch (IOException e) {

            }
            if (socket != null) {
                mState = STATE_CONNECTING;
                connected(socket);
            }
        }

        public void cancel() {
            try {
                bluetoothServerSocket.close();
            } catch (IOException e) {
            }
        }
    }

    private class ConnectThread extends Thread {
        private BluetoothSocket mSocket;

        public ConnectThread(BluetoothDevice device, UUID uuid) {
            mDevice = device;
            deviceUUID = uuid;
        }

        public void run(){
            BluetoothSocket tmp = null;
            // Get a BluetoothSocket for a connection with the
            // given BluetoothDevice
            try {
               tmp = mDevice.createRfcommSocketToServiceRecord(deviceUUID);
            } catch (IOException e) {

            }
            mSocket = tmp;

            mBluetoothAdapter.cancelDiscovery();

            try {
                mSocket.connect(); //this throws exception for socket close ( but only the second time)
            } catch (IOException e) {
                // Close the socket
                try {
                    mSocket.close();
                } catch (IOException e1) {
                }
                e.printStackTrace();
            }
            connected(mSocket);
        }
        public void cancel() {
            try {
                mSocket.close();
            } catch (IOException e) {
            }

        }
    }

    public synchronized void start() {
        if (mConnectThread != null) {
            mConnectThread.cancel();
            mConnectThread = null;
        }
        if (mAcceptThread == null) {
            mAcceptThread = new AcceptThread();
            mAcceptThread.start();
        }
    }


    public void startClient(BluetoothDevice device,UUID uuid){
        mConnectThread = new ConnectThread(device, uuid);
        mConnectThread.start();
    }

    private class ConnectedThread extends Thread {
        private final BluetoothSocket mSocket;
        private final InputStream mInStream;
        private final OutputStream mOutStream;

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

            try {
                tmpIn = mSocket.getInputStream();
                tmpOut = mSocket.getOutputStream();
            } catch (IOException e) {
                e.printStackTrace();
            }

            mInStream = tmpIn;
            mOutStream = tmpOut;
        }

        public void run(){
            byte[] buffer = new byte[1024];

            int bytes; // bytes returned from read()

            // Keep listening to the InputStream until an exception occurs
            while (true) {
                // Read from the InputStream
                try {
                    bytes = mInStream.read(buffer);
                    if(bytes != 0) {
                        String incomingMessage = new String(buffer, 0, bytes);
                        message = incomingMessage;
                        System.out.println("HO LETTO " + message);
                        mState = STATE_BUFFER_NOT_EMPTY;
                    }
                } catch (IOException e) {
                    break;
                }
            }
        }

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

            }
        }

        //termina la connessione
        public void cancel() {
            try {
                mSocket.close();
            } catch (IOException e) { }
        }
    }

    private void connected(BluetoothSocket mSocket) {
        // Start the thread to manage the connection and perform transmissions
        mConnectedThread = new ConnectedThread(mSocket);
        mConnectedThread.start();
        mState = STATE_CONNECTED;

    }

    public void write(byte[] out) {
        // Create temporary object
        ConnectedThread r;
        // Synchronize a copy of the ConnectedThread
        synchronized (this) {
            if (mState != STATE_CONNECTED) {
                return;}
            r = mConnectedThread;
        }
        // Perform the write unsynchronized
        r.write(out);
    }

    public int getState(){

        return mState;
    }
    public String getMessage(){
        String tmp = null;
        if(!message.equals("")){
            tmp = message;
            message = "";
        }
        mState = STATE_CONNECTED;
        return tmp;
    }
    public void setState(int state){
        this.mState = state;
    }

    public void cancel(){
        if(mAcceptThread != null) {
            mAcceptThread.cancel();
            mAcceptThread = null;
        }
        if(mConnectThread != null) {
            mConnectThread.cancel();
            mConnectThread = null;
        }
        if(mConnectedThread != null) {
            mConnectedThread.cancel();
            mConnectedThread = null;
        }
    }
}

MainActivity

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_transition);
        /* * */

    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        /* * */
        if(requestCode == DISCOVER_REQUEST){
            if(resultCode ==  120){

                bluetoothService = new BluetoothService(this);
                bluetoothService.start();

                //after receiving some message correctly
                Intent thirdActivity = new Intent(this, com.project.ThirdActivity.class);
                bluetoothService.cancel();
                this.startActivity(thirdActivity);
                finish();
            }
            if(resultCode == RESULT_CANCELED){
                finish();
            }
        }
    }

}

SecondActivity我取消连接的方式与MainActivity几乎相同。我在收到一些消息后关闭了套接字,然后启动ThirdActivity

ThirdActivity

if(mode == CLIENT){
    BluetoothDEvice bluetoothDevice = getIntent().getExtras().getParcelable("btdevice");
    bluetoothService.startClient(bluetoothDevice,myid);
}else //SERVER
    bluetoothService.start();

1 个答案:

答案 0 :(得分:0)

可能的解决方案:

  1. 将选定的MAC地址从Activity2传递到Activity3
  2. 在Activity3中,启动Bluetooth服务中的ConnectThread。
  3. 使用处理程序在服务和Activity3之间进行通信。
  4. 请确保在套接字断开连接时关闭线程。

以下链接是一个出色的例子:

https://github.com/googlesamples/android-BluetoothChat