4***@qq.com
4***@qq.com
  • 发布:2020-07-09 10:16
  • 更新:2023-08-05 14:46
  • 阅读:3450

【报Bug】Uniapp BLE Android平台开启notify的BUG,接口为uni.notifyBLECharacteristicValueChange

分类:uni-app

产品分类: uniapp/App

PC开发环境操作系统: Windows

PC开发环境操作系统版本号: windows 10

HBuilderX类型: 正式

HBuilderX版本号: 2.6.5

手机系统: Android

手机系统版本号: Android 7.0

手机厂商: 华为

手机机型: HUAWEI MAIMANG 5

页面类型: vue

打包方式: 云端

项目创建方式: HBuilderX

操作步骤:

for (BluetoothGattDescriptor descriptor : characteristic.getDescriptors()) {
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE); // 和通知类似,但服务端不主动发数据,只指示客户端读取数据
write = gatt.writeDescriptor(descriptor);
}

预期结果:
  1. 于是我们使用android原生工程去定位问题,发现要主动设置 :
    BluetoothGattDescriptor descriptor = characteristic.getDescriptor(UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"));
    descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
    gatt.writeDescriptor(descriptor);

实际结果:

无法在android上面开启BLE notify功能

bug描述:

目前我们再使用uniapp开发一款测温APP,在连接一款医疗资质认证过的BLE测温仪的时候,BLE在android平台上面读通道notify功能始终无法使用 uni.notifyBLECharacteristicValueChange 打开notify功能,导致数据无法在uni.onBLECharacteristicValueChange()中上报上来,后来在把相同的代码放到iOS上面去运行,iOS是可以上来数据。

  1. 在微信小程序(Android)测试,可以收到notify上报数据;
  2. 于是我们使用android原生工程去定位问题,发现要主动设置 :
    BluetoothGattDescriptor descriptor = characteristic.getDescriptor(UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"));
    descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
    gatt.writeDescriptor(descriptor);
  3. 在dcloud公布的工程代码Bluetooth feature中发现notifyBLECharacteristicValueChange函数处理这段代码的时候是这样处理的:
    for (BluetoothGattDescriptor descriptor : characteristic.getDescriptors()) {
    descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE); // 和通知类似,但服务端不主动发数据,只指示客户端读取数据
    write = gatt.writeDescriptor(descriptor);
    }
    但现在问题是: characteristic.getDescriptors()平常大部分是返回为空的,有些设备会返回有多个Descriptor,但不是每一个Descriptor都能写ENABLE_NOTIFICATION_VALUE,BLE开启notify功能目前约定为 UUID.fromString("00002902-0000-1000-8000-00805f9b34fb") 这一个Descriptor,如果往其它用途的Descriptor中写入后,蓝牙通信功能就失效了,请考录优化一下这段处理代码。

另外附上所有 Descriptor的用途:

// GATT Descriptors
attributes.put("00002900-0000-1000-8000-00805f9b34fb", "Characteristic Extended Properties");
attributes.put("00002901-0000-1000-8000-00805f9b34fb", "Characteristic User Description");
attributes.put("00002902-0000-1000-8000-00805f9b34fb", "Client Characteristic Configuration");
attributes.put("00002903-0000-1000-8000-00805f9b34fb", "Server Characteristic Configuration");
attributes.put("00002904-0000-1000-8000-00805f9b34fb", "Characteristic Presentation Format");
attributes.put("00002905-0000-1000-8000-00805f9b34fb", "Characteristic Aggregate Format");
attributes.put("00002906-0000-1000-8000-00805f9b34fb", "Valid Range");
attributes.put("00002907-0000-1000-8000-00805f9b34fb", "External Report Reference Descriptor");
attributes.put("00002908-0000-1000-8000-00805f9b34fb", "Report Reference Descriptor");

2020-07-09 10:16 负责人:无 分享
已邀请:
l***@qq.com

l***@qq.com - QQ282580583

建议修改优化notifyBLECharacteristicValueChange完整代码

public void notifyBLECharacteristicValueChange(IWebview pwebview, JSONArray args) {  
        String callbackid = args.optString(0);  
        JSONObject param = args.optJSONObject(1);  
        String serviceId = param.optString("serviceId");  
        String deviceid = param.optString("deviceId");  
        String characteristicId = param.optString("characteristicId");  
        boolean state = param.optBoolean("state", true);  
        this.checkNull(pwebview, callbackid, serviceId, deviceid, characteristicId);  
        if (this.isInit) {  
            if (state) {  
                BluetoothGatt gatt = this.getBluetoothGatt(deviceid);  
                if (gatt != null) {  
                    BluetoothGattService service = gatt.getService(UUID.fromString(serviceId));  
                    if (service != null) {  
                        BluetoothGattCharacteristic characteristic = service.getCharacteristic(UUID.fromString(characteristicId));  
                        if (characteristic == null) {  
                            JSUtil.execCallback(pwebview, callbackid, StringUtil.format("{code:%d,message:'%s'}", new Object[]{10005, "no characteristic"}), JSUtil.ERROR, true, false);  
                            return;  
                        }  

                        boolean notification = gatt.setCharacteristicNotification(characteristic, true);  
                        boolean write = false;  
//********修改开始  
                        BluetoothGattDescriptor descriptor = characteristic.getDescriptor(UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"));  
                        if ((characteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_INDICATE) == BluetoothGattCharacteristic.PROPERTY_INDICATE) {  
                            //以indicate的方式打开特征通道    
                            descriptor.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);  
                            notification = gatt.writeDescriptor(descriptor);  
                            write = true;  
                        } else {  
                            //以notify的方式打开特征通道    
                            descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);  
                            notification = gatt.writeDescriptor(descriptor);  
                            write = true;  
                        }  
//****修改结束  
                        if (notification) {  
                            JSUtil.execCallback(pwebview, callbackid, StringUtil.format("{code:%d,message:'%s'}", new Object[]{0, "ok"}), JSUtil.OK, true, false);  
                        } else {  
                            JSUtil.execCallback(pwebview, callbackid, StringUtil.format("{code:%d,message:'%s'}", new Object[]{10011, "notify fail"}), JSUtil.ERROR, true, false);  
                        }  
                    } else {  
                        JSUtil.execCallback(pwebview, callbackid, StringUtil.format("{code:%d,message:'%s'}", new Object[]{10004, "no service"}), JSUtil.ERROR, true, false);  
                    }  
                }  
            }  
        } else {  
            JSUtil.execCallback(pwebview, callbackid, StringUtil.format("{code:%d,message:'%s'}", new Object[]{10000, "not init"}), JSUtil.ERROR, true, false);  
        }  

    }
