5

I am doing an Android application where I need 2 devices or more to be able to connect to one device via Bluetooth. The code to connect two devices together in a peer-to-peer form works, but when I try to connect another I get an IOException saying "Connection refused" because the Socket is closed and as such, is unable to complete pairing. The error is shown below.

Socket closed. Unable to complete pairing.
java.io.IOException: Connection refused
    at android.bluetooth.BluetoothSocket.connectNative(Native Method)
    at android.bluetooth.BluetoothSocket.connect(BluetoothSocket.java:216)
    at com.ablueworld.androidgridcomputingframework.BluetoothManager$ConnectAsyncTask.doInBackground(BluetoothManager.java:270)
    at com.ablueworld.androidgridcomputingframework.BluetoothManager$ConnectAsyncTask.doInBackground(BluetoothManager.java:1)
    at android.os.AsyncTask$2.call(AsyncTask.java:264)
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
    at java.util.concurrent.FutureTask.run(FutureTask.java:137)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
    at java.lang.Thread.run(Thread.java:856)
Could not connect to this device

I've then read that it needs to have a different UUID for each connection, is that right? Anyway, I've written my code as shown below, taking a different UUID from an array for each new connection.

    // Unique UUID for this application
    private static int indexUUID = 0;
    private static final UUID[] MY_UUID_SECURE = {UUID.fromString("98b97e6b-62ff-4a36-a81b-82256fd1d168"),
                                                  UUID.fromString("98b97e6b-62ff-4a36-a81b-82256fd1d169"),
                                                  UUID.fromString("98b97e6b-62ff-4a36-a81b-82256fd1d170"),
                                                  UUID.fromString("98b97e6b-62ff-4a36-a81b-82256fd1d171"),
                                                  UUID.fromString("98b97e6b-62ff-4a36-a81b-82256fd1d172")};
    private static final String NAME_SECURE = "GridFrameworkSecure";

    /**
     * Method to connect securely to Bluetooth device using it's MAC address
     * @param macAddress valid Bluetooth MAC address
     */
    public boolean connectSecurelyToDevice(BluetoothAdapter btAdapter, String macAddress){
        BluetoothDevice device = btAdapter.getRemoteDevice(macAddress);
        ConnectAsyncTask connectTask = new ConnectAsyncTask();
        BluetoothSocket deviceSocket = null;
        try {
            deviceSocket = connectTask.execute(device).get();
        } catch (InterruptedException e) {
            e.printStackTrace();
            return false;
        } catch (ExecutionException e) {
            e.printStackTrace();
            return false;
        }
        if(deviceSocket!=null){
            if(serverBluetoothNode==null){
                try {
                    serverBluetoothNode = new BluetoothNode(deviceSocket);
                    Log.i("bluetooth manager", "You are now a slave node.");


                    return true;
                } catch (IOException e) {
                    e.printStackTrace();
                    return false;
                }
            } else {
                Log.e("bluetooth manager", "You already have a master.");
                return false;
            }
        } else return false;
    }

    /**
     * Method to allow this Bluetooth device to accept connection from another Bluetooth device
     */
    public void allowSecureConnectionFromRemoteDevice(BluetoothAdapter btAdapter){
        AcceptConnectionAsyncTask acceptTask = new AcceptConnectionAsyncTask();
        acceptTask.execute(btAdapter);
    }

    private class ConnectAsyncTask extends AsyncTask<BluetoothDevice, Void, BluetoothSocket> {

        @Override
        protected BluetoothSocket doInBackground(BluetoothDevice... params) {
            BluetoothDevice device = params[0];
            BluetoothSocket socket = null;

            // Get a BluetoothSocket for a connection with the
            // given BluetoothDevice
            try {
                socket = device.createRfcommSocketToServiceRecord(MY_UUID_SECURE[indexUUID]);
            } catch (IOException e) {
                Log.e("Bluetooth Pairing", "create() failed", e);
            }

            Log.i("Bluetooth Pairing", "BEGIN ConnectThread SocketType: Secure");

            // Make a connection to the BluetoothSocket
            try {
                // This is a blocking call and will only return on a
                // successful connection or an exception
                socket.connect();
                Log.i("bluetooth manager", "You have connected a slave node to this one.");

                return socket;
            } catch (IOException e) {
                Log.e("Bluetooth Pairing", "Socket closed. Unable to complete pairing.", e);
                // Close the socket
                try {
                    socket.close();
                    indexUUID++;
                } catch (IOException e2) {
                    Log.e("Bluetooth Pairing", "unable to close() socket during connection failure", e2);
                }
            }

            return null;
        }

    }

    private class AcceptConnectionAsyncTask extends AsyncTask<BluetoothAdapter, Void, Void> {

        @Override
        protected Void doInBackground(BluetoothAdapter... params) {
            BluetoothServerSocket serverSocket = null;
            String socketType = "Secure";

            // Create a new listening server socket
            try {
                serverSocket = params[0].listenUsingRfcommWithServiceRecord(NAME_SECURE, MY_UUID_SECURE[indexUUID]);
            } catch (IOException e) {
                Log.e("Accept Bluetooth Pairing Thread", "Socket Type: " + socketType + "listen() failed", e);
                indexUUID++;
            }

            Log.d("Accept Bluetooth Pairing Thread", "Socket Type: " + socketType +
                    "BEGIN mAcceptThread" + this);

            BluetoothSocket socket = null;

            // Listen to the server socket if we're not connected
            while (true) { //mState != STATE_CONNECTED) {
                try {
                    // This is a blocking call and will only return on a
                    // successful connection or an exception
                    socket = serverSocket.accept();
                    Log.i("Slave", "server socket found");                    

                    // If a connection was accepted
                    if (socket != null) {
                        BluetoothNode node = null;
                        try {
                            node = new BluetoothNode(socket);
                            Log.i("connected to", node.getDeviceInformation());
                            slaveBluetoothNodes.add(node);

                            indexUUID++;
                    serverSocket = params[0].listenUsingRfcommWithServiceRecord(NAME_SECURE, MY_UUID_SECURE[indexUUID]);

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

                            indexUUID++;
                            serverSocket = params[0].listenUsingRfcommWithServiceRecord(NAME_SECURE, MY_UUID_SECURE[indexUUID]);
                        }
                    }
                } catch (IOException e) {
                    Log.e("Accept Bluetooth Pairing Thread", "Socket Type: " + socketType + "accept() failed", e);

                    try {
                        indexUUID++;
                        serverSocket = params[0].listenUsingRfcommWithServiceRecord(NAME_SECURE, MY_UUID_SECURE[indexUUID]);
                    } catch (IOException e1) {
                        Log.e("Accept Bluetooth Pairing Thread", "Socket Type: " + socketType + "listen() failed", e1);
                    }
                }


            }
        }

    }

