13
votes

Does anyone know how to create an insecure RFCOMM connection between 2 Android devices at API level 2.3.3 while using an arbitrarily declared service name? (not random or changing service name, just a service name that I define myself)

Details

I am trying to create an insecure Rfcomm connection between 2 Android devices: Droid X2 and an Asus Transformer. I am assuming that both of these devices have functionality at the level of Android 2.3.3 to actually gain the ability to use insecure Rfcomm.

When I try to create the Bluetooth connection as described here, using the now public createInsecureRfcommSocketToServiceRecord() and listenUsingInsecureRfcommWithServiceRecord(SERVICE, UUID), I get a reported:

java.io.IOException: Service discovery failed
at android.bluetooth.BluetoothSocket$SdpHelper.doSdp(BluetoothSocket.java:377)
at android.bluetooth.BluetoothSocket.connect(BluetoothSocket.java:201)
at com.s4d.bluenomad.DeviceConnections$ClientThread.run(DeviceConnections.java:406)

I found a related question where someone creating a normal connection was getting this error and used reflection to invoke a private method. However, I have no idea what private method would now correspond to initiating an "insecure" connection. I tried using the solution proposed in that related question, but I am asked by Android to pair the devices which is exactly what I need to avoid. I really do need the insecure approach.

I even tried a combination of the official and hacked solutions outlined here

Relevant Code Snippets

Creating ServerThread To Listen For Connections

Log.i(TAG, "Constructing a ServerThread");
// Use a temporary object that is later assigned to serverSocket,
// because serverSocket is final
BluetoothServerSocket tmp = null;
try {
    // MY_UUID is the app's UUID string, also used by the client code
    tmp = btAdapter.listenUsingInsecureRfcommWithServiceRecord(SERVICE_NAME, SERVICE_UUID);
    Log.i(TAG,"Started listening on insecure RFCOMM channel for service requests for: " + SERVICE_NAME);
} catch (IOException e) { }
serverSocket = tmp;

ServerThread Listening for Connections

BluetoothSocket socket;
while(true)
{
    try
    {
        socket = serverSocket.accept();
    }
    catch( IOException e)
    {
        break;
    }

    if( socket != null )
    {
        Log.i(TAG, "Received new socket connection requesting service: " + SERVICE_NAME);
    }
    else
    {
        Log.i(TAG, "Socket connection attempted, but socket received is NULL.");
    }
}

Creating ClientThread to Initiate Connections

Log.i(TAG, "Constructing a ClientThread");
BluetoothSocket tmp = null;
try {
    // MY_UUID is the app's UUID string, also used by the server code
    tmp = device.createInsecureRfcommSocketToServiceRecord(SERVICE_UUID);
    Log.i(TAG,"Created client socket on insecure RFCOMM channel for service requests for: " + SERVICE_NAME);
} 
catch (IOException e) 
{ 
    Log.i(TAG, "Failed to createInsecureRfcommSocket() against MAC: " + device.getAddress());
}
clientSocket = tmp;

ClientThread Connecting to Server

try
{
    clientSocket.connect();
}
catch( final IOException e)
{
    DeviceConnections.this.runOnUiThread(new Runnable()
    {

        @Override
        public void run() 
        {
            console.append("Client unable to connect to service.");
            Log.i(TAG, "Client socket unable to connect() to: " + clientSocket.getRemoteDevice().getAddress());
            e.printStackTrace();
        }

    });

}

I do get the log output "Client socket unable to connect() to: [MY_MAC_ADDRESS]", then I get the stacktrace for the "Service discovery failed" exception.

5
hi matt howz u ? i am also stuck here in same problem ..means when i connecting from one device to other its get connected and again if i am doing from second to first device log cat showing the message "service discovery failed" so why it is not connecting from other device i had tryed it wid diffrent UUId's pls help me.. - shyam
@shyam - did you look at my answer down below? If you try to connect to a service while your BluetoothAdapter is still searching for devices, the discovery will fail. I also had an additional problem with connections that I posted about here: My Other Connection Problem - Matt

5 Answers

15
votes

It appears the problem was that before I called

clientSocket.connect()

I needed to call

btAdapter.cancelDiscovery()

I had seen this in documentation but it was listed as a "performance" issue - in my case it seems that this was actually a "functional" issue. Once I added the cancel discovery call, the socket connection worked immediately.

5
votes

A few things to check

  • using the same and unique UUID both at the client and server.
  • Have the BLUETOOTH permission
  • Try with the standard well-known SPP UUID 00001101-0000-1000-8000-00805F9B34FB

Also it will help if you can paste the complete logs on the client and server side printing API error codes if any.

3
votes

"Service Discovery Failed" simply means our device is not able to find service with same UUID in any other device.

The 2nd device has not called the "listenUsingInsecureRfcommWithServiceRecord" method, before you are trying to call the "createInsecureRfcommSocketToServiceRecord" from 1st device.

Make sure this code has been executed in 2nd device (like onResume(), or a button/optionsItem click) before you try to connect from 1st device.

 if ((mChatService != null) &&  (mBluetoothAdapter.isEnabled())) {
// Only if the state is STATE_NONE, do we know that we haven't started already
if (mChatService.getState() == BluetoothChatService.STATE_NONE) {
// Start the Bluetooth chat services
mChatService.start();
            }
        }
0
votes

You should change 8ce255c0-200a-11e0-ac64-0800200c9a66 to any other UUID and you can use you service name because 8ce255c0-200a-11e0-ac64-0800200c9a66 is used for predefined Service BluetoothChatInsecure

0
votes

Android Bluetooth implementation is painful, because it may vary across devices.

I was experiencing the same issue. In my specific case, the error occured when at least one of the devices BluetoothAdapter.getScanMode() was set to BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE (i.e. the device is both discoverable and connectable from remote Bluetooth devices).

That is curious because the device should be connectable, but it was not.

If the device getScanMode() ==SCAN_MODE_CONNECTABLE, then no error occurs.

By now the the solution I found is to show a warning to the user, so they only connect to paired devices. If the devices are not paired, the user should use the Android settings and do the job.

Enabling bluetooth communication only for paired devices eliminates the need to be discoverable and then avoiding the "Service discovery failed".

Again, it is my specific case on my specific device. This may not be a general rule, but hope this helps anyone who is getting the same error.