安卓蓝牙开发填坑之路

作者: MrHorse1992 | 来源:发表于2018-01-15 15:36 被阅读572次

    前言

    入职不久,也是刚刚接触安卓开发。公司主要业务是嵌入式设备以及可穿戴设备。因此新人主要任务就是学习安卓蓝牙开发。

    由于没有任何经验因此在开发过程中踩到了许多坑,今天将这些填坑过程分享出来,希望以后开发中避免这些问题。

    (一)传递对象而不传递地址

    开发之初实现主界面搜索设备,点击目标设备进入连接、通信界面的功能,因此需要传递目标设备BluetoothDevice的相关信息。起初采用Intent传递Bluetooth.getAddress()方式传递蓝牙的Mac地址,在ManagerActivity调用BluetoothDevice device = mBluetoothAdapter.getRemoteDevice()获取设备。实际使用中发现此函数比较耗时,影响效率。

    解决办法:使用Intent传递BluetoothDevice对象。BluetoothDevice实现了Parcelable接口,可以使用Intent直接传递。

    (二)加上延时,保证执行完毕

    手机端打开蓝牙、关闭蓝牙、开启搜索和停止搜索都需要一定的时间来完成,因此在执行以上操作后最好加上一段延时,等待对应操作完成后再去执行下一步。

    (三) BLE蓝牙连接参数

    经典蓝牙建立连接后类似于Socket通信,出现问题的情况不多。遇到问题的情况大多数出现在BLE蓝牙中。
    device.connectGatt(context, autoConnect, callback);第二个参数最好设置为false,实际测试发现设置为false连接速度更快。

    (四)找准UUID,成功开启监听

    BLE蓝牙的服务和特征都是通过UUID来查找的,开发时一定要区分好哪个BluetoothGattCharacteristic是用于setCharacteristicNotification的,哪个BluetoothGattCharacteristic是用于writeCharacteristic的。
    setCharacteristicNotification函数用于开启监听,执行成功后相当于与设备建立通信通道,之后可以通过写入命令指令来获取设备中的数据。
    setCharacteristicNotification的返回值基本上一直都是true,但是不代表开启监听成功。通过查看谷歌官方BLEdemo发现安卓系统下还需要设置用于监听下BluetoothGattCharacteristic的UUID为"00002902-0000-1000-8000-00805f9b34fb"的BluetoothGattDescriptor的Value为BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE。
    当设置成功后回调onDescriptorWrite,当status == BluetoothGatt.GATT_SUCCESS基本上才能实现开启监听。而且开启监听以后最好还是要等待200ms左右再向设备发命令,等待设备和手机建立稳定通信通道。

    (五)最多20字节

    成功开启监听后,终于可以与设备通信了。我使用的设备是一个便携式心电计。上位机发送命令指令,下位机回复的数据格式均为64字节,然后将64字节解析出心率和心电图数据。理想很丰满,然而实际使用中才发现每次回调onCharacteristicChanged方法获取的数据最多20字节,64字节的数据分成了4包发送上来。

    解决办法:只能用缓冲区接收了,判断缓冲区大小、判断缓冲区第一个字节,根据数据头读取缓冲区,并进一步解析数据。

    不过值得庆幸的是上位机命令指令均小于20字节,起码写入数据不需要分包发送,如果真有遇到这种特殊情况的请看BLE分包发送

    既然最多20字节一包数据,大数据通信就不要考虑BLE了。

    (六)一定要关闭连接

    我就有一段程序在通信完毕后忘记了断开连接,发现之后再次连接设备以后每写入一次命令onCharacteristicChanged回调多次相同数据,使得缓冲区处理出现问题。感觉就是建立了多个连接通道。在通信出错或者完成同步之后一定要调用mBluetoothGatt.disconnect();
    mBluetoothGatt.close();
    断开当前连接。

    (七)加密BLE设备

    大多数BLE设备是非加密的,也就是不需要与手机配对即可通信。大部分软件都是同步BLE设备的中数据到手机端,整个流程也是自动执行的。大体流程就是:扫描目标设备、开启连接、连接成功扫描服务,扫到服务开启监听、收发数据、断开连接。

    BLE设备加密后在连接设备时会弹出系统蓝牙配对对话框,等待用户配对。按常理说此时设备是没有建立连接的,因为还没有配对成功,但是安卓手机端不仅可以完成建立连接,而且还能扫描到服务。如果按照自动流程就去开启监听是无法成功的,因为设备还没有配对成功。

    解决办法:监听系统关于蓝牙配对的广播,在完成配对之后在去开启监听。如果是已经配对的设备不会由蓝牙配对广播,只需按照不加密设备流程执行即可。

    (八)6.0以上权限问题

    最初测试用的设备比较老旧,有天用新手机测试发现根本不能扫描到蓝牙设备,查询之后发现是权限问题。安卓6.0以后扫描蓝牙需要模糊定位权限

    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    

    安卓随着版本提升对于权限限制更加严格,还是学着用动态申请权限吧。

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        if (this.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, 1);
        }
    }
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }
    

    (九)碎片化带来各种问题

    安卓系统碎片化导致遇到了各种奇葩问题:
    华为mate8 mate9 荣耀6a无法主动断开与加密BLE设备连接,除非取消配对或者关闭某一方的蓝牙。
    魅族Flyme系统第一次配对成功后不能断开连接,以后使用可以正常断开。
    部分手机在BLE设备连接上之后会主动断开一次连接,然后马上又重新连接上设备。

    结语

    以上就是本人在安卓蓝牙开发中遇到的诸多问题,由于缺乏经验和能力相对不足,踩到了很多坑,不过在填坑过程中提高自身能力也是很满足的。

    相关文章

      网友评论

      本文标题:安卓蓝牙开发填坑之路

      本文链接:https://www.haomeiwen.com/subject/ldoroxtx.html