But even so, I get a different error on the third mobile which I'm trying to connect to one that has already a working Bluetooth connection to a second device, as shown below.

 Socket closed. Unable to complete pairing.
 java.io.IOException: Service discovery failed
    at android.bluetooth.BluetoothSocket$SdpHelper.doSdp(BluetoothSocket.java:406)
    at android.bluetooth.BluetoothSocket.connect(BluetoothSocket.java:217)
    at com.ablueworld.androidgridcomputingframework.BluetoothManager$ConnectAsyncTask.doInBackground(BluetoothManager.java:270)
    at com.ablueworld.androidgridcomputingframework.BluetoothManager$ConnectAsyncTask.doInBackground(BluetoothManager.java:1)
    at android.os.AsyncTask$2.call(AsyncTask.java:185)
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:306)
    at java.util.concurrent.FutureTask.run(FutureTask.java:138)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581)
    at java.lang.Thread.run(Thread.java:1019)
 Could not connect to this device

Can anybody help figure this out? Thank you.

Jean-Paul Manuel
  • 546
  • 2
  • 12
  • 29

2 Answers2

0

try calling cancelDiscovery() on your BluetoothAdapter before creating the socket connection. This might solve your problem on the java.io.IOException: Service discovery failed that you are getting.

the-ginger-geek
  • 7,041
  • 4
  • 27
  • 45
0

I've figured out the solution to my problem.

In the method to listen then make the connection, I've written it this way:

UUID[] MY_UUID_SECURE = {UUID.fromString("98b97e6b-62ff-4a36-a81b-82256fd1d168"),
                                                  UUID.fromString("98b97e6b-62ff-4a36-a81b-82256fd1d169"),
                                                  UUID.fromString("98b97e6b-62ff-4a36-a81b-82256fd1d170"),
                                                  UUID.fromString("98b97e6b-62ff-4a36-a81b-82256fd1d171"),
                                                  UUID.fromString("98b97e6b-62ff-4a36-a81b-82256fd1d172")};

BluetoothServerSocket serverSocket = null;
            BluetoothSocket socket = null;

            try {
                // Listen for all UUIDs in array
                for (int i = 0; i < MY_UUID_SECURE.length; i++) {
                    serverSocket = btAdapter.listenUsingRfcommWithServiceRecord(NAME_SECURE, MY_UUID_SECURE[i]);
                    socket = serverSocket.accept();
                    if (socket != null) {
                        BluetoothNode node = null;
                        node = new BluetoothNode(socket);
                        Log.i("connected to", node.getDeviceInformation());
                        slaveBluetoothNodes.add(node);

                        // add node to database
                        databaseManager.insertToGridTree(node.getDeviceAddress(), "slave", "active", node.getDeviceName());
                    }                       
                }
            } catch (IOException e) {
                Log.e("Accept Bluetooth Pairing Thread", "accept() failed", e);
            }

And the method for the slave devices to connect to the master:

    BluetoothDevice device = params[0];
    BluetoothSocket socket = null;

    Log.i("Bluetooth Pairing", "BEGIN ConnectThread SocketType: Secure");

    // Get a BluetoothSocket for a connection with the
    // given BluetoothDevice
    for(int i=0; i<MY_UUID_SECURE.length; i++){
        try {
            socket = device.createRfcommSocketToServiceRecord(MY_UUID_SECURE[i]);
            // This is a blocking call and will only return on a
            // successful connection or an exception
            socket.connect();
            Log.i("bluetooth manager", "You have connected a slave node to this one.");

            return socket;
        } catch (IOException e) {
            Log.e("Bluetooth Pairing", "create() failed", e);
            Log.i("Bluetooth Pairing", "trying another UUID");
            try {
                socket.close();
            } catch (IOException e2) {
                Log.e("Bluetooth Pairing", "unable to close() socket during connection failure", e2);
            }
        }
    }

This project helped me figure this out: https://github.com/polyclef/BluetoothChatMulti

Hope this helps anyone having the same issue. :)

Jean-Paul Manuel
  • 546
  • 2
  • 12
  • 29