Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bluetooth : Service discovery failed

I try to establish a Bluetooth connection between my Android App (on a Samsung phone running 4.1.2: the client) and my Laptop (Win7, 64bits: the server). It has always failed with a Service discovery failed.

I read various topics about this (here and there) but it didn't solve my problem.

I have two questions:

  • what means the well known UUID "00001101-0000-1000-8000-00805F9B34FB" . Why/when should it be used ?
  • any suggestion to investigate/solve my problem would be appreciated.

Remarks:

  • I tried to establish a secured and unsecured connection (same failure with both)
  • I'm able to pair my laptop and my device from Settings>Bluetooth
  • As suggested in comments : I tried with a randomly generated UUID (but the same on both side) instead of the well known one, but I still have exactly the same behavior.

I have those permissions

<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>

EDIT

Instead of harcoding the UUID on client side, I tried the following (but still get the same error):

UUID uuid = bluetoothDevice.getUuids()[bluetoothDevice.getUuids().length-1].getUuid();

The UUID of the echo-server is always the last one in the array.

END EDIT

Here are the relevant logs on the client:

08-22 12:30:28.627: ERROR/BluetoothService.cpp(12008): stopDiscoveryNative: D-Bus error in StopDiscovery: org.bluez.Error.Failed (Invalid discovery session)
08-22 12:30:28.647: INFO/BluetoothSocket.cpp(18030): Setting Master socket option
08-22 12:30:28.647: VERBOSE/BluetoothSocket.cpp(18030): ...fd 43 created (RFCOMM, lm = 7)
08-22 12:30:28.687: DEBUG/BluetoothPolicyService(12008): getAllowBluetoothDataTransfer - showMsg: true
08-22 12:30:28.687: DEBUG/BluetoothPolicyService(12008): MDM: isProfileEnabled = true
08-22 12:30:28.697: DEBUG/BluetoothUtils(18030): isSocketAllowedBySecurityPolicy start : device null
08-22 12:30:28.727: ERROR/BluetoothEventLoop.cpp(12008): onCreateDeviceResult: D-Bus error: org.bluez.Error.AlreadyExists (Already Exists)
08-22 12:30:28.727: VERBOSE/BluetoothService.cpp(12008): discoverServicesNative
08-22 12:30:28.727: VERBOSE/BluetoothService.cpp(12008): ... Object Path = /org/bluez/12635/hci0/dev_00_09_DD_50_88_54
08-22 12:30:28.727: VERBOSE/BluetoothService.cpp(12008): ... Pattern = , strlen = 0
08-22 12:30:29.138: VERBOSE/BluetoothEventLoop.cpp(12008): event_filter: Received signal org.bluez.Device:PropertyChanged from /org/bluez/12635/hci0/dev_00_09_DD_50_88_54
08-22 12:30:29.138: DEBUG/BluetoothEventLoop(12008): Device property changed
08-22 12:30:32.141: DEBUG/BluetoothA2DPStateReceiver(15827): BluetoothA2DPStateReceiver constructor call()
08-22 12:30:32.141: DEBUG/BluetoothA2DPStateReceiver(15827): onReceive(): action = android.bluetooth.device.action.ACL_CONNECTED
08-22 12:30:32.141: DEBUG/BluetoothA2DPStateReceiver(15827): ACTION_ACL_CONNECTED
08-22 12:30:32.141: DEBUG/BluetoothA2DPSinkInfo(15827): checkBlackListCarkit() : isBlackListCarkit false
08-22 12:30:32.161: DEBUG/BluetoothNotiBroadcastReceiver(15910): onReceive
08-22 12:30:40.749: ERROR/Bluetooth(18030): Cannot connect
    java.io.IOException: Service discovery failed
    at android.bluetooth.BluetoothSocket$SdpHelper.doSdp(BluetoothSocket.java:475)
    at android.bluetooth.BluetoothSocket.connect(BluetoothSocket.java:241)
    at com.company.BlueToothTestActivity.open(BlueToothTestActivity.java:48)
    at com.company.BlueToothTestActivity$1.run(BlueToothTestActivity.java:29)
08-22 12:30:40.749: WARN/Bluetooth(18030): Unable to open connection !

Here is the code to reproduce the error (it's simplified version, it compiles and reproduce the error - at least on my hardware -)

Client

import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;

import java.io.IOException;
import java.util.UUID;

public class BlueToothTestActivity extends Activity {

private String macAddress = "00:09:DD:50:88:54";  //hardcoded laptop macAddress
private BluetoothAdapter mBluetoothAdapter;
private BluetoothDevice bluetoothDevice;
private BluetoothSocket socket;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);   
    Thread bluetoothClientThread = new Thread(){
        @Override
        public void run() {
            if(open()){
                Log.i("Bluetooth","Connection is open !");
            }else{
                Log.w("Bluetooth","Unable to open connection !");
            }
        }
    };
    bluetoothClientThread.start();
    initUI();
}

public boolean open() {
    mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
    bluetoothDevice = mBluetoothAdapter.getRemoteDevice(macAddress);
    String BT_UUID = "00001101-0000-1000-8000-00805F9B34FB";
    try {
        mBluetoothAdapter.cancelDiscovery();
        //socket = bluetoothDevice.createInsecureRfcommSocketToServiceRecord(UUID.fromString(BT_UUID));
        socket = bluetoothDevice.createRfcommSocketToServiceRecord(UUID.fromString(BT_UUID));
        socket.connect(); //Block 12 sec here, then throw the exception.
        return true;
    } catch (IOException e) {
        try {
            socket.close();
        } catch (IOException closeException) { }
        Log.e("Bluetooth", "Cannot connect", e);
        return false;
    }
}

