tom_mai78101
tom_mai78101

Reputation: 2443

Android Bluetooth: Unable to connect to listening socket after generating a random UUID

There are two different instances of my program not being about to connect to a BluetoothServerSocket.

One of the instances has only 1 UUID generated randomly before it initiates scan mode with SCAN_MODE_CONNECTABLE_DISCOVERABLE and before using the same generated UUID to create a BluetoothServerSocket for listening. The other intance generates a random UUID just before a BluetoothDevice tries to connect with the UUID just generated.

Each of the instances cannot complete the Bluetooth connection. Throughout the entire program, I put many Logs just to try and see why it wouldn't be able to connect.

Below is the code for the first instance. (Generate 1 random UUID at the launch of the app.) If anyone likes to download my Eclipse project just to take a look, here's the link of the project from MediaFire. As for the second instance, uncommenting the C-style comments in the code below will reveal it.

I expected the results would be to have a successful connection between two devices. The successful connection connects a device to a listening socket, by using a generated UUID. The observed results show it is unlikely.

As far as I know, the only way to obtain a UUID is to obtain it from UUID.randomUUID(). If there are other ways, please post a comment below, and I'll check it. But for now, it's not the answer I wanted.

Thanks in advance.

package o.p;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.UUID;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

/**
 * The purpose of this app is to create a server-only Bluetooth connection that
 * only accepts incoming Bluetooth connections. It is used only for testing
 * one device that needs Bluetooth tweaking in order to consistently work
 * correctly on the other device. In short, 2 devices are required.
 * */

public class Main extends Activity implements View.OnClickListener {
    //Button
    private Button acceptButton;
    private Button scanButton;

    //Bluetooth stuffs.
    private BluetoothAdapter btAdapter;
    private BluetoothServerSocket serverSocket;
    private BluetoothSocket socket;
    private BluetoothDevice targetDevice;
    private final UUID uuid = UUID.randomUUID();

    /*private UUID randomUUID;*/

    //Accepting thread.
    private class Accept implements Runnable {
        private BluetoothServerSocket socket;
        private BluetoothSocket result = null;

        public Accept(BluetoothServerSocket s) {
            socket = s;
            result = null;
        }

        @Override
        public void run() {
            try {
                Log.d("DEBUG", "Accepting.");
                result = socket.accept();
                Log.d("DEBUG", "Closing server socket.");
                socket.close();
            }
            catch (IOException e) {
                Log.d("DEBUG - onClick(), case Accept", "Unable to accept incoming connection.");
            }
        }

        public BluetoothSocket getSocket() {
            while (result == null);
            return result;
        }
    }

    //Connecting thread.
    private class Connecting implements Runnable {
        private BluetoothDevice device;

        public Connecting(BluetoothDevice d) {
            device = d;
        }

        @Override
        public void run() {
            try {


                   /*Log.d("DEBUG", "Generating a new random UUID.");
                randomUUID = UUID.randomUUID();*/
                Log.d("DEBUG", "Obtaining a socket.");
                BluetoothSocket s = device.createRfcommSocketToServiceRecord(uuid);
                Log.d("DEBUG", "Cancelling discovery, if it's still discovering.");
                if (btAdapter.isDiscovering())
                    btAdapter.cancelDiscovery();
                Log.d("DEBUG", "Connecting to listening socket with UUID: " + uuid.toString());
                s.connect();

            }
            catch (IOException e) {
                Log.d("DEBUG - Connecting.run()", "Unable to connect to the listening socket.");
            }
        }
    }

    //Thread executor
    private ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newCachedThreadPool();

    //BroadcastReceiver for accepting Bluetooth
    private BroadcastReceiver receiver;

