Connecting to a Bluetooth A2DP Device from android

I’ve been wondering whether there is any way to connect my bluetooth headset to my android device programatically and which works on all android versions. Finally after lot many googling, I’ve got a solution to this.

In early Android devices, the classes which are required to connect to a bluetooth A2DP device is hidden in the API level and in the later devices from Android 4.0 onwards, it is made partially visible. I’ll tell you a solution which will work on all the Android versions above 2.3 taking these things into consideration.

Basically, to have an Interaction with the A2DP devices, we need to make some IPC (Inter Process Communication) calls. For this, we need to know how to make IPC calls. In Android, its done with the help of AIDL (Android Interface Definition Language). My solution is also using the same method. You can learn about the AIDL calls from the android developer site.

The class which we need to connect to an A2DP device is BluetoothA2dp. This class is hidden in Android versions below 4 and is visible with limited functionality in Android 4 and above.

1. Our first step is to get hold on to the instance of BluetoothA2dp class. For that, you need to create 2 AIDL file first in your src folder of Android Project under package android.bluetooth as follows :

IBluetooth.aidl :

 /*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.bluetooth;

import android.bluetooth.BluetoothDevice;

/**
 * System private API for Bluetooth service
 *
 * {@hide}
 */
interface IBluetooth {
   String getRemoteAlias(in String address);
   boolean setRemoteAlias(in String address, in String name);
}

IBluetoothA2dp.aidl

 /*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.bluetooth;

import android.bluetooth.BluetoothDevice;

/**
 * System private API for Bluetooth A2DP service
 *
 * {@hide}
 */
interface IBluetoothA2dp {
    boolean connectSink(in BluetoothDevice device); // Pre API 11 only
    boolean disconnectSink(in BluetoothDevice device); // Pre API 11 only
    boolean connect(in BluetoothDevice device); // API 11 and up only
    boolean disconnect(in BluetoothDevice device); // API 11 and up only
    boolean suspendSink(in BluetoothDevice device); // all
    boolean resumeSink(in BluetoothDevice device); // all
    BluetoothDevice[] getConnectedSinks();  // change to Set<> once AIDL supports, pre API 11 only
    BluetoothDevice[] getNonDisconnectedSinks();  // change to Set<> once AIDL supports, 
    int getSinkState(in BluetoothDevice device); // pre API 11 only
    int getConnectionState(in BluetoothDevice device); // API 11 and up
    boolean setSinkPriority(in BluetoothDevice device, int priority); // Pre API 11 only
    boolean setPriority(in BluetoothDevice device, int priority); // API 11 and up only
    int getPriority(in BluetoothDevice device); // API 11 and up only
    int getSinkPriority(in BluetoothDevice device); // Pre API 11 only
    boolean isA2dpPlaying(in BluetoothDevice device); // API 11 and up only
}    

After creating the AIDL file, just compile the project and the stub for the interfaces in AIDL files will be generated in the gen folder (Do not edit these files neither mind it).

2. Then in the Manifest, add permissions for using bluetooth and related services :


android.permission.BLUETOOTH
android.permission.BLUETOOTH_ADMIN
android.permission.BROADCAST_STICKY
android.permission.BIND_ACCESSIBILITY_SERVICE

3. Next step is to identify the device to connect. You can get the already paired devices list from BluetoothAdapter class As Follows :

Set devices=BluetoothAdapter.getDefaultAdapter().getBondedDevices();

From there, find the device that you want to connect. Let that device variable name be “deviceToConnect”

4. Use the below method to connect to that bluetooth A2DP Device :


public void connectUsingBluetoothA2dp(Context context,
			final BluetoothDevice deviceToConnect) {

try {
Class<?> c2 = Class.forName("android.os.ServiceManager");
Method m2 = c2.getDeclaredMethod("getService", String.class);
IBinder b = (IBinder) m2.invoke(c2.newInstance(), "bluetooth_a2dp");
if (b == null) {
// For Android 4.2 Above Devices
BluetoothAdapter.getDefaultAdapter().getProfileProxy(context,
	new ServiceListener() {

		@Override
		public void onServiceDisconnected(int profile) {

		}

		@Override
		public void onServiceConnected(int profile,
				BluetoothProfile proxy) {
			BluetoothA2dp a2dp = (BluetoothA2dp) proxy;
			try {
			a2dp.getClass()
				.getMethod("connect",BluetoothDevice.class)
					.invoke(a2dp, deviceToConnect);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}, BluetoothProfile.A2DP);
} else {
// For Android below 4.2 devices
Class<?> c3 = Class.forName("android.bluetooth.IBluetoothA2dp");
Class<?>[] s2 = c3.getDeclaredClasses();
Class<?> c = s2[0];
Method m = c.getDeclaredMethod("asInterface", IBinder.class);
m.setAccessible(true);
IBluetoothA2dp a2dp = (IBluetoothA2dp) m.invoke(null, b);
a2dp.connect(deviceToConnect);
}
} catch (Exception e) {
	e.printStackTrace();
}
}

Leave a Reply