0

I'm trying to get two android phones to connect via bluetooth. I'm following the instructions here from the android online howto's, and I'm following pretty closely.

http://developer.android.com/guide/topics/connectivity/bluetooth.html

I can get bluetooth to connect once, but I have to restart the android device or the app itself in order to get it to connect a second time. This is not a problem during development because with each edit of the code the android studio program re-loads the app. It starts it and restarts it, so that during testing I can connect over and over. During actual use I have to restart the android phone or go to the applications manager option under settings and physically stop that app.

From the code below I can connect if I call these lines:

generateDefaultAdapter();
startDiscovery();
startThreadAccept();
startThreadConnect();

How do I get it so that the bluetooth connection can be initiated over and over again? I see the message 'unable to connect' from the inner class 'ConnectThread' and an IO error from a 'printStackTrace()' from that part of the code. The second time I try, I seem to be able to call the method 'stopConnection()' and then the lines above (starting with 'generateDefaultAdapter()') but I find I cannot connect.

package org.test;

//some import statements here...

public class Bluetooth {

    public boolean mDebug = true;
    public BluetoothAdapter mBluetoothAdapter;

    public UUID mUUID  = UUID.fromString(BLUETOOTH_UUID);
    public Thread mAcceptThread;
    public Thread mConnectThread;

    public ConnectedThread mManageConnectionAccept;
    public ConnectedThread mManageConnectionConnect;


    public APDuellingBluetooth() {

    }


    public void generateDefaultAdapter() {
        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        if (mBluetoothAdapter == null) {
            // Device does not support Bluetooth
        }
        if (mBluetoothAdapter != null && !mBluetoothAdapter.isEnabled() ) {
            Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            (mDialogDuel.getActivity()).startActivityForResult(enableBtIntent, INTENT_ACTIVITY_BLUETOOTH_REQUEST_ENABLE);
        }
    }


    public void cancelDiscovery() { if (mBluetoothAdapter != null) mBluetoothAdapter.cancelDiscovery();}
    public void startDiscovery() { mBluetoothAdapter.startDiscovery();}
    public BluetoothAdapter getBluetoothAdapter() {return mBluetoothAdapter;}


