蓝牙BLE 的几个坑与心得!

第一次写CSDN博客,多多关照
公司APP的业务是做蓝牙mesh组网的,具体协议我就不提了,具体通讯方式是Gatt连接和非连接,非连接是通过扫描与广播进行通讯的。
分享一下几个坑与心得:
1.BLE广播 BluetoothLeAdvertiser
广播设置 AdvertiseSettings有一项是timeout,这个timeout千万不要用,有很严重的bug,会导致广播无法关闭(disconnect),甚至即使把APP给杀死然后重启也无济于事!设置了timeout不等于0的话,只能成功广播一次,之后的所有广播,都会失败,即使重启APP,也是失败,只能重启蓝牙!
解决方法:timeout设置为0,或者不设置,写一个新的线程控制它的关闭(disconnect)
【蓝牙BLE 的几个坑与心得!】2.GATT每次写操作之前确保回调
不仅是写操作,还有notify,以及设置mtu,在收到回调之前,不能够进行下一个方法的调用!否则会直接回调失败!
3.扫描和广播是可以同时进行的!
虽然蓝牙设备并不是双工(发送和接收(扫描)同时进行),但是我估计手机蓝牙设备底层做了处理,因此我在做非连接状态的通信的时候,用的是边发送,边扫描的方式,大大增加了通信的成功率。
4.Android6.0以下的手机的Gatt连接
6.0以下的手机调用Gatt的connect很可能会失败,直接返回status133,无法连接。
看起来好像是没有办法解决,但是我用一款调试软件nrfConnect的时候,发现该软件可以连接,然后我将代码反编译下来,发现它是这样连接的

Class localClass = bleDevice.getDevice().getClass(); Class[] arrayOfClass = new Class[4]; arrayOfClass[0] = Context.class; arrayOfClass[1] = Boolean.TYPE; arrayOfClass[2] = BluetoothGattCallback.class; arrayOfClass[3] = Integer.TYPE; Method localMethod = localClass.getMethod("connectGatt", arrayOfClass); if (localMethod != null) { Object[] arrayOfObject = new Object[4]; arrayOfObject[0] = BleManager.getInstance().getContext(); boolean bool2 = false; arrayOfObject[1] = Boolean.valueOf(bool2); arrayOfObject[2] = gattCallback; \\这个是BluetoothGattCallback的实例 arrayOfObject[3] = Integer.valueOf(2); bluetoothGatt = (BluetoothGatt) localMethod.invoke(bleDevice.getDevice(), arrayOfObject);

他是通过反射来调用系统的方法。
亲测可行
5.多次启动Scan的问题
在多次连接启动、终止Scan 后,蓝牙会处于一种无法扫描的状态,方法已经回调了,但是却没有设备被扫描出来,因此,最好不要多次startScan 和cancelScan,如果需要保持多次scan,最好保持在scan状态,即使这样耗电会比较高。

    推荐阅读