l***@qq.com

l***@qq.com - QQ282580583

  1. 应该要判断getProperties 是NOTIFY还是INDICATE 然后调用相应的
    descriptor.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);
    descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);

目前看官方notifyBLECharacteristicValueChange代码,全部使用BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE,导致如果是indication属性的使能无效。

2.characteristic.getDescriptors()平常大部分是返回为空,BLE开启notify功能目前约定为 UUID.fromString("00002902-0000-1000-8000-00805f9b34fb") 这一个Descriptor,如果往其它用途的Descriptor中写入后,蓝牙通信功能就失效了,请考录优化一下这段处理代码。

代码如下

 //获取uuid为2902的Descriptor  
BluetoothGattDescriptor descriptor=characteristic.getDescriptor(UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"));  
        boolean isSuccess=gatt.setCharacteristicNotification(characteristic, true);  

//根据不同的打开方式,调用不同的接口,如setNotify还是setIndicat  

        if((characteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_INDICATE)==BluetoothGattCharacteristic.PROPERTY_INDICATE)  
        {  
            //以indicate的方式打开特征通道  
            descriptor.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);  
            isSuccess= gatt.writeDescriptor(descriptor);  
        }  
        else  
        {  
            //以notify的方式打开特征通道  
            descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);  
            isSuccess= gatt.writeDescriptor(descriptor);  
        }
l***@qq.com

l***@qq.com - QQ282580583

我重构了下Bluetooth feature的代码,代码地址:
https://github.com/LiuXinyi/H5P.Android/tree/sinyi/feature/Bluetooth/src/io/dcloud/feature/bluetooth