    public void stopConnection () {

        try {
            if (mAcceptThread != null) {

                mAcceptThread.interrupt();
                //mAcceptThread.join();
                mAcceptThread = null;
            }

            if (mConnectThread != null) {

                mConnectThread.interrupt();
                //mConnectThread.join();
                mConnectThread = null;
            }

            if (mManageConnectionConnect != null) {
                mManageConnectionConnect.cancel();
                mManageConnectionConnect.interrupt();
                mManageConnectionConnect = null;
            }

            if (mManageConnectionAccept != null) {
                mManageConnectionAccept.cancel();
                mManageConnectionAccept.interrupt();
                mManageConnectionAccept = null;
            }

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


    }



    public void startThreadAccept () {

        if (mAcceptThread != null && !mAcceptThread.isInterrupted()) {
            if (mDebug) System.out.println("server already open");
            //return;
            mAcceptThread.interrupt();
            mAcceptThread = new AcceptThread();

        }
        else {
            mAcceptThread = new AcceptThread();
        }
        if (mAcceptThread.getState() == Thread.State.NEW ){
                //mAcceptThread.getState() == Thread.State.RUNNABLE) {
            mAcceptThread.start();
        }
    }



    public void startThreadConnect () {

        BluetoothDevice mDevice = mBluetoothAdapter.getRemoteDevice(mChosen.getAddress());
        //if (mDebug) System.out.println(mDevice.getAddress() + " -- " + mChosen.getAddress() );

        if (mConnectThread != null && !mConnectThread.isInterrupted()) {
            if (mDebug) System.out.println("client already open");
            //return;
            mConnectThread.interrupt();
            mConnectThread = new ConnectThread(mDevice);
        }
        else {
            mConnectThread = new ConnectThread(mDevice);
        }


        if (mConnectThread.getState() == Thread.State.NEW){// ||
                //mConnectThread.getState() == Thread.State.RUNNABLE) {
            mConnectThread.start();
        }
    }



    public void manageConnectedSocketAccept(BluetoothSocket socket) {


        String mTemp = mBluetoothAdapter.getName();
        if (mDebug) {
            System.out.println("socket accept from " + mTemp);
            System.out.println("info accept " + socket.getRemoteDevice().toString());
        }
        if (mManageConnectionAccept != null && !mManageConnectionAccept.isInterrupted()) {
            //mManageConnectionAccept.cancel();
            //mManageConnectionAccept.interrupt();
            if (mAcceptThread == null) System.out.println(" bad thread accept");
        }
        else {
            mManageConnectionAccept = new ConnectedThread(socket, "accept");
        }

        if (mManageConnectionAccept.getState() == Thread.State.NEW ){//||
                //mManageConnectionAccept.getState() == Thread.State.RUNNABLE) {
            mManageConnectionAccept.start();
        }

    }

    public void manageConnectedSocketConnect(BluetoothSocket socket) {


        String mTemp = mBluetoothAdapter.getName();
        if (mDebug) {
            System.out.println("socket connect from " + mTemp);
            System.out.println("info connect " + socket.getRemoteDevice().toString());

        }

        if (mManageConnectionConnect != null && !mManageConnectionConnect.isInterrupted()) {
            //mManageConnectionConnect.cancel();
            //mManageConnectionConnect.interrupt();
            if (mConnectThread == null) System.out.print(" bad thread connect ");
        }
        else {
            mManageConnectionConnect = new ConnectedThread(socket, "connect");
        }
        if (mManageConnectionConnect.getState() == Thread.State.NEW){// ||
                //mManageConnectionConnect.getState() == Thread.State.RUNNABLE) {
            mManageConnectionConnect.start();
        }
    }




    public void decodeInput (String mIn, ConnectedThread mSource) {
        // do something with info that is returned to me...

    }

    public void encodeOutput (String mMac1, String mMac2, int mLR1, int mLR2) {


        String mTemp = composeOutputString ( mServer, mMac1,mMac2, mLR1, mLR2);


        if (mManageConnectionConnect != null && mManageConnectionConnect.isConnected()) {
            mManageConnectionConnect.write(mTemp.getBytes());
            mManageConnectionConnect.flush();

        }
        if (mManageConnectionAccept != null && mManageConnectionAccept.isConnected()) {
            mManageConnectionAccept.write(mTemp.getBytes());
            mManageConnectionAccept.flush();
        }

        mTemp = composeOutputString ( mClient, mMac1,mMac2, mLR1, mLR2);


        if (mManageConnectionConnect != null && mManageConnectionConnect.isConnected()) {
            mManageConnectionConnect.write(mTemp.getBytes());
            mManageConnectionConnect.flush();
        }
        if (mManageConnectionAccept != null && mManageConnectionAccept.isConnected()) {
            mManageConnectionAccept.write(mTemp.getBytes());
            mManageConnectionAccept.flush();
        }
    }

    public String composeOutputString (SocketConnectData mData, String mMac1, String mMac2, int mLR1, int mLR2) {

        // make a string here with the data I want to send...
        String mTemp = new String();
        return mTemp;
    }



    /////////////////////////////////////////////
    private class AcceptThread extends Thread {
        private final BluetoothServerSocket mmServerSocket;
        private boolean mLoop = true;

        public AcceptThread() {


            // Use a temporary object that is later assigned to mmServerSocket,
            // because mmServerSocket is final
            mLoop = true;

            BluetoothServerSocket tmp = null;
            try {
                // MY_UUID is the app's UUID string, also used by the client code
                tmp = mBluetoothAdapter.listenUsingRfcommWithServiceRecord(mServiceNameReceive, mUUID );
            } catch (IOException e) {
                System.out.println("rfcomm problem ");
            }
            mmServerSocket = tmp;
        }

        public void run() {
            BluetoothSocket socket = null;
            // Keep listening until exception occurs or a socket is returned
            while (mLoop) {
                try {
                    if (mmServerSocket != null) {
                        socket = mmServerSocket.accept();
                    }
                } catch (IOException e) {
                    if (mDebug) System.out.println("rfcomm accept problem");
                    e.printStackTrace();
                    break;
                }
                // If a connection was accepted
                if (socket != null && ! isConnectionOpen() ) {
                    // Do work to manage the connection (in a separate thread)
                    manageConnectedSocketAccept(socket);
                    try {
                        mmServerSocket.close();

                    }
                    catch (IOException e) {}
                    break;
                }
            }
        }

        /** Will cancel the listening socket, and cause the thread to finish */
        public void cancel() {
            try {
                mLoop = false;
                mmServerSocket.close();
            } catch (IOException e) { }
        }
    }
    /////////////////////////////////////////////

    private class ConnectThread extends Thread {
        //private final BluetoothSocket mmSocket;
        private BluetoothSocket mmSocket;
        private final BluetoothDevice mmDevice;

        public ConnectThread(BluetoothDevice device) {


            // Use a temporary object that is later assigned to mmSocket,
            // because mmSocket is final
            BluetoothSocket tmp = null;
            mmDevice = device;

            try {

                tmp = device.createRfcommSocketToServiceRecord(mUUID);


                if (mDebug) System.out.println("connect -- rf socket to service record " + tmp);

            } catch (Exception e) {
                System.out.println("exception -- rf socket to service record problem " + tmp);

            }
            mmSocket = tmp;
        }

        public void run() {
            // Cancel discovery because it will slow down the connection
                mBluetoothAdapter.cancelDiscovery();


            try {
                // Connect the device through the socket. This will block
                // until it succeeds or throws an exception

                mmSocket.connect();

            }
            //catch (InterruptedException e ) {System.out.println("interrupted exception");}

            catch (IOException e) {
                // Unable to connect; close the socket and get out
                if (mDebug) System.out.println("unable to connect ");

                e.printStackTrace(); //   <---- I see output from this spot!!



                try {
                    mmSocket.close();
                } catch (IOException closeException) {
                    System.out.println("unable to close connection ");
                }

                return;
            }


            // Do work to manage the connection (in a separate thread)
            if (mmSocket.isConnected() && ! isConnectionOpen()) {
                manageConnectedSocketConnect(mmSocket);
            }
        }

        /** Will cancel an in-progress connection, and close the socket */
        public void cancel() {
            try {
                mmSocket.close();
            } catch (IOException e) { }
        }

        public boolean isConnected() {
            return mmSocket.isConnected();
        }
    }

    /////////////////////////////////////////////
    private class ConnectedThread extends Thread {
        private final BluetoothSocket mmSocket;
        private final InputStream mmInStream;
        private final OutputStream mmOutStream;
        public String mTypeName = "";

        private boolean mLoop = true;

        public StringWriter writer;

        public ConnectedThread(BluetoothSocket socket, String type) {
            mTypeName = type;
            mLoop = true;

            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();
                tmpOut = socket.getOutputStream();
            } catch (IOException e) { }

            mmInStream = tmpIn;
            mmOutStream = tmpOut;

            try {


                writer = new StringWriter();
            }
            catch (Exception e) {}

        }

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

            int bytes; // bytes returned from read()
            String [] mLines ;



            // Keep listening to the InputStream until an exception occurs
            while (mLoop) {
                try {
                    // Read from the InputStream
                    bytes = mmInStream.read(buffer);

                    if (bytes == -1 || bytes == 0) {
                        if (mDebug) System.out.println("zero read");
                        return;
                    }

                    writer.append(new String(buffer, 0, bytes));

                    mLines = writer.toString().split("!");

                    if (mDebug) System.out.println( "lines " +mLines.length);

                    for (int i = 0; i < mLines.length; i ++ ) {


                        if (true) {
                            if (mDebug) System.out.println("  " + mLines[i]);
                            decodeInput (mLines[i], this);


                        }

                    }


                } catch (Exception e) {
                    e.printStackTrace();
                    if (mDebug) System.out.println("read buffer problem");
                    break;
                }
            }
        }

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

