4

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>
Community
  • 1
  • 1
ben75
  • 29,217
  • 10
  • 88
  • 134
  • The logcat is indicating the `open` call on the android side failed, the hard-coded UID, which I think may be the culprit here, could be one of system reserved identifiers, If I were you, I'd try using this [site](http://www.uuidgenerator.com) to generate a random UUID, paste it in both server/client, and try again. If that fails, might try taking the Bluetooth chat sample program found in the SDK and tweak it to talk to your server. – t0mm13b Aug 22 '13 at 11:11
  • @t0mm13b thanks for your comment. I tried with a random UUID (the same on both side), but I still have the same problem and same logs. – ben75 Aug 22 '13 at 11:20
  • Hmmm... on the EchoServer side, try moving the code to a thread, as it seems to block thus the android side does not "see" it? The comment *//never reach this line* is what made me think. – t0mm13b Aug 22 '13 at 11:37
  • `server.acceptAndOpen();` is blocking and it is the expected behavior. The server is just waiting for a client, so it don't seems that moving it in a thread will help. – ben75 Aug 22 '13 at 11:49

2 Answers2

8

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.

allprog
  • 16,540
  • 9
  • 56
  • 97
  • Thanks. But when I try the option 2 : the `socket.connect()` fail with a "connection timeout". Additionally, I'm not sure that the uuid of my server is not in the repository since when I call `bluetoothDevice.getUuids()` on the client I receive an array with the SPP-UUID + my custom UUID (if I define one randomly generated) – ben75 Aug 26 '13 at 09:44
  • What version of android do you use? – allprog Aug 26 '13 at 12:25
  • I use android 4.1.2 on a Samsung GT-B5330 – ben75 Aug 26 '13 at 12:53
  • Ok, I'll try to confirm again that this works. I have the same version on my device. – allprog Aug 26 '13 at 13:10
  • @ben75 I tested the whole scenario and updated the post. Btw: getUuids() for me returns the 0x1000, 0x1101, 0x1115, 0x1200 services in this order. – allprog Aug 26 '13 at 22:42
  • Thanks again. I'm not sure why it didn't work, but it seems that the BT service is in a weird state after a failed attempt and/or after the device go to sleep. Restarting the device make things going better. – ben75 Aug 27 '13 at 12:36
  • Yes, this is what I found too. Back in Android 2.1 even more hacks had to be carried out. :) – allprog Aug 27 '13 at 12:47
  • "make things going better" does this mean the connection is working now? Do you think you could accept this answer? – allprog Aug 27 '13 at 13:14
  • Yes, I think I can accept it. (I still have other problems with the Bluetooth API... maybe other questions later) Anyway thanks for your help. – ben75 Aug 27 '13 at 13:28
1

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.

Abdul Rahman
  • 2,097
  • 4
  • 28
  • 36
ligi
  • 39,001
  • 44
  • 144
  • 244
  • Yeah, turned off bluetooth can screw things up. But in that case the exception is: java.io.IOException: Unable to start Service Discovery – allprog Aug 26 '13 at 23:06
  • afair I had a "unable to start Service Discovery" once for a switched off bluetooth – ligi Aug 26 '13 at 23:18