Yukin
Yukin
  • 发布:2020-09-10 18:56
  • 更新:2024-08-09 16:57
  • 阅读:4213

【报Bug】uniapp蓝牙无法取消监听

分类:uni-app

产品分类: uniapp/App

PC开发环境操作系统: Windows

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

HBuilderX类型: 正式

HBuilderX版本号: 2.8.11

手机系统: Android

手机系统版本号: Android 9.0

手机厂商: OPPO

手机机型:

页面类型: vue

打包方式: 云端

项目创建方式: HBuilderX

操作步骤:

预期结果:

希望更新取消监听的方法

实际结果:

bug描述:

uniapp蓝牙里的监听事件,没有相对应的取消监听的方法,导致在安卓环境下多次监听,而且调用uni.closeBluetoothAdapter()关闭蓝牙模块后,监听依然存在。我看微信小程序都有对应的取消监听的方法wx.offBLEConnectionStateChange、wx.offBLECharacteristicValueChange、wx.offBLEPeripheralConnectionStateChanged,麻烦官方也跟进一下

2020-09-10 18:56 负责人:无 分享
已邀请:
b***@gmail.com

b***@gmail.com

uni.offBluetoothDeviceFound() 没实现

Jalen_cokoino

Jalen_cokoino

是的,再次重复监听的时候会得到重复蓝牙,还会多次累加,罗盘、加速度计都会这样,大大的坑,官方也不回复。我现在是把重复的数据丢掉,坑啊。。。。。。。。。。。。
给你看我处理的办法
'''
uni.onBluetoothDeviceFound(devices => { //开启 监听寻找到新设备的事件
//console.log("发现设备: " + JSON.stringify(devices)); //JSON.stringify() 方法用于将 JavaScript 值转换为 JSON 字符串
if (!self.deviceList.some(item => { //不重复,就添加到devicesList中,
return item.deviceId === devices.devices[0].deviceId
})) {
if (devices.devices[0].name != "") { //保存蓝牙名称不为空的蓝牙设备参数
self.deviceList.push ({
name : devices.devices[0].name,
deviceId: devices.devices[0].deviceId,
RSSI : devices.devices[0].RSSI,
})
//蓝牙自动链接,当手机靠近蓝牙设备达到一定距离时,依据蓝牙名称和RSSI的强度来判断链接蓝牙设备
if(devices.devices[0].name === "HMSoft" || devices.devices[0].name === "BBC micro:bit [gavop]"){
if(devices.devices[0].RSSI > -48){
self.createBLEConnection(devices.devices[0].deviceId);
}
}
}
}
});
'''

  • Yukin (作者)

    感谢老哥,我试试看。不过蓝牙多次累加到一定次数,安卓机就会卡死,我也是很无语

    2020-09-10 19:56

  • Jalen_cokoino

    有答案也告诉我一下,感谢

    2020-09-11 08:07

  • Yukin (作者)

    回复 Jalen_cokoino: 老哥,我现在的做法是把所有的监听都放在app.vue这个文件的onLaunch生命周期里(onBLEConnectionStateChange、onBLECharacteristicValueChange、onBluetoothDeviceFound),这样进app的时候就只会监听一次,然后在具体的页面就只需要做连接蓝牙、获取服务、获取特征值和发指令的操作就行了

    2020-09-15 15:00

Jalen_cokoino

Jalen_cokoino

没人理会这个问题????

j***@163.com

j***@163.com - uniapp小白

我现在弄蓝牙,也遇到这个问题了,有什么好的办法吗?

  • Yukin (作者)

    并没有,你可以看一下一楼那位老哥的方法

    2020-09-14 17:08

  • Yukin (作者)

    看一楼,目前测过一台安卓10的oppo和一台iPhone8,暂时还没有发现问题

    2020-09-15 15:09

DCloud_Android_zl

DCloud_Android_zl

