1

I'm doing some stuff with bluetooth on android and I would like to connect to one of the discovered devices and open a socket connection towards it.

I've granted all of the needed permissions: Bluetooth, Bluetooth_Admin, Access_Fine_Location and Access_Coarse_Location and ask for them before I do anything with bluetooth.

Now, I've discovered some devices with adapter.startDiscovery(); and activity.registerReceiver(receiver, filter);

In the receiver finds a device of a certain name, I try connecting to it like this:

            adapter.cancelDiscovery();
            Log.d(TAG, "Create Bond");
            device.createBond();
            try {
                socket = device.createRfcommSocketToServiceRecord(uuid);
                Log.d(TAG, "Sleep 10");
                sleep(10000);
                Log.d(TAG, "Create Socket");
                //socket = device.createInsecureRfcommSocketToServiceRecord(uuid);
                Log.d(TAG, "Connect socket");
                socket.connect();
                Log.d(TAG, "Connecting Done");
            } catch (Exception e) {
                Log.d(TAG, "Failed to connect to device", e);
                try {
                    socket.close();
                } catch (Exception e2) {
                    Log.d(TAG, "Failed to close socket", e2);
                }
            }

This is a test code with which I'm trying to create a socket and open a connection.

I get the following Exception on .connect():

java.io.IOException: read failed, socket might closed or timeout, read ret: -1 at android.bluetooth.BluetoothSocket.readAll(BluetoothSocket.java:684) at android.bluetooth.BluetoothSocket.readInt(BluetoothSocket.java:696) at android.bluetooth.BluetoothSocket.connect(BluetoothSocket.java:373)

What am I doing wrong.

The bluetooth device I connect to is a Android mobile device, but I plan on using others when I manage to get the connection.

Update1: Android version is 7.0

Invader Zim
  • 796
  • 2
  • 14
  • 39

3 Answers3

2

use fetchUuidsWithSdp() and getUuids() to find all the published services and their associated UUID values.

Abdelrahman Saed
  • 382
  • 4
  • 13
  • 1
    Sorry, can you elaborate a bit please? Forgot to mention it, I generate a random UUID with UUID.randomUUID(); – Invader Zim Sep 12 '19 at 15:09
  • Oh wait, should I use devices UUID? I figured that the UUID variable in createRF..Socket(uuid) was my UUID, not the devices? – Invader Zim Sep 12 '19 at 15:11
0

You don't need to call device.createBond(); to connect to a Bluetooth device.

Try removing this line. Also check, that your phone is not already paired with the device you're trying to connect to. You can check that on the Bluetooth settings screen (open it with a long press on the Bluetooth icon on your smartphone.

Here is a sample code to initiates a Bluetooth connection :

private class ConnectThread extends Thread {
    private final 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 {
            // Get a BluetoothSocket to connect with the given BluetoothDevice.
            // MY_UUID is the app's UUID string, also used in the server code.
            tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
        } catch (IOException e) {
            Log.e(TAG, "Socket's create() method failed", e);
        }
        mmSocket = tmp;
    }

    public void run() {
        // Cancel discovery because it otherwise slows down the connection.
        bluetoothAdapter.cancelDiscovery();

        try {
            // Connect to the remote device through the socket. This call blocks
            // until it succeeds or throws an exception.
            mmSocket.connect();
        } catch (IOException connectException) {
            // Unable to connect; close the socket and return.
            try {
                mmSocket.close();
            } catch (IOException closeException) {
                Log.e(TAG, "Could not close the client socket", closeException);
            }
            return;
        }

        // The connection attempt succeeded. Perform work associated with
        // the connection in a separate thread.
        manageMyConnectedSocket(mmSocket);
    }

    // Closes the client socket and causes the thread to finish.
    public void cancel() {
        try {
            mmSocket.close();
        } catch (IOException e) {
            Log.e(TAG, "Could not close the client socket", e);
        }
    }
}

This code is from Android official doc: https://developer.android.com/guide/topics/connectivity/bluetooth#ConnectAsAClient

matdev
  • 4,115
  • 6
  • 35
  • 56
  • 1
    Hmmm, does connect use it? Because the exception is triggered on the .connect() line, I don't use readCharacteristic() – Invader Zim Sep 12 '19 at 15:46
  • Why shouldn't I use device.createBond()? Btw, I may have figured it out, as I'm calling a socket creation, there should be another server socket on the other side that receives this connection yes? And I didn't have it. – Invader Zim Sep 13 '19 at 09:48
  • I confirm that you don't need to be paired with the device to connect to it. Check out my answer with sample code from official doc. Your bluetooth peripheral device should be BLE advertising and not currently BLE connected. – matdev Sep 13 '19 at 10:22
  • I actually first tried this code and I got the same error. I will try it again. – Invader Zim Sep 13 '19 at 11:26
  • Update: I tried this code and I get the same error. – Invader Zim Sep 13 '19 at 11:32
  • 1
    What version of Android runs on the device you're trying to connect to ? Have you checked this answer: https://stackoverflow.com/a/25647197/2068732 – matdev Sep 13 '19 at 12:33
  • I added the fallback code, and I still get the same error on both connects. I checked the Blueetooth type and its Classic. Added android version to the question, its 7.0 – Invader Zim Sep 13 '19 at 13:16
  • Are you sure the Android device is in peripheral mode ? Can you discover its mac address ? This tut can help you https://code.tutsplus.com/tutorials/how-to-advertise-android-as-a-bluetooth-le-peripheral--cms-25426 – matdev Sep 13 '19 at 13:35
0

I wrote another code instead of what I was using for server side.

            Log.d(TAG,"Start server");
            BluetoothServerSocket serverSocket = null;
            try {
                serverSocket = adapter.listenUsingRfcommWithServiceRecord("ime", uuid);
            } catch (Exception e) {
                e.printStackTrace();
            }

            while (true) {
                try {
                    serverSocket.accept();
                } catch (Exception e) {
                    e.printStackTrace();

                }
            }

I used this code inside of a thread which starts instead of calling the code from the question.

Installing the App with server code on one app and calling "connect" on socket did the trick. I used the same UUID (previous was random generated, new one was static from string).

Invader Zim
  • 796
  • 2
  • 14
  • 39