JayJona
JayJona

Reputation: 502

how to solve bluetooth connect() fails socket might be close

I'm trying to make an app that communicates with nearby devices. My app is composed of the main activity that asks to enable bluetooth and sets the discoverable mode, so it waits for a connection to be made.

The second activity takes care of finding nearby devices and making the pairing. After pairing pairing some configuration messages are exchanged and then both start a ThirdActivity that deals with the communication between the two devices.

I can successfully exchange these messages but the problem is that I need to pass the BluetoothService object (which keeps the communication information) to the Third Activity.

Since I don't think I can implement parcelable then I simply closed the connection without eliminating the pairing and then recreate AcceptThread and ConnectThread in the thirdActivity by creating a new BluetoothService object but always passing the same BluetoothDevice.

From the various logs what happens is that the AcceptThread waits on the accept(), while the ConnectThread fails the connect() reporting this error.

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)

What can I do?

This is the BluetoothService Class

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 the way I cancel the connection is pretty the same as MainActivity. I close the socket after some message and then start ThirdActivity

ThirdActivity

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

Upvotes: 1

Views: 1308

Answers (1)

kavin pandian
kavin pandian

Reputation: 11

Possible solution:

  1. Pass the selected MAC address from Activity2 to Activity3
  2. In Activity3 Start the ConnectThread in the Bluetooth Service.
  3. Use a Handler to communicate between service and the Activity3.
  4. Make sure you close the Thread when sockets disconnect.

A brilliant example is in the following link:

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

Upvotes: 1

Related Questions