麻烦提供个示例,我们复现一下。

  • Jalen_cokoino

    进行多次搜索,直接将蓝牙监听的数据打印出来,就会看得到很多个名字相同的数据,不是偶尔事件,是百分百事件,很容易复现

    2020-09-21 10:41

  • Jalen_cokoino

    uni.onBluetoothDeviceFound(devices => { //开启 监听寻找到新设备的事件

    console.log("发现设备: " + JSON.stringify(devices)); //JSON.stringify() 方法用于将 JavaScript 值转换为 JSON 字符串

    });


    多次成功进行调用这个API,将监听的数据打印出来,就可以看得到了

    2020-09-21 10:50

  • Jalen_cokoino

    加速度计的这个API也有这个现象:

    uni.onAccelerometerChange(function (res) {

    console.log(res.x);

    console.log(res.y);

    console.log(res.z);

    });

    2020-09-21 10:57

  • Jalen_cokoino

    代码复现在下面

    2020-09-21 16:23

  • 1***@qq.com

    3年了,解决了吗?文档上还是没有 offBluetoothDeviceFound 解绑方法,每次搜索都会有重复的

    2023-11-15 16:02

Jalen_cokoino

Jalen_cokoino

<template>  
    <view class="content">  
        <button @click="search">搜索蓝牙</button>  
        <button @click="unsearch">停止搜索蓝牙</button>  
        <button @click="compass">开启罗盘</button>  
        <button @click="closecompass">关闭罗盘</button>  
        <button @click="Accelerometer">开启加速度计</button>  
        <button @click="closeAccelerometer">关闭加速度计</button>  
    </view>  
</template>  

<script>  
    export default {  
        data() {  
            return {  
                title: 'Hello'  
            }  
        },  
        onLoad() {  

        },  
        methods: {  
            search(){  
                //开启手机蓝牙模块:  
                uni.openBluetoothAdapter({  
                    success: res => {  
                        console.log("蓝牙已开启");  
                        uni.startBluetoothDevicesDiscovery({  
                            success: res => {  
                                console.log("开始监听设备...");  
                                uni.onBluetoothDeviceFound(devices => {  
                                    //重复搜索会打印重复相同数据,还会累加,多了会卡死机。  
                                    console.log("发现设备: " + JSON.stringify(devices));  
                                })  
                            },  
                        })  
                    },  
                })  
            },  
            unsearch(){  
                uni.stopBluetoothDevicesDiscovery({  
                    success: e => {  
                        console.log("停止蓝牙设备搜索");  
                    },  
                })  
            },  
            compass(){  
                uni.startCompass();  
                uni.onCompassChange(function (res) {  
                    //重复搜索会打印重复相同数据,还会累加,多了会卡死机。  
                    console.log(res.direction);  
                });  
            },  
            closecompass(){  
                uni.stopCompass();  
            },  
            Accelerometer(){  
                uni.startAccelerometer();  
                uni.onAccelerometerChange(function (res) {  
                    //重复搜索会打印重复相同数据,还会累加,多了会卡死机。  
                    console.log("x:"+res.x);  
                    console.log("y:"+res.y);  
                    console.log("z:"+res.z);  
                });  
            },  
            closeAccelerometer(){  
                uni.stopAccelerometer();  
            }  
        }  
    }  
</script>  

<style>  
    .content {  
        display: flex;  
        flex-direction: column;  
        align-items: center;  
        justify-content: center;  
    }  

    .logo {  
        height: 200rpx;  
        width: 200rpx;  
        margin-top: 200rpx;  
        margin-left: auto;  
        margin-right: auto;  
        margin-bottom: 50rpx;  
    }  

    .text-area {  
        display: flex;  
        justify-content: center;  
    }  

    .title {  
        font-size: 36rpx;  
        color: #8f8f94;  
    }  
</style>

代码复现

疯狂的瓜菜

疯狂的瓜菜

我们也出此案这个问题,不止你说的音频组件也有这个问题,我们的蓝牙部分现在做法也是丢数据,尤其是用匿名函数接收,没办法在页面被销毁后函数也会被销毁,最后我们采用动态判断的方案,我们在音频里面自己实现了全局的音频注册管理,目前音频没出现这个问题

疯狂的瓜菜

疯狂的瓜菜

在main.js里面全局挂载

import bgAudioMannager from '@/utils/helper/audioMannager.js'  
Vue.prototype.bgAudioMannager = bgAudioMannager