可自行下载附件改后缀为aar,放在宿主app测试,也可以用源码编译出aar

目前自测是没有问题~,但是有流程还未跑全,不排除有bug

https://github.com/dcloudio/H5P.Android/pull/14

  • 1***@qq.com

    请问如何编译操作呢?求大佬教教

    2022-04-06 22:32

  • 1***@qq.com

    可自行下载附件改后缀为aar,放在宿主app测试,也可以用源码编译出aar

    请问如何编译附件?

    2022-04-06 22:41

于鹏飞

于鹏飞

遇到了同样的问题,希望官方及时修复。感谢!

三段码农

三段码农 - 从5+到uniapp,6年开发,一路成长。

希望官方能看到

DCloud_Android_zl

DCloud_Android_zl

已采纳,将会在下版更新。

  • 三段码农

    希望尽快看到新版本,不然这个uni-app小程序方案就要砍掉了,555

    2020-07-17 15:46

  • l***@qq.com

    https://github.com/dcloudio/H5P.Android/pull/14 大佬code review 一下 自测目前还未发现bug

    2020-08-07 20:15

  • f***@qq.com

    我们也遇到同样的问题

    2020-09-04 14:59

  • d***@163.com

    修复了吗?在哪个版本?

    2021-06-08 14:16

1***@qq.com

1***@qq.com

呵呵呵呵

[已删除]

[已删除]

前端人找资源(外包),熟悉uni、vue开发。APP、小程序、H5、PC端网站都可以做,找资源(外包),找有资源的服务端开发都行,有的话加微信13192733603。

jrexe

jrexe

有没有大佬提示一下 iOS BLE后台持续保持监听的问题

f***@qq.com

f***@qq.com - balbal

目前遇到一个大问题,苹果手机微信小程序蓝牙都正常,安卓手机微信小程序监听特征值后无法获得任何上报的数据!!而且监听特征值的返回只有errMsg没有errCode,貌似内部bug。目前安卓手机蓝牙不可操作没有返回值。

1***@qq.com

1***@qq.com - 开发者

请问这个问题修复了吗?在哪个版本修复的?我在hbuilder版本呢2.9.3 20201014正式版本也遇到,急用!!!!!!!!!!!!!!!!我的在安卓调用notifyBLECharacteristicValueChange时报10004 no service,ios手机上调用无此问题。

1***@qq.com

1***@qq.com - 开发者

遇到了同样的问题,希望官方及时修复。感谢!

g***@126.com

g***@126.com

2.9.11 alpha飘过,依然存在这个bug

d***@163.com

d***@163.com

目前为止还是有这样的问题,HBX 3.1.13的
到底有没有修复?

1***@qq.com

1***@qq.com - test-wr

3.3.11 仍然存在改bug.

  • 1***@qq.com

    3.3.13 仍然存在该bug.

    2022-04-07 10:52

l***@qq.com

l***@qq.com - QQ282580583

撤了吧,搞蓝牙还是得用原生

typhcl

typhcl

目前版本还是GG

7***@qq.com

7***@qq.com

同样的问题,IOS接收没问题,但是android不行,差点要放弃uniapp 安卓端了,终于找到了解决办法,双版本都正常接收到数据

plus.bluetooth.notifyBLECharacteristicValueChange({  
    state: true, // 启用 notify 功能  
    // 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接  
    deviceId:devinfo.deviceId,  
    // 这里的 serviceId 需要在 getBLEDeviceServices 接口中获取  
    serviceId:devinfo.advertisServiceUUIDs[0],  
    characteristicId:res.characteristics[0].uuid,  
    state:true,  
    success(res) {  
        console.log('notifyBLECharacteristicValueChange success', res.errMsg)  
        console.log("开始监听notify");  
        setTimeout(()=>{  
            plus.bluetooth.onBLECharacteristicValueChange((res) => {  
                console.log(res)  
            })  
        },500)  
    },  
     fail(res) {  
        console.log(res)  
        uni.showToast({  
            icon:"none",  
            title:res.errMsg  
        })  
     }  
})
  • typhcl

    是要加一个延迟

    2023-08-11 11:28

要回复问题请先登录注册