Android 如何获取已连接的蓝牙地址

    xiaoxiao2021-03-25  67

    项目中有一个需求,就是获取已连接的蓝牙地址

    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

    /** * 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}. * * <p>Requires {@link android.Manifest.permission#BLUETOOTH}. * * <p> 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; } mService是IBluetooth接口对象

    /** * 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<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都有哪些

    /** * 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; 我们列举了主要的几种,除了我们测试的HEADSET、A2DP、HEALTH外,还有GATT和GATT_SERVER,其实都是Hide。最开始的代码加上GATT和GATT_SERVER之后,依然没有结果。

    实在没有办法了,我看到了BluetoothAdapter有一个hide方法直接调用了AdapterProperties的getConnectionState方法。

    /** * @return the mConnectionState */ int getConnectionState() { synchronized (mObject) { return mConnectionState; } }

    Class<BluetoothAdapter> bluetoothAdapterClass = BluetoothAdapter.class;//得到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

    转载请注明原文地址: https://ju.6miu.com/read-26012.html

    最新回复(0)