然后在实际使用页面的

onLoad() {  
    let callback = {  
        onTimeUpdate: (playId,duration,currentTime,buffered) => {  
            //this.onTimeUpdateOnTimeUpdate(playId,duration,currentTime,buffered)  
        },  
        onPlay: (playId) => {  
            console.log('播放')  
        },  
        onPause: (playId) => {  
            console.log('暂停')  
        },  
        onStop: (playId) => {  
            console.log('播放停止')  
        },  
        onEnded: (playId) => {  
            console.log('播放结束')  
        },  
        onPrev: () => {  
            console.log('上一首触发')  
        },  
        onNext: () => {  
            console.log('下一首触发')  
        }  
    }   
    //index为自生页面的唯一标识  
    this.bgAudioMannager.initdCallback(callback,'index')    
}
疯狂的瓜菜

疯狂的瓜菜

然后是全局代码

const initdCallback = (callback,id) => {  
    console.log("应用注册音频回调",id)  
    returnCallback[id] = callback;  
}  

const destroy = (index) => {  
    try{  
        returnCallback[index] = null;  
        delete returnCallback[index];  
    }catch(e){  
        //TODO handle the exception  
    }  
}  

returnCallback在一开始初始化的时候做回调调用
写一个调用demo


bgAudioMannager.onCanplay(() => {  
        console.log("音频加载成功")  
        for (let item in returnCallback) {  
            try{  
                returnCallback[item].onCanplay(bgPlayList[playIndex].id)  
            }catch(e){  
                //TODO handle the exception  
            }  
        }  
    })  
疯狂的瓜菜

疯狂的瓜菜

记得调用销毁

onUnload() {  
    console.log('销毁调用');  
    this.bgAudioMannager.destroy('index')  
}
1***@qq.com

1***@qq.com

现在解决了吗 还是没有 offBluetoothDeviceFound

1***@qq.com

1***@qq.com

已经完美解决,这段代码放到app.vue的onlanuch 里面
uni.onBLECharacteristicValueChange (c){
//将监听到的值转发
uni.$emit('value',c)
}

//**别的页面
uni.$on('value',function{
//处理逻辑
})

onUnload(){
uni.$off('value')
}

7***@qq.com

7***@qq.com

发现安卓app和ios app还有微信小程序中会有不同表现,目前封装了这个,使用了单例模式

import eventbus from '@/utils/eventbus'
import utils from '@/utils/utils'
import useConfigStore from '@/store/modules/config'

import i18nConfig from '@/locale/index'
const { t } = i18nConfig.global

