自从Android-BLE库开源了一段时间以来,愈来愈多的小伙伴问到了各类各样的关于BLE的奇怪问题,在这里我想跟你们分享一下本人对于Android BLE蓝牙的一些见解和解决方式,避免刚接触的小伙伴再次踩坑。android
不少人曾问过我这个问题,为何其余手机都没什么问题,就华为的一些手机总是链接不稳定,常常链接的很慢,并且链接上还常常断开。的确,在这里强调一下华为的一部分手机确实很容易出现这种问题,有时候软件、硬件都搞不定,并且常常性收到客户投诉关于华为手机链接稳定性问题,这个的确没有彻底解决的办法,只能靠App和硬件的优化,并非想甩锅给华为,咱也不敢问究竟是什么缘由,并且咱们公司专门针对各个Android版本的手机作过测试,包括蓝牙传输速率的测试,最后发现华为P20的速度居然跟小米8的速度差了好几倍,按理说P20手机也不便宜啊,为何手机蓝牙芯片不能作的再好一点呢?git
先肯定下列几项是否知足:
一、蓝牙是否打开
二、蓝牙相关权限是否受权(6.0以上位置权限)
三、7.0以上手机不少须要手动打开GPS
复制代码
缘由:
出现这个问题的不少是Android7.0以上手机,为何呢?
由于Google为了防止Android7中的BLE扫描滥用,从而作了一些限制,即不要在30s内对蓝牙扫描
重复开启-关闭超过5次。
建议:
设置扫描周期>6s, 用户点击扫描后不要重复进行扫描,能够作一个是否正在扫描的标志位,若是
正在扫描就不作重复扫描动做了。
复制代码
BLE扫描滥用预防github
Android8.0以上退到后台息屏后,为了保证省电等缘由,若是不设置ScanFilters的话是默认扫不到设备的,
因此解决办法就是设置以下:
mScannerSetting = new ScanSettings.Builder()
//退到后台时设置扫描模式为低功耗
.setScanMode(ScanSettings.SCAN_MODE_LOW_POWER)
.build();
mFilters.add(new ScanFilter.Builder()
//过滤扫描蓝牙设备的主服务
.setServiceUuid(ParcelUuid.fromString("0000ffff-0000-1000-8000-00805f9bfffb"))
.build());
mScanner.startScan(mFilters, mScannerSetting, mScannerCallback);
复制代码
息屏状态下,蓝牙扫描日志,由于扫描周期是12s,因此打印的时间戳间隔是12s,这里的日志为系统日志。bash
翻译:
启动蓝牙扫描。扫描结果将经过回调传递。对于未通过滤的扫描,扫描是中止在屏幕上关闭,以节省
电力。再次打开屏幕时,将恢复扫描。为了不这种状况,请使用适当的扫描过滤器进行文件扫描。
复制代码
可能缘由:
在使用 BluetoothDevice.connectGatt() 或者 BluetoothGatt.connect() 等创建 BluetoothGatt
链接的时候,在任什么时候刻都只能最多一个设备在尝试创建链接。若是同时对多个蓝牙设备发起创建 Gatt
链接请求。若是前面的设备链接失败了,后面的设备请求会被永远阻塞住,不会有任何链接回调。
建议:
若是要对多个设备发起链接请求,最好创建一个请求队列,前一个设备请求创建链接,后面请求在队列中等待
。若是链接成功了,就处理下一个链接请求。若是链接失败了(例如出错,或者链接超时失败),就立刻调用
BluetoothGatt.disconnect()/close()来释放创建链接请求,而后处理下一个设备链接请求。
复制代码
链接成功后,会进行BluetoothGatt.discoverServices()去发现服务,进而设置特征值等,由于该方法是在主
线程中执行的,因此为了链接过程的可靠性,建议不要在该过程当中,在主线程中不要处理太多的操做(尤为是频
繁绘制操做)。
复制代码
这个问题其实并不主要是客户端的问题,因此不要一味的在代码中找问题了,建议与硬件沟通,让其进行优化
,如能够调整设备的链接参数(ConnectionInterval(链接间隔)、SlaveLatency(从设备延迟或者从设备时
延)、SupervisionTimeout(超时时间或者监控超时)),这三个参数是低功耗蓝牙中十分重要的链接参数,
一块儿决定了BLE的功耗,通常硬件设备会在APP链接成功时主动去更新一下这三个参数,以保证不一样手机的差别
性获得一致,可是APP端是没办法控制这三个参数的。
复制代码
标准答案是7个,为何是7个,这个咱们能够从以下图所示的底层蓝牙源码中找到依据。
复制代码
android.googlesource.com/platform/ex…app
发起蓝牙Gatt链接 BluetoothDevice.connectGatt(Context context, boolean autoConnect,
BluetoothGattCallback callback),这里有一个参数autoConnect,若是为 true
的话,系统就会发起一个后台链接,等到系统发现了一个设备,就会自动连上,一般这个过程是很是慢的。为
false 的话,就会直接链接,一般会比较快。一样,BluetoothGatt.connect()只能发起一个后台链接,不是直
接链接,因此链接时设置autoConnect参数设置为false,若是想实现重连功能的话,本身去手动实现吧,实在不
想手动写,那就用Android-BLE库吧,你想要的基本都有。
复制代码
缘由:可能因为首次链接蓝牙后没有释放掉gatt资源致使的蓝牙协议栈异常,从而出现133或257
19等值不为0:因为协议栈,链接创建失败
建议:在onConnectionStateChange()回调中判断,若state非0(链接断开),调用gatt.close(),手动释放掉
gatt相关资源
复制代码
缘由:
一、首先肯定主服务是否正确,再看设置的读、写特征值是否正确
二、由于BLE发现服务和设置特征、通知等是须要耗时的,因此你并不能链接成功后立马发送数据,能够等到在
onDescriptorWrite()回调时,或者手动延迟一段时间再去作发送操做。
复制代码
BLE4.0蓝牙发送数据,单次最大传输20个byte,若是是通常的协议命令,如:开关灯、前进左右等等,是不须要
分包的,若是是须要发送如:图片、BIN文档、音乐等大数据量的文件,则必须进行分包发送,BLE库中已经提
供了发送大数据包的接口,须要的小伙伴能够去下载DEMO查看用法。
复制代码