Ble蓝牙开发遇到的坑

 蓝牙Ble相关的开发看似很简单,但是总有一些小细节不清楚就会让你容易入坑。现在就我在蓝牙开发过程中遇到的一些坑和一些需求的解决方式进行总结,也算是对前期蓝牙开发的一些记录。

什么是蓝牙BLE?
蓝牙Ble就是一种新的蓝牙标准,google从Android4.3开始支持蓝牙Ble。我们知道蓝牙发展至今经历多个版本,如1.1、1.2、2.0、2.1、3.0、4.0、4.1、4.2。在1.1~3.0之间的我们称之为传统蓝牙,4.x开始的蓝牙我们称之为低功耗蓝牙也就是蓝牙ble。低功耗蓝牙比传统蓝牙,传输速度更快,覆盖范围更广,安全性更高,延迟更短,耗电极低等优点。传统蓝牙与低功耗蓝牙通信方式也有所不同,传统的一般通过socket方式,而低功耗蓝牙是通过Gatt协议来实现。
BLE蓝牙有三部分:Service,Characteristic,Descriptor。这三部分都用UUID作为唯一标识符。UUID为这种格式:0000ffe1-0000-1000-8000-00805f9b34fb。不同的UUID有不同的属性和作用。

1、一般蓝牙开发中我们一般的流程是 开启系统蓝牙》搜索蓝牙》配对蓝牙》,但是在有些场景中该流程不太适合。该流程每次需要连接蓝牙的时候都需要重新搜索、配对。当周边蓝牙设备过多时就难免出现搜索时间长,对于需要流水式作业时使用的体验就很不好。
解决方式:一次配对,将固定蓝牙设备名和mac地址缓存起来,以后每次均通过Mac地址获取远程蓝牙对象,直接发起连接,不用走标准的蓝牙连接流程。

2、在连接蓝牙后一般需要开启蓝牙使通知功能,开启后既可以接收蓝牙发送的数据;
坑:当收到蓝牙连接成功的通知后立即调用 gatt.discoverServices();去搜索蓝牙服务;有时出现蓝牙服务搜索不到的情况。
原因:蓝牙的很多操作都是异步的,此时可以稍微延迟执行搜索服务;

3、如果发现连接上了,service也找到了,但是始终不能触发onCharacteristicChanged的,一定要查找如下2个重要原因:
1). 一定要gatt.setCharacteristicNotification(characteristic, enable);
2). 如果设置了1).却还是发现没有触发,加上对此Characteristic的descriptor做indication Enable就应该可以了;

for(BluetoothGattDescriptor dp:characteristic().getDescriptors()) {
dp.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
mBluetoothGatt().writeDescriptor(dp);
}

4、对蓝牙的许多操作最好放在主线程中执行如:BluetoothDevice.conncectGatt(),
BluetoothGatt.connect(),
BluetoothGatt.disconnect(),
BluetoothGatt.discoverServices()
否则会遇到很多意想不到的麻烦。

5、 一个主设备(例如Android手机)可以同时连接多个从设备(一般为6个,例如智能硬件。超过就连接不上了),一个从设备只能被一个主设备连接,一旦从设备连接上主设备,就停止广播,断开连接则继续广播。在任何时刻都只能最多一个设备在尝试建立连接。如果同时对多个蓝牙设备发起建立Gatt连接请求。如果前面的设备连接失败了,则后面的设备请求会被永远阻塞住,不会有任何连接回调。所以建议:如果要对多个设备发起连接请求,最好是一个接一个的顺序同步请求管理。

6、 任何出错,或超时,都调用一下Gatt.disconnect(),然后在收到蓝牙断开连接的广播后再调用 Gatt.close()。

7、扫描尽量不要放在主线程进行,可以放入子线程里。

8、对于需要输入配对的pin来配对的蓝牙设备,但又不需要用户输入配对的需求,可以采用映射的方式来配对连接。
(1)、获得蓝牙对象 BluetoothDevice btd = mAdapter.getRemoteDevice(lymac2);
(2)、使用ClsUtils(已开放,百度有很多)工具中的setPin方法:
ClsUtils.setPin(myBlutoothdvice.getClass(), myBlutoothdvice, “123456”);
(3)、调用连接 mBluetoothGatt = myBlutoothdvice.connectGatt(mContext, false, mGattCallback);

9、Ble蓝牙设备通讯使用UUID分别获取读、写对象,打开蓝牙通知服务的一般都使用for循环语句,最好不要用UUID来单独获取读写对象,避免在有些设备上获取不到的问题。

private void discoverService() {
    for (BluetoothGattService service : mGatt.getServices()) {
        if (CCCD.equals(service.getUuid().toString())) {
            List<BluetoothGattCharacteristic> gattCharacteristics = service
                    .getCharacteristics();
            for (BluetoothGattCharacteristic bluetoothGattCharacteristic : gattCharacteristics) {
                if (bluetoothGattCharacteristic.getUuid().toString().equals(BLUETOOTH_NOTIFY_D)) {
                    setCharNotification(bluetoothGattCharacteristic, true);
                }
            }
        }

        if (WRITESERVICEUUID.equals(service.getUuid().toString())) {
            List<BluetoothGattCharacteristic> gattCharacteristics = service
                    .getCharacteristics();
            for (BluetoothGattCharacteristic bluetoothGattCharacteristic : gattCharacteristics) {
                if (bluetoothGattCharacteristic.getUuid().toString().equals(WRITECHARACTERISTICUUID)) {
                    writeGattCharacteristic = bluetoothGattCharacteristic;
                    mListener.onInitServicesed();
                }
            }
        }
    }

}

private void setCharNotification(BluetoothGattCharacteristic characteristic, boolean enabled) {
//开启蓝牙通知服务
    if (mGatt == null) {
        return;
    }
    boolean isEnableNotification = mGatt.setCharacteristicNotification(characteristic, enabled);
    if (isEnableNotification) {
        List<BluetoothGattDescriptor> descriptorList = characteristic.getDescriptors();
        if (descriptorList != null && descriptorList.size() > 0) {
            for (BluetoothGattDescriptor descriptor : descriptorList) {
                descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
                mGatt.writeDescriptor(descriptor);
            }
        }
    }
}

10、蓝牙 API 连接蓝牙设备的超时时间大概在 20s 左右,具体时间看系统实现。有时候某些设备进行蓝牙连接的时间会很长,大概十多秒。

待续·······

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xiawj8957

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值