class Bluetooth {
constructor() {
if (Bluetooth.instance) {
return Bluetooth.instance;
}
Bluetooth.instance = this;

    this.limitUUid = undefined  
    this.serviceUUid = null  
    this.platform = null  
    this.bleList = [];  
    this._discoveryStarted = false;  

    // 重发  
    this.times = 0  

    this.blePubTimer = null;  
    // 蓝牙重启计时器  
    this.bleAdpterTimer = null;  
    this.bleUpdateTime = 5000;  

    // 蓝牙设备  
    this.clearConnectInfo()  

    // 回调函数  
    this.readCb = null;  
    this.connectionStateChangeCb = null;  
    this.deviceFoundCb = null;  
    // 设置回调函数(在这里设置不会重复进入)  
    this.onBLECharacteristicValueChange();  

    this.onConnectionStateChange()  
    this.onBluetoothDeviceFound();  

}  

clearConnectInfo(){  
    this.serviceId = null;  
    this.characteristicId = null;  
    this.bluetoothId = null;  
    this.connect = false;  
    this.connecting = false;  

}  

startBle(deviceFoundCb, refresh) {  
    this.platform = useConfigStore().getConfig().platform  
    setTimeout(() => {  
    // 不同平台需要分开处理  
    // #ifdef MP  
        this.doOpenBluetoothAdapter(deviceFoundCb);  
        // #endif  
    // #ifdef APP-PLUS  
        console.log(this.platform, "refresh", refresh)  
        if (this.platform === "ios") {  
            if(refresh === false){  
                this.doOpenBluetoothAdapter(deviceFoundCb);  
            }else {  
                this.bleUpdateTime = 30000;  
                this.openBluetoothAdpter4IosApp(deviceFoundCb);  
            }  

        }  
        if (this.platform === "android") {  
            this.doOpenBluetoothAdapter(deviceFoundCb);  
        }  

    // #endif  
    }, 1300);  
    if(this.blePubTimer){  
        return  
    }  

     this.blePubTimer = setInterval(() => {  
        if (this.bleList && this.bleList.length > 0) {  
            this.bleList = this.bleList.filter((item) => {  
                if(!item.last_time){  
                    item.last_time = Date.now();  
                }  
                return Date.now() - item.last_time < this.bleUpdateTime;  
            });  
            eventbus.pub("bleList", {  
                bleList: this.bleList,  
            });  
            // console.log(this.bleList)  
        }  
    }, 1500);  
}  

async doOpenBluetoothAdapter(deviceFoundCb) {  
    uni.openBluetoothAdapter({  
        success: (res) => {  
            console.log("初始化蓝牙适配器成功", res);  
            this.startBluetoothDevicesDiscovery(deviceFoundCb); // 开始搜索  
        },  
        fail: (err) => {  
            console.log("初始化错误", err);  
            if (err?.errCode === 10001 || err?.code === 10001) {  
                // 10001:当前蓝牙适配器不可用  
                uni.showModal({  
                    title: t('public.button'),  
                    content: t('public.enableBluetooth'),  
                    showCancel: false,  
                });  
            }  
        },  
    });  
}  

clearTimer(){  
    clearInterval(this.bleAdpterTimer);  
}  

openBluetoothAdpter4IosApp(deviceFoundCb) {  
    // ios app如果不重新开启蓝牙适配器则无法获取蓝牙数据  
    clearInterval(this.bleAdpterTimer)  

    console.log("ios 打开蓝牙适配器")  

    this.bleAdpterTimer = setInterval(()=>{  
        if (this.bleList && this.bleList.length > 0) {  
            return  
        }  
        uni.closeBluetoothAdapter({  
            success: (res) => {  
                console.log("closeBluetoothAdapter 成功")  
            },  
            fail: (err) => {  
                console.log("closeBluetoothAdapter 失败", err)  
            }  
        })  
        this.doOpenBluetoothAdapter(deviceFoundCb)  
    }, 3500);  

}  

async startBluetoothDevicesDiscovery(deviceFoundCb) {  
    this.deviceFoundCb = deviceFoundCb;  

    uni.startBluetoothDevicesDiscovery({  
        powerLevel: "high",  
        allowDuplicatesKey: true,  
        services: ['FFF0'],  
        success: (res) => {  
            console.log("开始搜索", res);  
            // #ifdef MP  
            this.onBluetoothDeviceFound();  

            //  #endif  
        },  
        fail: (res) => {  
            console.log("搜索失败", res);  
            wx.showModal({  
                title: "提示",  
                content: "搜索失败,请重试",  
                showCancel: true,  
            });  
        },  
    });  
}  

onBluetoothDeviceFound() {  
    console.log("设置设备发现回调")  
    uni.onBluetoothDeviceFound((res) => {  
        // console.log("found res", res.devices)  
        res.devices.forEach((device, index) => {  
            if (!device.name && !device.localName) {  
                return;  
            }  
            // if (!utils.isDevice(device.name)) {  
            //     return;  
            // }  
            if (this.platform === "ios") {  
                device.mac = utils.uuid2mac(device.advertisData);  
                device.bluetoothId = device.deviceId  
            }  
            if (this.platform === "android") {  
                device.mac = device.deviceId;  
                device.bluetoothId = device.deviceId;  
            }  
            device.name = device.name.trim();  
            const idx = utils.inArray(this.bleList, "deviceId", device.deviceId);  
            if (idx === -1) {  
                this.bleList.push(device);  
            } else {  
                const oldDevice = {  
                    ...this.bleList[idx],  
                };  
                this.bleList[idx] = {  
                    ...oldDevice,  
                    last_time: new Date(),  
                    RSSI: device.RSSI,  
                };  
            }  
        });  

        if (this.deviceFoundCb) {  
            this.deviceFoundCb(res.devices);  
        }  
    });  
}  

connectDevice(bluetoothId, needStop,connectBeforeCb , connectSucCb,  
              connectFailCb,  
              connectionStateChangeCb,  
              closeCallback, notifyCb, readCb, serviceUUid = 'FFF0', limitUUid = undefined) {  

    this.connectionStateChangeCb = connectionStateChangeCb  
    this.readCb = readCb  

    this.clearTimer()  
    console.log('尝试连接蓝牙', bluetoothId)  
    if (this.connect) {  
        console.log('蓝牙已连接');  
        return  
    }  
    if(this.connecting){  
        console.log('蓝牙正在连接');  
        return;  
    }  

    if(connectBeforeCb){  
        connectBeforeCb()  
    }  

    this.connecting = true  
    this.bluetoothId = bluetoothId  
    this.serviceUUid = serviceUUid  
    this.limitUUid = limitUUid  

    uni.createBLEConnection({  
        deviceId: bluetoothId,  
        // timeout: 2000,  
        timeout: 3500,  
        success: (res) => {  
            if (needStop) {  
                uni.stopBluetoothDevicesDiscovery({  
                        success: (res) => {  
                            console.log('停止搜寻蓝牙', res);  
                        }  
                    }  
                );  
            }  
            if(connectSucCb){  
                console.log('蓝牙连接成功回调');  
                setTimeout(() => {  
                    connectSucCb()  
                }, 4000)  
            }  

            console.log('连接低功耗蓝牙成功', res);  
            // 设置蓝牙最大传输单元  
            // 如果设置超过了系统的最大值就返回错误码-1,显示 internal error 内部错误  
            // 但好像设置依旧有效,可能如果超过了系统的最大值,默认使用系统支持的最大值  
            if (this.platform === 'android') {  
                setTimeout(() => {  
                    uni.setBLEMTU({  
                        deviceId: bluetoothId,  
                        mtu: 185,  
                        success: (res1) => {  
                            console.log('设置蓝牙最大传输单元', res1);  
                            setTimeout(() => {  
                                this.getBLEDeviceServices(bluetoothId, notifyCb, readCb);  
                            }, 1500);  
                        },  
                        fail: (err) => {  
                            this.closeBLEConnection(closeCallback);  
                            console.log('设置蓝牙最大传输单元 失败', err);  
                        }  
                    });  
                }, 1000)  
            } else {  
                setTimeout(() => {  
                    this.getBLEDeviceServices(bluetoothId, notifyCb, readCb);  
                }, 1000)  
            }  

        },  
        fail: (err) => {  
            console.log('蓝牙连接失败');  
            if(connectFailCb){  
                console.log('蓝牙连接失败回调');  
                connectFailCb()  
            }  

            // TODO: 连接失败的处理  
            this.closeBLEConnection(closeCallback);  
        },  
        complete:()=>{  
            this.connecting = false;  
        }  
    })  
}  

onConnectionStateChange() {  
    console.log("设置状态改变回调")  
    uni.onBLEConnectionStateChange(({deviceId, connected}) => {  
        console.log(`device ${deviceId} state has changed, connected: ${connected}`)  
        this.connect = connected;  
        if (this.connectionStateChangeCb) {  
            this.connectionStateChangeCb(deviceId, connected)  
        }  

    });  
}  

closeBLEConnection(closeCallback) {  
    console.log("尝试断开")  
    uni.closeBLEConnection({  
        deviceId: this.bluetoothId,  
        success: (result) => {  
            console.log('断开成功', result);  
            // this.clearConnectInfo()  
            if(closeCallback){  
                closeCallback()  
            }  
        },  
        fail: (error) => {  
            console.log('断开失败', error, this.bluetoothId);  
        },  
        complete: () =>{  
            this.connecting = false  
            this.connect = false  
        }  
    });  
}  

getBLEDeviceServices(bluetoothId, notifyCb, readCb) {  
    uni.getBLEDeviceServices({  
        deviceId: bluetoothId,  
        success: (res) => {  
            console.log('获取蓝牙设备所有服务', res);  
            console.log('所有服务', res.services);  
            for (let i = 0; i < res.services.length; i++) {  
                if (res.services[i].uuid.indexOf(this.serviceUUid) > -1) {  
                    console.log('res.services[i].uuid', res.services[i].uuid);  
                    if (res.services[i].isPrimary) {  
                        // setTimeout(()=>{  
                        //     this.getBLEDeviceCharacteristics(bluetoothId, res.services[i].uuid, notifyCb, readCb);  
                        //     }  

                        // ,1000) }  

                                this.getBLEDeviceCharacteristics(bluetoothId, res.services[i].uuid, notifyCb, readCb);  
                    }  
                }  
            }  
        },  
        fail(error) {  
            console.log('获取蓝牙设备所有服务失败', error);  
            this.closeBLEConnection();  
        }  
    });  
}  

getBLEDeviceCharacteristics(deviceId, serviceId, notifyCb, readCb) {  
    var that = this;  
    uni.getBLEDeviceCharacteristics({  
        deviceId,  
        serviceId,  
        success: (res) => {  
            console.log('获取蓝牙设备某个服务中所有特征值 成功', res.characteristics);  
            for (let i = 0; i < res.characteristics.length; i++) {  
                let item = res.characteristics[i];  
                if (this.limitUUid) {  
                    if (item.uuid.indexOf(this.limitUUid) == -1) {  
                        return  
                    }  
                }  
                if (item.properties.read) {  
                    console.log('read', item.uuid);  
                    // 读取低功耗蓝牙设备的特征值的二进制数据值。注意:必须设备的特征值支持 read 才可以成功调用。  
                    uni.readBLECharacteristicValue({  
                        deviceId,  
                        serviceId,  
                        characteristicId: item.uuid,  
                        success(res) {  
                            console.log('开启读取特征值成功', res);  
                        },  
                        fail(err) {  
                            console.log('开启读取特征值失败', err);  
                        }  
                    });  
                }  
                if (item.properties.write) {  
                    this.serviceId = serviceId;  
                    this.characteristicId = item.uuid;  
                    console.log('write', item.uuid);  
                }  
                if (item.properties.notify || item.properties.indicate) {  
                    console.log('notify', item.uuid);  
                    // 启用低功耗蓝牙设备特征值变化时的 notify 功能,订阅特征值。  
                    // 注意:必须设备的特征值支持 notify 或者 indicate 才可以成功调用。  
                    // 另外,必须先启用 notifyBLECharacteristicValueChange 才能监听到设备 characteristicValueChange 事件  
                    // #ifdef MP  
                    that.onBLECharacteristicValueChange();  
                    //  #endif  
                    uni.notifyBLECharacteristicValueChange({  
                        deviceId,  
                        serviceId,  
                        characteristicId: item.uuid,  
                        state: true,  
                        success(res) {  
                            console.log('启用notify成功', res);  

                            // TODO: callback  
                            if (notifyCb) {  
                                console.log('notify回调');  
                                notifyCb(res);  
                            }  
                        }  
                    });  
                }  
            }  
        },  
        fail(err) {  
            console.error('获取蓝牙服务的特征值 失败', err);  
        }  
    });  
}  

onBLECharacteristicValueChange() {  

    // 判断是否有设备连接上  
    console.log('设置 读取数据回调');  
    // 操作之前先监听,保证第一时间获取数据  
    // 大概操作就是做了某段操作后把_currentState改为该阶段,然后在收到C ACK这些指令时都判断_currentState,同一阶段收到不同的指令做出不同动作  

    uni.onBLECharacteristicValueChange((characteristic) => {  
        // console.log('收到的消息', Date.now(), characteristic)  
        console.log("收到的值:", utils.ab2hex(characteristic.value));  
        if (this.readCb) {  
            console.log('收到消息回调');  
            this.readCb(characteristic)  
        }  
    });  

    //  
    // /*#ifdef APP-PLUS*/  
    //  
    // if (readCb) {  
    //     readCb()  
    // }  
    // /*#endif*/  
}  

writeBLEData(bluetoothId,buffer, successCb, failCb) {  
    // console.log("write buffer",buffer)  
    // console.log(this.serviceId)  
    // console.log(this.characteristicId)  
    // console.log(bluetoothId)  
    console.log("buffer", utils.ab2hex(buffer))  
    var that = this  
    /*#ifdef MP*/  
    uni.writeBLECharacteristicValue({  
        deviceId: bluetoothId,  
        serviceId: this.serviceId,  
        characteristicId: this.characteristicId,  
        value: buffer,  
        success(res) {  
            console.log("写入蓝牙数据成功")  
            if(successCb){  
                successCb(res)  
            }  
        },  
        fail(err) {  
            console.log("写入蓝牙数据失败", err)  
            // setTimeout(() => {  
            //     if (that.times != 0) return  
            //     that.times++  
            //     that.writeBLEData(bluetoothId, buffer, null, null)  
            // }, 2000)  
            if (failCb){  
                failCb(err)  
            }  
        }  
    });  
    /*#endif*/  

    /*#ifdef APP-PLUS*/  

    uni.writeBLECharacteristicValue({  
        deviceId: bluetoothId,  
        serviceId: this.serviceId,  
        characteristicId: this.characteristicId,  
        value: buffer,  
        success(res) {  
            console.log("写入蓝牙数据成功")  
            that.times = 0  
            if(successCb){  
                successCb(res)  
            }  
        },  
        fail(err) {  
            console.log("写入蓝牙数据失败", err)  
            setTimeout(() => {  
                if (that.times != 0) return  
                that.times++  
                that.writeBLEData(bluetoothId, buffer, null, null)  
            }, 2000)  
           if (failCb){  
               failCb(err)  
           }  
        }  
    });  
    /*#endif*/  

}  

async getBluetoothAdapterState() {  
    return new Promise((resolve, reject) => {  
        uni.getBluetoothAdapterState({  
            success(e) {  
                resolve(e)  
            },  
            fail(e) {  
                console.log("获取蓝牙适配器状态失败:",e)  
                reject(e)  
            }  
        })  
    })  
}  

}

