uni-app 低功耗蓝牙的监听事件无法移除

uni-app 低功耗蓝牙的监听事件无法移除

类别 信息
产品分类 uniapp/App
PC开发环境操作系统 Mac
PC开发环境操作系统版本号 Mac min Apple M1
HBuilderX类型 正式
HBuilderX版本号 4.66
手机系统 Android
手机系统版本号 Android 15
手机厂商 小米
手机机型 REDMI K80 Pro
页面类型 vue
vue版本 vue3
打包方式 云端
项目创建方式 HBuilderX

操作步骤:

/** 开锁 */  
const openLock = () => {  
    uni.showLoading({  
        title: '正在开锁',  
        mask: true  
    });  
    uni.getBLEDeviceCharacteristics({  
        deviceId: deviceId.value,  
        serviceId: targetServiceId  
    });  
    const instruction = calculateUnlockingInstructions(deviceId.value);  
    const data = hex2ArrayBuffer(instruction);  
    if (!isCreateListener.value) {  
        createListener();  
    }  
    setTimeout(async () => {  
        await sendToDevice(deviceId.value, hex2ArrayBuffer(obtainElectricity));  
        await sendToDevice(deviceId.value, data);  
        uni.hideLoading();  
    }, 800);  
};  
/** 创建监听 */  
const createListener = () => {  
    uni.notifyBLECharacteristicValueChange({  
        deviceId: deviceId.value,  
        serviceId: targetServiceId,  
        characteristicId: targetCharacteristicId_NOTIFY,  
        state: true,  
        success: () => {  
            if (!isCreateListener.value) {  
                isCreateListener.value = true;  
                uni.onBLECharacteristicValueChange((res) => {  
                    let result = ab2hex(res.value as any);  
                    if (result.indexOf('50') > -1) {  
                        const decode = xOr(`${deviceId.value}:${result.slice(6, 8)}`);  
                        const power = parseInt(decode, 16);  
                        uni.showModal({  
                            content: `电量${power}`  
                        });  
                    }  
                });  
            }  
        },  
        fail: (err) => {  
            uni.showModal({  
                content: `启动notify失败,原因${err.errMsg},错误码${err.code}`  
            });  
        }  
    });  
};

预期结果:

创建一次监听代码每次执行都会触发监听

实际结果:

但是只执行一次,如果多次创建就会一直叠加监听效果

bug描述:

低功耗蓝牙的监听事件无法移除,使用closeBluetoothAdapter和closeBLEConnection都没有效果,如果只创建一次那么onBLECharacteristicValueChange就执行一次,如果创建多次那么监听效果就无限叠加


更多关于uni-app 低功耗蓝牙的监听事件无法移除的实战教程也可以访问 https://www.itying.com/category-93-b0.html

1 回复

更多关于uni-app 低功耗蓝牙的监听事件无法移除的实战教程也可以访问 https://www.itying.com/category-93-b0.html


这是一个典型的蓝牙事件监听器重复注册问题。在uni-app中,uni.onBLECharacteristicValueChange是一个全局事件监听器,每次调用createListener()都会注册一个新的监听器,导致回调函数被重复执行。

问题核心在于:

  1. uni.onBLECharacteristicValueChange没有对应的移除方法
  2. 使用isCreateListener.value标志位无法阻止重复注册
  3. 关闭蓝牙适配器或连接不会自动移除已注册的监听器

解决方案:

let characteristicValueCallback = null;

/** 创建监听 */
const createListener = () => {  
    if (characteristicValueCallback) {
        return; // 避免重复注册
    }
    
    uni.notifyBLECharacteristicValueChange({  
        deviceId: deviceId.value,  
        serviceId: targetServiceId,  
        characteristicId: targetCharacteristicId_NOTIFY,  
        state: true,  
        success: () => {  
            characteristicValueCallback = (res) => {  
                let result = ab2hex(res.value);  
                if (result.indexOf('50') > -1) {  
                    const decode = xOr(`${deviceId.value}:${result.slice(6, 8)}`);  
                    const power = parseInt(decode, 16);  
                    uni.showModal({  
                        content: `电量${power}`  
                    });  
                }  
            };
            
            uni.onBLECharacteristicValueChange(characteristicValueCallback);  
        },  
        fail: (err) => {  
            uni.showModal({  
                content: `启动notify失败,原因${err.errMsg},错误码${err.code}`  
            });  
        }  
    });  
};

/** 移除监听 */
const removeListener = () => {
    if (characteristicValueCallback) {
        // 由于uni-app没有提供直接移除的方法,需要通过关闭notify来间接移除
        uni.notifyBLECharacteristicValueChange({
            deviceId: deviceId.value,
            serviceId: targetServiceId,
            characteristicId: targetCharacteristicId_NOTIFY,
            state: false,
            success: () => {
                characteristicValueCallback = null;
                isCreateListener.value = false;
            }
        });
    }
};
回到顶部