项目中有一个需求,就是获取已连接的蓝牙地址
- private void getConnectBt() {
- LogUtil.i("getConnectBt");
-
- int a2dp = _bluetoothAdapter.getProfileConnectionState(BluetoothProfile.A2DP);
- int headset = _bluetoothAdapter.getProfileConnectionState(BluetoothProfile.HEADSET);
- int health = _bluetoothAdapter.getProfileConnectionState(BluetoothProfile.HEALTH);
- int flag = -1;
- if (a2dp == BluetoothProfile.STATE_CONNECTED) {
- flag = a2dp;
- } else if (headset == BluetoothProfile.STATE_CONNECTED) {
- flag = headset;
- } else if (health == BluetoothProfile.STATE_CONNECTED) {
- flag = health;
- }
-
- Log.d(TAG,"flag:"+flag);
- if (flag != -1) {
- _bluetoothAdapter.getProfileProxy(_context, new BluetoothProfile.ServiceListener() {
- @Override
- public void onServiceDisconnected(int profile) {
-
- }
-
- @Override
- public void onServiceConnected(int profile, BluetoothProfile proxy) {
- List<BluetoothDevice> mDevices = proxy.getConnectedDevices();
- if (mDevices != null && mDevices.size() > 0) {
- for (BluetoothDevice device : mDevices) {
- Log.d(TAG,device.getName() + "," + device.getAddress());
- }
- } else {
-
- }
- }
- }, flag);
-
- }
- }
从网上看到这段代码并没有作用,由于flag一直等于-1,所以一直返回BluetoothProfile.STATE_DISCONNECTED。也就是说
- int a2dp = _bluetoothAdapter.getProfileConnectionState(BluetoothProfile.A2DP);
- int headset = _bluetoothAdapter.getProfileConnectionState(BluetoothProfile.HEADSET);
- int health = _bluetoothAdapter.getProfileConnectionState(BluetoothProfile.HEALTH);
这三个方法都是返回的BluetoothProfile.STATE_DISCONNECTED
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- public int getProfileConnectionState(int profile) {
- if (getState() != STATE_ON) return BluetoothProfile.STATE_DISCONNECTED;
- try {
- synchronized(mManagerCallback) {
- if (mService != null) return mService.getProfileConnectionState(profile);
- }
- } catch (RemoteException e) {
- Log.e(TAG, "getProfileConnectionState:", e);
- }
- return BluetoothProfile.STATE_DISCONNECTED;
- }
mService是IBluetooth接口对象
-
-
-
- BluetoothAdapter(IBluetoothManager managerService) {
-
- if (managerService == null) {
- throw new IllegalArgumentException("bluetooth manager service is null");
- }
- try {
- mService = managerService.registerAdapter(mManagerCallback);
- } catch (RemoteException e) {Log.e(TAG, "", e);}
- mManagerService = managerService;
- mLeScanClients = new HashMap<LeScanCallback, GattCallbackWrapper>();
- mHandler = new Handler(Looper.getMainLooper());
- }
- public static synchronized BluetoothAdapter getDefaultAdapter() {
- if (sAdapter == null) {
- IBinder b = ServiceManager.getService(BLUETOOTH_MANAGER_SERVICE);
- if (b != null) {
- IBluetoothManager managerService = IBluetoothManager.Stub.asInterface(b);
- sAdapter = new BluetoothAdapter(managerService);
- } else {
- Log.e(TAG, "Bluetooth binder is null");
- }
- }
- return sAdapter;
- }
我们看到managerService是IBluetoothManager的Proxy,我们来找找Stub端在哪。
- private static class AdapterServiceBinder extends IBluetooth.Stub
- class BluetoothManagerService extends IBluetoothManager.Stub
- public IBluetooth registerAdapter(IBluetoothManagerCallback callback){
- Message msg = mHandler.obtainMessage(MESSAGE_REGISTER_ADAPTER);
- msg.obj = callback;
- mHandler.sendMessage(msg);
- synchronized(mConnection) {
- return mBluetooth;
- }
- }
我们继续看BluetoothAdapter的mService到底是什么
- mBluetooth = IBluetooth.Stub.asInterface(service);
- private static class AdapterServiceBinder extends IBluetooth.Stub
原来BluetoothAdapter的mService = mBluetooth = IBluetooth.Stub.asInterface(service),BluetoothManagerService只是个门面而已,真正干活的是IBluetooth.Stub也就是AdapterServiceBinder。我们回到最开始的问题,我们看AdapterService的getProfileConnectionState方法
- int getProfileConnectionState(int profile) {
- enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-
- return mAdapterProperties.getProfileConnectionState(profile);
我们继续看AdapterProperties类
- int getProfileConnectionState(int profile) {
- synchronized (mObject) {
- Pair<Integer, Integer> p = mProfileConnectionState.get(profile);
- if (p != null) return p.first;
- return BluetoothProfile.STATE_DISCONNECTED;
- }
- }
mProfileConnectionState是干什么用的,在此之前我们先看看蓝牙的一些基本概念。
BluetoothProfile
描述Bluetooth Profile的接口。Bluetooth Profile是两个设备基于蓝牙通讯的无线接口描述。
(对Bluetooth Profile的详细解释,来自百度:为了更容易的保持Bluetooth设备之间的兼容,Bluetooth规范中定义了 Profile。Profile定义了设备如何实现一种连接或者应用,你可以把Profile理解为连接层或者应用层协议。 比如,如果一家公司希望它们的Bluetooth芯片支援所有的Bluetooth耳机,那么它只要支持HeadSet Profile即可,而无须考虑该芯片与其它Bluetooth设备的通讯与兼容性问题。如果你想购买Bluetooth产品,你应该了解你的应用需要哪 些Profile来完成,并且确保你购买的Bluetooth产品支持这些Profile。)
BluetoothHeadset
提供移动电话的Bluetooth耳机支持。包括Bluetooth耳机和Hands-Free (v1.5) profiles。
BluetoothA2dp
定义两个设备间如何通过Bluetooth连接进行高质量的音频传输。
A2DP(Advanced Audio Distribution Profile):高级音频传输模式。
mProfileConnectionState也就是管理各种profile连接情况的一个集合
很显然,我们最开始那段代码不起作用,是因为profile不对,我们来看profile都有哪些
-
-
-
- public static final int HEADSET = 1;
-
-
-
-
- public static final int A2DP = 2;
-
-
-
-
- public static final int HEALTH = 3;
-
-
-
-
-
- public static final int INPUT_DEVICE = 4;
-
-
-
-
-
- public static final int PAN = 5;
-
-
-
-
-
- public static final int PBAP = 6;
-
-
-
-
- static public final int GATT = 7;
-
-
-
-
- static public final int GATT_SERVER = 8;
我们列举了主要的几种,除了我们测试的HEADSET、A2DP、HEALTH外,还有GATT和GATT_SERVER,其实都是Hide。最开始的代码加上GATT和GATT_SERVER之后,依然没有结果。
实在没有办法了,我看到了BluetoothAdapter有一个hide方法直接调用了AdapterProperties的getConnectionState方法。
-
-
-
- int getConnectionState() {
- synchronized (mObject) {
- return mConnectionState;
- }
- }
- Class<BluetoothAdapter> bluetoothAdapterClass = BluetoothAdapter.class;
- try {
- Method method = bluetoothAdapterClass.getDeclaredMethod("getConnectionState", (Class[]) null);
-
- method.setAccessible(true);
- int state = (int) method.invoke(_bluetoothAdapter, (Object[]) null);
-
- if(state == BluetoothAdapter.STATE_CONNECTED){
-
- LogUtil.i("BluetoothAdapter.STATE_CONNECTED");
-
- Set<BluetoothDevice> devices = _bluetoothAdapter.getBondedDevices();
- LogUtil.i("devices:"+devices.size());
-
- for(BluetoothDevice device : devices){
-
- Method isConnectedMethod = BluetoothDevice.class.getDeclaredMethod("isConnected", (Class[]) null);
- method.setAccessible(true);
- boolean isConnected = (boolean) isConnectedMethod.invoke(device, (Object[]) null);
-
- if(isConnected){
- LogUtil.i("connected:"+device.getAddress());
- return device.getAddress();
- }
-
- }
-
- }
-
- } catch (Exception e) {
- e.printStackTrace();
- }
利用反射获取了当前蓝牙连接的状态,根据getBondedDevices获取已绑定的蓝牙连接,然后遍历BluetoothDevice,同样利用反射的方法调用BluetoothDevice的isConnected方法。成功获取。
参考文章:
http://blog.csdn.net/mapeifan/article/details/50683956