Android 如何获取已连接的蓝牙地址,项目中有一个需求,就是获取已连接的蓝牙地址。
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) { ListmDevices = proxy.getConnectedDevices(); if (mDevices != null && mDevices.size() > 0) { for (BluetoothDevice device : mDevices) { Log.d(TAG,device.getName() + "," + device.getAddress()); } } else { } } }, flag); } }
int a2dp = _bluetoothAdapter.getProfileConnectionState(BluetoothProfile.A2DP); int headset = _bluetoothAdapter.getProfileConnectionState(BluetoothProfile.HEADSET); int health = _bluetoothAdapter.getProfileConnectionState(BluetoothProfile.HEALTH);这三个方法都是返回的BluetoothProfile.STATE_DISCONNECTED
/** * Get the current connection state of a profile. * This function can be used to check whether the local Bluetooth adapter * is connected to any remote device for a specific profile. * Profile can be one of {@link BluetoothProfile#HEALTH}, {@link BluetoothProfile#HEADSET}, * {@link BluetoothProfile#A2DP}. * *
Requires {@link android.Manifest.permission#BLUETOOTH}. * *
Return value can be one of * {@link BluetoothProfile#STATE_DISCONNECTED}, * {@link BluetoothProfile#STATE_CONNECTING}, * {@link BluetoothProfile#STATE_CONNECTED}, * {@link BluetoothProfile#STATE_DISCONNECTING} */ 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; }
/** * Use {@link #getDefaultAdapter} to get the BluetoothAdapter instance. */ 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(); 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; }
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; } }
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) { Pairp = mProfileConnectionState.get(profile); if (p != null) return p.first; return BluetoothProfile.STATE_DISCONNECTED; } }
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都有哪些
/** * Headset and Handsfree profile */ public static final int HEADSET = 1; /** * A2DP profile. */ public static final int A2DP = 2; /** * Health Profile */ public static final int HEALTH = 3; /** * Input Device Profile * @hide */ public static final int INPUT_DEVICE = 4; /** * PAN Profile * @hide */ public static final int PAN = 5; /** * PBAP * @hide */ public static final int PBAP = 6; /** * GATT */ static public final int GATT = 7; /** * GATT_SERVER */ static public final int GATT_SERVER = 8;
实在没有办法了,我看到了BluetoothAdapter有一个hide方法直接调用了AdapterProperties的getConnectionState方法。
/** * @return the mConnectionState */ int getConnectionState() { synchronized (mObject) { return mConnectionState; } }
ClassbluetoothAdapterClass = BluetoothAdapter.class;//得到TelephonyManager的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 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(); }