Need BLUETOOTH PRIVILEGED permission以及requestMtu导致蓝牙断连问题

在部分Android手机上,当连接上GATTService后直接requestMtu有可能会造成蓝牙连接中断,随后继续重新连接会报错Need BLUETOOTH PRIVILEGED permission

复制代码
1 //扫描成功后连接gatt
2 BluetoothDevice mRemoteDevice = mBluetoothAdapter.getRemoteDevice(result.getDevice().getAddress());
3 BluetoothGatt mBluetoothGatt = mRemoteDevice.connectGatt(getContext(), false, bluetoothGattCallback);

在 BluetoothGattCallback 监听的 onConnectionStateChange(BluetoothGatt gatt, int status, int newState)方法中直接requestMtu(512) 会直接导致蓝牙断开连接

复制代码
 1 private int setMTUInt = 512;
 2 
 3 
 4 @Override
 5 public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
 6     super.onConnectionStateChange(gatt, status, newState);
 7 
 8     if (newState == BluetoothProfile.STATE_CONNECTED) { //// 连接成功
 9         //虽然这里的boolean会为true但是实际上会失败,并且导致蓝牙断开链接
10         boolean requestMtu = gatt.requestMtu(setMTUInt);
11         Log.e(TAG,"设置 requestMtu:"+requestMtu);
12 
13     } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { // 连接断开
14         //清除缓存,防止Need BLUETOOTH PRIVILEGED permission
15         refreshDeviceCache();
16         //将MTU的值减少,值可以随意设置
17         setMTUInt -= 100;
18         // 关闭GATT客户端
19         mBluetoothGatt.close();
20     }
21 }

在监听的onMtuChanged(BluetoothGatt gatt, int mtu, int status)方法中,确认mtu设置成功后,再去请求特征值

复制代码
1 @Override
2 public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {
3     super.onMtuChanged(gatt, mtu, status);
4             
5     // 开始查找GATT服务器提供的服务
6     gatt.discoverServices(); 
7            
8 }

随后在监听的onServicesDiscovered(BluetoothGatt gatt, int status)方法中设置特征

复制代码
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
    super.onServicesDiscovered(gatt, status);
     if (status == BluetoothGatt.GATT_SUCCESS) {
        //设置特征值
        requestCharacteristic();
    } 
}

清除缓存的方法,gatt本身有提供清除缓存方法,但是不给外部直接调用,所以使用反射的方式进行调用,建议在每次开启扫描设备时也清除一下缓存,防止链接过其他设备后直接链接新设备报错 java.lang.SecurityException: Need BLUETOOTH PRIVILEGED permission: Neither user 10208 nor current process has android.permission.BLUETOOTH_PRIVILEGED.

复制代码
 1 public boolean refreshDeviceCache() {
 2     if (mBluetoothGatt != null) {
 3         Log.e(TAG,"清除缓存 refreshDeviceCache");
 4         try {
 5             BluetoothGatt localBluetoothGatt = mBluetoothGatt;
 6             Method localMethod = localBluetoothGatt.getClass().getMethod(
 7                         "refresh", new Class[0]);
 8             if (localMethod != null) {
 9                 boolean bool = ((Boolean) localMethod.invoke(
10                             localBluetoothGatt, new Object[0])).booleanValue();
11                 return bool;
12             }
13         } catch (Exception localException) {
14             Log.i(TAG, "An exception occured while refreshing device");
15         }
16     }
17     return false;
18 }