    @Override
    public void onCreate(Bundle b) {
        super.onCreate(b);
        setContentView(R.layout.main);
        init();
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.button_accept:
                Log.d("DEBUG", "Pressing the Accept button.");
                Accept acceptThread = new Accept(serverSocket);
                Connecting connectThread = new Connecting(targetDevice);
                if (serverSocket != null) {
                    executor.execute(acceptThread);
                    executor.execute(connectThread);
                    socket = acceptThread.getSocket();
                }
                else {
                    Log.d("DEBUG", "Server socket isn't ready.");
                    Toast.makeText(this, "Server socket isn't ready.", Toast.LENGTH_LONG).show();
                }
                break;
            case R.id.button_scan:
                if (btAdapter.getScanMode() != BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
                    Log.d("DEBUG", "Initiating discovery scan mode.");
                    Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
                    discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
                    this.startActivity(discoverableIntent);
                    Toast.makeText(this, "Being discovered...", Toast.LENGTH_LONG).show();
                }
                if (btAdapter.isDiscovering()) {
                    Toast.makeText(this, "Re-scanning...", Toast.LENGTH_SHORT).show();
                    Log.d("DEBUG", "Re-scanning.");
                    btAdapter.cancelDiscovery();
                }
                Log.d("DEBUG", "Scanning.");
                Toast.makeText(this, "Scanning...", Toast.LENGTH_LONG).show();
                btAdapter.startDiscovery();
                break;
        }
    }

    private void init() {
        Log.d("DEBUG", "Initializing.");
        Log.d("DEBUG", "Button initializing.");
        acceptButton = (Button) findViewById(R.id.button_accept);
        acceptButton.setOnClickListener(this);
        scanButton = (Button) findViewById(R.id.button_scan);
        scanButton.setOnClickListener(this);
        Log.d("DEBUG", "Registering BroadcastReceiver.");
        receiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                String action = intent.getAction();
                if (BluetoothDevice.ACTION_FOUND.equals(action)) {
                    Log.d("DEBUG", "Device has been found.");
                    BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                    Log.d("DEBUG", "Obtained a device from Intent.");
                    if (device.getBondState() == BluetoothDevice.BOND_BONDED) {
                        Log.d("DEBUG", "Removing paired device.");
                        try {
                            Method m = device.getClass().getMethod("removeBond", (Class[]) null);
                            m.invoke(device, (Object[]) null);
                            Log.d("DEBUG", "Removed " + device);
                        }
                        catch (NoSuchMethodException e) {
                            Log.e("ERROR - DeviceReceiver.onReceive()", "", e);
                        }
                        catch (IllegalArgumentException e) {
                            Log.e("ERROR - DeviceReceiver.onReceive()", "", e);
                        }
                        catch (IllegalAccessException e) {
                            Log.e("ERROR - DeviceReceiver.onReceive()", "", e);
                        }
                        catch (InvocationTargetException e) {
                            Log.e("ERROR - DeviceReceiver.onReceive()", "", e);
                        }
                    }
                    else {
                        Log.d("DEBUG", "Obtaining remote device's address.");
                        btAdapter.getRemoteDevice(device.getAddress());
                        try {
                            serverSocket = btAdapter.listenUsingRfcommWithServiceRecord(device.getName(), uuid);
                            Log.d("DEBUG", "Listening to " + device.getName() + "...");
                        }
                        catch (IOException e) {
                            Log.d("DEBUG - onReceive()", "Unable to create a server socket after receiving a broadcast.", e);
                            serverSocket = null;
                            Log.d("DEBUG", "Server socket is set to null.");
                        }
                    }
                    targetDevice = device;
                }
                else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
                    Log.d("DEBUG", "Scanning finished.");
                }
            }
        };
        Log.d("DEBUG", "Creating Bluetooth Adapter.");
        btAdapter = BluetoothAdapter.getDefaultAdapter();
        try {
            Log.d("DEBUG", "Creating a server socket for listening using UUID: " + uuid.toString());
            serverSocket = btAdapter.listenUsingRfcommWithServiceRecord("server", uuid);
        }
        catch (IOException e) {
            Log.d("DEBUG - init()", "Error in creating a server socket from uuid.");
        }
    }

    @Override
    public void onResume() {
        super.onResume();
        //TODO: Not done with the receivers.
        IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
        registerReceiver(receiver, filter);
        filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
        registerReceiver(receiver, filter);
    }

    @Override
    public void onPause() {
        //TODO: Complete this one. Same for onResume().
        super.onPause();
        unregisterReceiver(receiver);
    }
}

Upvotes: 1

Views: 2653

Answers (1)

Dennis Mathews
Dennis Mathews

Reputation: 6975

To be able to connect the UUIDs should match. On the Server side what you are doing is correct i.e generating a ramdom UUID and listening on it, But the client needs to connect using the same UUID that the server is listening on. The way to get it will be from your client use the fetchUuidsWithSdp() on the Server BluetoothDevice object and use the obtained UUID to connect to the server.

Upvotes: 1

Related Questions