                mmOutStream.write(bytes);


            } catch (IOException e) {
                e.printStackTrace();
                if (mDebug) System.out.println("bad write");
            }
        }

        /* Call this from the main activity to shutdown the connection */
        public void cancel() {
            try {
                mLoop = false;
                mmSocket.close();
                mmOutStream.close();
                mmInStream.close();
            } catch (IOException e) { }
        }

        public boolean isConnected() {
            boolean mIsOpen = false;
            try {
                mIsOpen = mmSocket.isConnected() ;
            } catch (Exception e) {}
            return mIsOpen;
        }

        public void flush() {
            try {
                mmOutStream.flush();
            }
            catch (IOException e) {e.printStackTrace();}
        }
    }

    ///////////////////////////////////////////////
}

Thanks for your time.

EDIT: this is the error msg:

W/System.err﹕ java.io.IOException: read failed, socket might closed or timeout, read ret: -1
W/System.err﹕ at android.bluetooth.BluetoothSocket.readAll(BluetoothSocket.java:553)
W/System.err﹕ at android.bluetooth.BluetoothSocket.waitSocketSignal(BluetoothSocket.java:530)
W/System.err﹕ at android.bluetooth.BluetoothSocket.connect(BluetoothSocket.java:357)
W/System.err﹕ at org.davidliebman.test.Bluetooth$ConnectThread.run(Bluetooth.java:761)
D Liebman
  • 337
  • 1
  • 8
  • 17

1 Answers1

0

Try this: Instead of restarting the app. Turn off the Bluetooth on the Android device and turn it back on after a 5-sec delay. If you could make the connection successfully, it typically a sign that you did not close the connection and socket completely. Log your code. Make sure the closing socket routine is smoothly executed. Check if the IOException you have in your cancel method of your ConnectedThread is not catching any exception:

    /* Call this from the main activity to shutdown the connection */
    public void cancel() {
        try {
            // ADD LOG
            mLoop = false;
            mmSocket.close();
            mmOutStream.close();
            mmInStream.close();
            // ADD LOG
        } catch (IOException e) { 
            // ADD LOG}
    }
Kasra
  • 3,045
  • 3
  • 17
  • 34
  • Toggling bluetooth does allow the app to run a second time. I am trying to add log statements to the `cancel()` method. – D Liebman Jan 18 '15 at 15:18
  • It seems that the cancel() method is never called. When I add log statements to that part of the code I never see them. I don't know what to do about that. I even tried to add a button to my UI that called finish(). My thought was that I could manually restart the whole app more easily with a button that called 'finish()'. Unfortunately it didn't work. The app has to be restarted anyway from the application manager of the system program, even after executing finish() successfully. – D Liebman Jan 18 '15 at 20:19
  • My suggestion is to avoid restrating the app. All you need to do is to properly back track why the cancel method is not called. I can see you have a stopConnection() method which calls the cancel method. However, what I am not sure about is which thread is your connection on. Maybe try adding the cancel() method to mConnectThread, and mAcceptThread in stopConnection() . – Kasra Jan 18 '15 at 21:38
  • I was looking at this question but nothing I tried from that page helped my situation: http://stackoverflow.com/questions/22022001/android-bluetooth-connection-fails-after-489-successful-connections – D Liebman Jan 19 '15 at 16:00