CaseyB
CaseyB

Reputation: 25058

Android Bluetooth Fails to Pair

I am having a problem getting my devices to pair in Android. If I go into the settings and pair them manually I can get them to connect using the following code:

Server

@Override
public void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.connect);

    Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
    startActivityForResult(discoverableIntent, REQUEST_ENABLE_BT);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
    if(requestCode == REQUEST_ENABLE_BT)
    {
        if(resultCode == RESULT_CANCELED)
        {
            new AlertDialog.Builder(this)
            .setTitle(R.string.error)
            .setMessage(R.string.bluetooth_unavailable)
            .setPositiveButton(android.R.string.ok, AndroidUtils.DismissListener)
            .create()
            .show();
        }
        else
        {
            mServerSocket = mAdapter.listenUsingRfcommWithServiceRecord("Moo Productions Bluetooth Server", mUUID);
            mState = State.ACCEPTING;
            BluetoothSocket socket = mServerSocket.accept();
            mServerSocket.close();
            connected(socket);
        }
    }
}

Client

Set<BluetoothDevice> pairedDevices = mAdapter.getBondedDevices();
BluetoothSocket socket = null;

// Search the list of paired devices for the right one
for(BluetoothDevice device : pairedDevices)
{
    try
    {
        mState = State.SEARCHING;
        socket = device.createRfcommSocketToServiceRecord(mUUID);
        mState = State.CONNECTING;
        socket.connect();
        connected(socket);
        break;
    }
    catch (IOException e)
    {
        socket = null;
        continue;
    }
}

But if the devices hadn't already been paired it gets out of the foreach without connecting to a valid socket. In that case I start discovering.

// If that didn't work, discover
if(socket == null)
{
    mState = State.SEARCHING;
    mReceiver = new SocketReceiver();
    mContext.registerReceiver(mReceiver, new IntentFilter(BluetoothDevice.ACTION_FOUND));
    mAdapter.startDiscovery();
}

// ... Later ...

private class SocketReceiver extends BroadcastReceiver
{
    @Override
    public void onReceive(Context context, Intent intent)
    {
        if(BluetoothDevice.ACTION_FOUND.equals(intent.getAction()))
        {
            try
            {
                // Get the device and try to open a socket
                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                BluetoothSocket socket = device.createRfcommSocketToServiceRecord(mUUID);
                mState = State.CONNECTING;
                socket.connect();

                // This is our boy, so stop looking
                mAdapter.cancelDiscovery();
                mContext.unregisterReceiver(mReceiver);

                connected(socket);
            }
            catch (IOException ioe)
            {
                ioe.printStackTrace();
            }
        }
    }
}

But it will never find the other device. I never get a pairing dialog and when I step through I see that it discovers the correct device, but it fails to connect with this exception java.io.IOException: Service discovery failed. Any ideas as to what I'm missing?

Upvotes: 5

Views: 10033

Answers (2)

Huxley
Huxley

Reputation: 1

Don't know if it's still relevant, but I did it like this and it worked:

if (BluetoothDevice.ACTION_FOUND.equals(action)) {
  discoveredDeviceName = intent.getStringExtra(BluetoothDevice.EXTRA_NAME);
}

if (discoveredDeviceName.equals("your_device_name")) { 
  mDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
}

Also, I would try to cancel discovery before:

BluetoothSocket socket = device.createRfcommSocketToServiceRecord(mUUID);
socket.connect();

Upvotes: 0

Scott Main
Scott Main

Reputation: 81

Your client will never discover the server if the server is not actually discoverable. Your server code's comment says "Make sure the device it discoverable," but listening on a socket does not mean the device is discoverable. You can make the server discoverable by calling:

Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
startActivity(discoverableIntent);

This is an Intent because discoverability must be enabled by the system and only with approval from the user (so this will raise a dialog, requesting discoverability for 300 seconds). Only during this window of 300 seconds will the server actually be discoverable. During this time, your client code should work just fine and you'll get the pairing requests.

This is all covered in detail in the Android dev guide: http://developer.android.com/guide/topics/wireless/bluetooth.html

Upvotes: 3

Related Questions