private void initUI(){
    LinearLayout linearLayout = new LinearLayout(this);
    Button finish = new Button(this);
    finish.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            if(socket!=null){
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            BlueToothTestActivity.this.finish();
        }
    });
    finish.setText("Exit");
    linearLayout.addView(finish);
    setContentView(linearLayout);
}
}

The server is a simple echo server (based on Bluecove library, I took the code from here : http://www.miniware.net/mobile/articles/viewarticle.php?id=22)

Server

import java.io.*;
import javax.bluetooth.*;
import javax.microedition.io.*;

// sample code from : http://www.miniware.net/mobile/articles/viewarticle.php?id=22   (Nikos Fotiou)
public class EchoServer {
    public final UUID uuid = new UUID("0000110100001000800000805F9B34FB",false);
    public final String name = "EchoServer";                       //the name of the service
    public final String url  =  "btspp://localhost:" + uuid + ";name=" + name  + ";authenticate=false;encrypt=false;";
    LocalDevice local = null;
    StreamConnectionNotifier server = null;
    StreamConnection conn = null;

    public EchoServer() {
    try {
        System.out.println("Setting device to be discoverable...");
        local = LocalDevice.getLocalDevice();
        local.setDiscoverable(DiscoveryAgent.GIAC);
        System.out.println("Start service:"+url);
        server = (StreamConnectionNotifier)Connector.open(url);
        System.out.println("Waiting for incoming connection...");
        conn = server.acceptAndOpen();  // stop and wait here
        System.out.println("Client Connected..."); //never reach this line
        DataInputStream din   = new DataInputStream(conn.openInputStream());
        while(true){
            String cmd = "";
            char c;
            while (((c = din.readChar()) > 0) && (c!='\n') ){
                cmd = cmd + c;
            }
            System.out.println("Received " + cmd);
        }
    } catch (Exception  e) {
        System.err.println("Exception Occured: " + e.toString());
        e.printStackTrace();
    }
}

public static void main (String args[]){
    EchoServer echoserver = new EchoServer();
}

}

Server pom.xml

<dependencies>
    <dependency>
        <groupId>net.sf.bluecove</groupId>
        <artifactId>bluecove</artifactId>
        <version>2.1.1-SNAPSHOT</version>
    </dependency>
</dependencies>

<repositories>
    <repository>
        <id>pyx4me-web-snapshot</id>
        <url>http://www.pyx4me.com/maven2-snapshot</url>
        <snapshots>
            <enabled>true</enabled>
        </snapshots>
        <releases>
            <enabled>false</enabled>
        </releases>
    </repository>
</repositories>
like image 249
ben75 Avatar asked Jan 13 '23 14:01

ben75


2 Answers

The UUID you try to use is the Serial Port Profile UUID. It could be declared in code like

private static final UUID BLUETOOTH_SPP_UUID =
                UUID.fromString("00001101-0000-1000-8000-00805f9b34fb");

I tried your code with a Windows 8 laptop and a Nexus S. First I had to pair the devices from the Nexus. Then I started the server and used the Bluetooth SPP app to test the connection. It worked flawlessly. Then I started your code and it worked as well and it worked too.

I could reproduce the "Service discovery failed" exception when the server side was not started. Also, after I scanned all 30 channels with the createRfcommSocket method, the bluetooth stack on the phone got corrupted and I had to restart the device.

In conclusion, to make sure you are able to communicate:

  1. on the laptop make sure that the bluetooth is in discoverable state
  2. (optional) turn off UAC and use an admin account to make sure you don't encounter any security bugs (I didn't have to do this but on the second start the firewall had to be opened for eclipse to enable debugging)
  3. restart the phone
  4. pair from the phone
  5. use the SPP UUID, not a custom one
  6. ensure you use the right mac address by adding System.out.println(local.getBluetoothAddress()); somewhere before the acceptAndOpen() invocation.
  7. test the connection with a third party app from the play store. I used this one in command line mode. Only the connection needs to be tested.
  8. update the MAC address and run the app
  9. it should work.

Here is the output I got from the run:

Start service:btspp://localhost:0000110100001000800000805f9b34fb;name=EchoServer;authenticate=false;encrypt=false;
MAC 402CF454215C
Waiting for incoming connection...
Client Connected...
Exception Occured: java.io.EOFException
BlueCove stack shutdown completed
java.io.EOFException
    at java.io.DataInputStream.readChar(Unknown Source)
    at examples.bluetooth_spp_server.EchoServer.<init>(EchoServer.java:30)
    at examples.bluetooth_spp_server.EchoServer.main(EchoServer.java:42)

For the sake of completeness, here is the error that is returned under various conditions

  • Windows bluetooth turned off: javax.bluetooth.BluetoothStateException: Bluetooth not detected
  • Android bluetooth turned off: java.io.IOException: Unable to start Service Discovery
  • Windows server not running: java.io.IOException: Service discovery failed
  • Not paired: TimeoutException

Theoretically pairing should happen automatically when a secure connection is initiated but in reality the pairing dialog may not appear in all cases on the phone or in Windows. This is a factor of uncertainty that needs to be considered if failures happen.

like image 176
allprog Avatar answered Jan 17 '23 14:01

allprog


a) The UUID is a Serial-Port UUID - mostly needed for using devices that do not speak the SDP protocol - e.g. small embedded RFCOMM devices.

b) Check if the bluetooth is switched on on your phone.

like image 38
ligi Avatar answered Jan 17 '23 14:01

ligi