57

Is there a way, using the Android SDK, to programmatically connect to an already-paired Bluetooth device?

In other words: I can go into Settings -> Wireless & networks -> Bluetooth settings, and tap the device (listed as "Paired but not connected"), at which point it will connect. I'd like to be able to do this programmatically, but don't see a way to do this.

I see the options to create an RFCOMM socket, and for a SPP device, I'm assuming that'll do the connection part as well, but for an A2DP device, where the actual data transfer will be handled by the OS rather than by my app, I think that's not applicable?

Alexander Farber
  • 21,519
  • 75
  • 241
  • 416
rmc47
  • 1,364
  • 1
  • 13
  • 17

4 Answers4

59

Okay, since this was driving me crazy, I did some digging into the source code and I've found a 100% reliable (at least on my Nexus 4, Android 4.3) solution to connect to a paired A2DP device (such as a headset or Bluetooth audio device). I've published a fully working sample project (easily built with Android Studio) that you can find here on Github.

Essentially, what you need to do is:

  • Get an instance of the BluetoothAdapter
  • Using this instance, get a profile proxy for A2DP:

adapter.getProfileProxy (context, listener, BluetoothProfile.A2DP);

where listener is a ServiceListener that will receive a BluetoothProfile in its onServiceConnected() callback (which can be cast to a BluetoothA2dp instance)

  • Use reflection to acquire the connect(BluetoothDevice) method on the proxy:

Method connect = BluetoothA2dp.class.getDeclaredMethod("connect", BluetoothDevice.class);

  • Find your BluetoothDevice:

String deviceName = "My_Device_Name";

BluetoothDevice result = null;

Set<BluetoothDevice> devices = adapter.getBondedDevices();
if (devices != null) {
    for (BluetoothDevice device : devices) {
        if (deviceName.equals(device.getName())) {
            result = device;
            break;
        }
    }
}

  • And invoke the connect() method:

connect.invoke(proxy, result);

Which, at least for me, caused an immediate connection of the device.