const bluetooth = new Bluetooth();
export default bluetooth;

1***@qq.com

1***@qq.com

2024年了 还是没处理这个问题。只能说好优秀的团队

d***@anylink.io

d***@anylink.io

取消对蓝牙状态的监听一直没解决吗?我真服了uni这个团队。

  • 1***@qq.com

    没有, 目前还是得手动写 单例控制 =_=

    2024-04-07 10:12

l***@163.com

l***@163.com - 测试

谁成功解决的 ,可以分享下代码吗

1***@qq.com

1***@qq.com

参考各位达人,我的经验分享如下:
1、ESP32 作为BLE服务器,将BLE客户端发来数据返回,作为调试手机APP的工具

2、编写一个公共文件ble_api.js,实现蓝牙功能。编写一个类,类中存储BLE通信数据和方法,定义此类唯一一个实例,供网页.vue调用。

3、为了解决uniapp蓝牙无法注销回调函数,在ble_api.js就BLE uni.notify编写唯一一个回调函数,保证唯一回调函数(这里是在网页显示周期内)注册一次。否者会出现多次调用问题。

4、在回调函数中,使用uni.$emit公共函数,将BLE数据发送至具体网页.vue中。

5、经实验具体做法,在每个网页script内, onshow()中调用BLE类实例注册一次BLE uni.notify的回调函数。否者,要么BLE不接收数据,要么回调函数重复多次执行。 BLE uni.notify的回调函数中使用uni.$emit()转发BLE数据,在具体网页.vue的 onshow()使用uni.$on()监听接收与处理数据,在此具体网页.vue的onhide()中使用uni.$off()注销此监听。

代码可参考:https://www.cnblogs.com/excellentHellen/p/18279222

  • 1***@qq.com

    刚刚学用uniapp,供参考。

    2024-07-02 09:34

11233

11233

  • c***@qq.com

    你这个是微信小程序的

    2024-08-16 14:20

要回复问题请先登录注册