13

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.

Community
  • 1
  • 1
Matt
  • 1,996
  • 5
  • 18
  • 24
  • 1
    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 Apr 03 '12 at 07:26
  • @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](http://stackoverflow.com/questions/9849852/android-bluetooth-service-discovery-failed-connection-to-desktop-laptop/9919631) – Matt Apr 03 '12 at 19:41

5 Answers5

15

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.

Matt
  • 1,996
  • 5
  • 18
  • 24
  • 6
    I am also having the same issue and I tried calling `btAdapter.cancelDiscovery()` before `sockect.connect()`, but unfortunately it didn't work in my case. I'm still experiencing the same problem. Any idea? – waqaslam Aug 17 '12 at 09:47
  • Can you post your code in a new question and then link it here? I can take a look, I just don't have any idea what it could be without seeing what you're doing from the start... – Matt Aug 18 '12 at 18:03
  • @Waqas: I had the same problem, until now I called cancelDiscovery, then connect on a socket (created using createRfcommSocketToServiceRecord and a UUID), and with one specific smart phone, I had the "Cancel Discovery Failed" when trying to connect to the socket. I checked online and found this solution that is working with the specific smart phone (http://www.eoeandroid.com/forum.php?mod=viewthread&tid=64073). Now like for this post use a way to select the corresponding method and save it for next call (http://stackoverflow.com/a/11878181/186880) – Vincent B. Nov 22 '12 at 07:20
5

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.

Dennis Mathews
  • 6,897
  • 2
  • 26
  • 39
  • I tried the UUID you listed - and the UUID is definitely the same across client and server because the client and server are both running the same Java class, hence they are using the same constant. Also, I have Bluetooth permission - I am able to start Bluetooth, and set it discoverable, its just the attempt to connect to another device that is a problem Also, I am now seeing: 'Received android.bluetooth.device.action.UUID' 'Cleaning up failed UUID channel lookup: 00:21:4F:FC:7F:62 00001101-0000-1000-8000-00805f9b34fb' I don't know if that was appearing before or not, but I noticed it now. – Matt Dec 31 '11 at 19:36
  • Didn't know the UUID was sort of a service type... Great to know, this helped me to connect to my Bluetooth module – Chiguireitor Sep 11 '12 at 11:36
3

"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();
            }
        }
Sourab Sharma
  • 2,940
  • 1
  • 25
  • 38
0

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

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.

Jon
  • 9,156
  • 9
  • 56
  • 73
tato.rodrigo
  • 2,783
  • 21
  • 26