Kevin Coppock
  • 133,643
  • 45
  • 263
  • 274
  • 1
    @kcoppock sir please check http://stackoverflow.com/questions/26800606/ble-4-0-getting-the-broadcast-data-from-device-to-phone for SPP profile – Ajit Nov 10 '14 at 06:58
  • @kcoppock: Is it possible to apply it for Handset profile. I tried it to connect with my headset device, however, your project did not work – John Jan 05 '15 at 02:28
  • 1
    @user8264: There is also a [`BluetoothHeadset`](http://developer.android.com/reference/android/bluetooth/BluetoothHeadset.html) class as well as a [`BluetoothProfile.HEADSET`](http://developer.android.com/reference/android/bluetooth/BluetoothProfile.html#HEADSET) constant. The changes to use these should be fairly trivial. – Kevin Coppock Jan 05 '15 at 18:23
  • Yes. This is my project. However, I tried to connect to headset and stream audio from headset device to android phone, I have some problem with echo sound. This is my question. http://stackoverflow.com/questions/27777305/how-to-mute-microphone-when-recording-from-headset – John Jan 06 '15 at 01:22
  • I downloaded the project in GitHub and somehow managed to integrate it into my own code so that now I can divert the phone audio output via bluetooth to my custom audio sink device. However, I do not seem to be able to figure out when the functions in the `BluetoothBroadcastReceiver` are being called. Are they necessary? When exactly do they get called? (for now, this is how my app works -> discovery -> pairing (for simplicity there are no previously paired devices and only one remote devic e to connect to) -> A2DP channel using BluetoothA2DPRequester -> all audio goes to the remote A2DP sink – user13267 Jan 13 '15 at 09:35
  • This should be the accepted answer. Using reflection to force an A2DP connection works fine :) (until Google blocks it..) – PieterAelse Feb 24 '15 at 11:53
  • I have a question about using this from a broadcast receiver. I would like to automatically pair the bluetooth device once bluetooth is turned on. However, Android prohibits broadcast receivers from binding services. So when the BluetoothProfile.ServiceListener gets called, there's an error. Is there anyway to connect in a broadcast receiver? Thanks! – waylonion Mar 02 '15 at 02:43
  • 1
    @WayWay You could probably start a new IntentService from your BroadcastReceiver (use the provided Context in onReceive to start it) and let that service do the bluetooth service binding. – Kevin Coppock Mar 02 '15 at 04:47
  • @kcoppock with this library could I autoconnect to the nearest/paired device autommatically? I mean if I turn on the Bluetooth it connects autommatically? – Skizo-ozᴉʞS ツ Jul 31 '15 at 11:44
  • No, this is specifically used to work around Bluetooth auto-connect not working. – Kevin Coppock Jul 31 '15 at 13:55
  • Can you check [this question](http://stackoverflow.com/questions/31761416/connect-to-bluetooth-programmatically) please? :( – Skizo-ozᴉʞS ツ Aug 02 '15 at 13:38
  • It helped me.. +10 for you (Y) – Manmohan Badaya Jan 04 '18 at 11:12
  • I an little bit surprised that "connect", "disconnect" for BluetoothHeadset profile is working Great! But "connect" is not working for BluetoothA2DP profile, "disconnect" is working – Vishal Sharma Mar 08 '18 at 09:30
  • This code actually helped me with an issue where cheaper headsets would pair but not connect when I used the createBond method so I had to force the connection this way. Funnily enough expensive headsets like BeatsX and Airpods didn't need to be forced after pairing – Gyurme Jun 04 '18 at 09:23
  • Wow thanks! is there a way to now disconnect the device? i know there is a disconnect method, but sometimes doesnt work :( – Jorge Barraza Z May 21 '19 at 22:07
  • I'm not sure, never tried that route myself. :) I would expect you could use a similar trick to access the disconnect method on the profile, though. That said, expect this solution to stop working, likely in Android Q, as many of these private APIs are becoming restricted. – Kevin Coppock May 21 '19 at 23:02
  • 3
    @KevinCoppock, you are brilliant! Just now you have saved my time! Thank you! – Georgiy Chebotarev Sep 07 '20 at 10:21
4

the best way I found to solve my problem was finding out that I can create a button that brings up the Bluetooth Settings screen. I didn't realize you could do this, or I would have from the beginning.

startActivity(new Intent(Settings.ACTION_BLUETOOTH_SETTINGS));
Wladimir Palant
  • 56,865
  • 12
  • 98
  • 126
Belboz
  • 107
  • 1
  • 2
  • 6
3

if the device is already paired , then you can use

if(device.getBondState()==device.BOND_BONDED){

        Log.d(TAG,device.getName());
        //BluetoothSocket mSocket=null;
        try {


            mSocket = device.createInsecureRfcommSocketToServiceRecord(MY_UUID);
        } catch (IOException e1) {
            // TODO Auto-generated catch block
            Log.d(TAG,"socket not created");
            e1.printStackTrace();
        }
        try{

            mSocket.connect();

        }
        catch(IOException e){
            try {

                mSocket.close();
                Log.d(TAG,"Cannot connect");
            } catch (IOException e1) {
                Log.d(TAG,"Socket not closed");
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }


        }

for the MY_UUID use

private static final UUID MY_UUID = UUID.fromString("0000110E-0000-1000-8000-00805F9B34FB");

the above code snippet is just to connect your device to an A2DP supported device. I hope it will work.

nam_ph
  • 233
  • 1
  • 3
  • 12
  • Will this force connect an a2dp headset? – Alec B. Plumb Sep 10 '12 at 17:17
  • it will only connect to the device that supports A2DP profile, being an insecure socket, it will just connect without asking for pairing(as we want, because your device is already paired). – nam_ph Sep 11 '12 at 03:15
  • 1
    please change the UUID to "0000110A-0000-1000-8000-00805F9B34FB" or "0000110B-0000-1000-8000-00805F9B34FB".... The above UUID is for AVRCP not for A2DP ,it just slipped out of my mind. – nam_ph Sep 11 '12 at 03:17
  • will this code will work to connect any unsecure bluetooth device? – abh22ishek Nov 20 '15 at 05:20
1

I used the code here as a starting point for this functionality in my app: http://developer.android.com/guide/topics/wireless/bluetooth.html#ConnectingDevices

Once the device is paired, the app has no problem connecting the two devices together programmtically.

Marc Bernstein
  • 11,423
  • 5
  • 34
  • 32
  • 1
    Marc: thanks for the reply. That's good for peer-to-peer application connections where it's your app that wants to send data (and hence grabs the BluetoothSocket), but in this case, I just need to establish a connection for A2DP; the actual data stream is handled by the OS. – rmc47 Mar 03 '11 at 16:19
  • Ahh, it wasn't clear to me that your other device is not an Android device. – Marc Bernstein Mar 03 '11 at 19:40
  • Have you found solution to connection with other bluetooth device(paired) non android @rmc47 ? – nafees ahmed Jul 08 '19 at 12:01