欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

蓝牙BLE 的几个坑与心得!

程序员文章站 2024-03-24 23:14:34
...

第一次写CSDN博客,多多关照

公司APP的业务是做蓝牙mesh组网的,具体协议我就不提了,具体通讯方式是Gatt连接和非连接,非连接是通过扫描与广播进行通讯的。

分享一下几个坑与心得:

1.BLE广播 BluetoothLeAdvertiser
广播设置 AdvertiseSettings有一项是timeout,这个timeout千万不要用,有很严重的bug,会导致广播无法关闭(disconnect),甚至即使把APP给杀死然后重启也无济于事!设置了timeout不等于0的话,只能成功广播一次,之后的所有广播,都会失败,即使重启APP,也是失败,只能重启蓝牙!
解决方法:timeout设置为0,或者不设置,写一个新的线程控制它的关闭(disconnect)

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状态,即使这样耗电会比较高。

相关标签: 蓝牙 Android