uni-app 小程序在iOS设备上能正常跟蓝牙设备交互数据 Android上开启蓝牙数据监听失败

uni-app 小程序在iOS设备上能正常跟蓝牙设备交互数据 Android上开启蓝牙数据监听失败

信息项 描述
产品分类 uni小程序SDK
手机系统 Android
手机系统版本 Android 9.0
手机机型 安卓设备
页面类型 vue
SDK版本号 SDK 3.2.3 V1 版本

示例代码:

========== 链接蓝牙页面代码----蓝牙模块开始================

// 初始化蓝牙  
InitBle() {  
    let _this = this  
    uni.openBluetoothAdapter({ //初始化蓝牙模块  
        success(res) {  
            console.log('初始化蓝牙', res);  
            // uni.showToast({  
            //  title: '初始化成功',  
            //  icon: 'success',  
            //  duration: 800  
            // })  
            // _this.SearchBle(); //2.0  
        },  
        fail(err) {  
            uni.showToast({  
                title: '请检查是否已开启蓝牙',  
                icon: 'none',  
                duration: 1500  
            })  
        }  
    })  
},  

// 搜索蓝牙  
SearchBle() {  
    let _this = this  
    _this.linkStatus = 1;  
    uni.startBluetoothDevicesDiscovery({  
        success(res) {  
            console.log('蓝牙开启搜索', res)  
            _this.Loading = true  
            _this.timer1 = setTimeout(() => { //加个延迟、目的是为了设备搜索完毕再获取列表,不然获取为空列表  
                _this.GetBleList() //3.0  
            }, 3000)  
        },  
        fail(res) {  
        _this.linkStatus = 0;  
            console.log("查找设备失败!");  
            uni.showToast({  
                icon: "none",  
                title: "查找设备失败!",  
                duration: 3000  
            })  
        }  
    })  
},  

// 搜索到的蓝牙列表  
GetBleList() {  
    var _this = this;  
    uni.getBluetoothDevices({  
        success: function(res) {  
            var bluetoothArr = res.devices.filter(function(obj) {  
                console.log("obj: ----- " + JSON.stringify(obj));  
                var uuids = obj.advertisServiceUUIDs;  
                var uuid = '';  
                if (Array.isArray(uuids)) {  
                    if (uuids.length > 0) {  
                        let str = uuids[0];  
                        if (str.length >= 8) {  
                            uuid = str.slice(4, 8);  
                            if (uuid == '6837') {  
                                _this.ConnectBle(obj.deviceId);  
                            }  
                        }  
                    }  
                }  
                return uuid == '6837';  
                // return obj.name != "未知设备" && obj.name == 'mycar_ble'; //这里过滤自己想要的设备  
            })  
            // console.log('蓝牙设备列表==2过滤后==', bluetoothArr)  
            _this.bluetoothList = bluetoothArr  
            // _this.bluetoothList = []  
        },  
        fail: function() {  
            _this.linkStatus = 0;  
            console.log("搜索蓝牙设备失败");  
            uni.showToast({  
                title: '搜索蓝牙设备失败或附件暂无开启的蓝牙设备',  
                icon: 'none',  
                duration: 2000  
            })  
        },  
        complete: function() {  
            console.log('搜索完成')  
            _this.Loading = false  
            _this.StopSearchBle()  
        }  
    })  
},  

// 蓝牙连接  根据某一id连接设备,4.0  
ConnectBle(deviceId) {  
    var _this = this;  
    uni.createBLEConnection({  
        deviceId: deviceId, //设备id  
        success: (res) => {  
            console.log('连接蓝牙成功==', res)  
            // _this.postDeviceInfo()   //提交蓝牙信息到后台  
            _this.deviceId = deviceId  
            _this.linkStatus = 2;  

            // 设置蓝牙最大传输单元。  
            // uni.setBLEMTU(22,512)  
            _this.NoticeConnection(); //连接成功后,开始监听异常  
            _this.timer2 = setTimeout(() => { //加个延迟、目的是为了确保连接成功后,再获取服务列表--可以显示正在连接效果  
                _this.Loading = false  
                _this.GetServiceId(deviceId); //5.0  
                uni.showToast({  
                    title: '连接成功',  
                    icon: 'success',  
                    duration: 800  
                })  
            }, 3000)  
        },  
        fail: function(err) {  
            _this.linkStatus = 0;  
            console.log('蓝牙连接失败err===', err)  
            if (err.errMsg == 'createBLEConnection:fail already connect') {  
                _this.Loading = false  
                _this.status_txt = '已有蓝牙连接'  
            } else {  
                _this.status_txt = err.errMsg  
            }  
        },  
        complete: function() {  
            console.log('蓝牙连接完成')  
        }  
    })  
},  

//获取蓝牙设备的服务uuid,5.0    //服务uuid可能有多个  
GetServiceId(deviceId) {  
    console.log('连接的蓝牙设备deviceId====', deviceId)  
    var _this = this  
    uni.getBLEDeviceServices({  
        deviceId,  
        success(res) {  
            console.log('获取蓝牙四个服务==', JSON.stringify(res.services))  
            _this.serviceid_list = res.services //蓝牙服务列表放在data里面只是备用  
            _this.serviceId = res.services[0].uuid //这是用来监听蓝牙下发和接收的服务uuid  
            _this.GetCharacteIdNotify(_this.serviceId,  
                deviceId) //6.0  获取第2个服务uuid的特征值 (关于获取第几个uuid服务,看蓝牙方面提供的协议  
        }  
    })  
},  

// 根据服务uuid获取蓝牙特征值,开始监听写入和接收  
GetCharacteIdNotify(serviceId, deviceId) {  
    console.log('serviceId:-----' + serviceId);  
    console.log('deviceId:-----' + deviceId);  
    let _this = this  
    uni.getBLEDeviceCharacteristics({  
        deviceId,  
        serviceId,  
        success(res) {  
            console.log('获取蓝牙特征值', res.characteristics)  
            _this.writeId = res.characteristics[0].uuid //写入id  
            _this.notifyId = res.characteristics[0].uuid //接收id  
            _this.startNoticeBle(_this.notifyId) //7.0,开始侦听数据  
        }  
    })  
},  

// 开启蓝牙数据监听  
startNoticeBle(notifyId) {  
    console.log('开启蓝牙数据监听', notifyId)  
    let _this = this  
    uni.notifyBLECharacteristicValueChange({  
        state: true, // 启用 notify 功能  
        deviceId: _this.deviceId,  
        serviceId: _this.serviceId,  
        characteristicId: notifyId,  
        success(res) {  
            console.log("监听成功===", res.errMsg, 'deviceId===', _this.deviceId)  
            _this.GetDataFromBle();  
        },  
        fail: function(err) {  
            console.log('开启监听失败', err)  
        }  
    })  
},  

// 设备返回的数据接收  
GetDataFromBle() {  
    var _this = this;  
    wx.onBLECharacteristicValueChange((res) => {  
        // 此时可以拿到蓝牙设备返回来的数据是一个ArrayBuffer类型数据,所以需要通过一个方法转换成字符串  
        // console.log('res:-----' + JSON.stringify(res.value)); // 0a010001060002daff000013  
        // console.log('返回的十六进制', _this.ab2hex(res.value));  
        _this.bleData = _this.ab2hex(res.value)  
        let data = _this.ab2hex(res.value)  
        console.log('data:-----' + data);  
        // 0a0100010600021dcf000000  
    })  
},  

// 向蓝牙写入数据  
BleWrite(instruction) {  
    // 向蓝牙设备发送一个0x00的16进制数据  
    let _this = this  
    let serviceId = _this.serviceId  
    let characteristicId = _this.writeId  
    let deviceId = _this.deviceId  
    const buffer = _this.hexStringToArrayBuffer(instruction);  
    // const dataView = new DataView(buffer)  
    // dataView.setUint8(0, 0)  
    uni.writeBLECharacteristicValue({  
        deviceId, // 蓝牙设备 deviceId  
        serviceId, // 蓝牙服务uuid,即第二个uuid  
        characteristicId, // 蓝牙特征值的 (即 writeId)  
        value: buffer, // 这里的value是ArrayBuffer类型  
        success(res) {  
            console.log('指令下发成功==', res.errMsg, res)  
        },  
        fail(err) {  
            console.log('写入数据失败', err)  
            uni.showToast({  
                icon: "none",  
                title: "请确保您的手机已连接设备",  
                duration: 3000  
            })  
        }  
    })  
},  

// 停止搜索蓝牙  
StopSearchBle() {  
    this.linkStatus = 0;  
    uni.stopBluetoothDevicesDiscovery({  
        success(res) {  
            console.log('停止搜索蓝牙', res)  
        }  
    })  
},  

// 重新搜索蓝牙  
ReSearchBle() {  
    console.log('重新扫描')  
    this.SearchBle()  
},  

// 关闭蓝牙模块  
CloseBle() {  
    this.linkStatus = 0;  
    uni.closeBluetoothAdapter({  
        success: function(res) {  
            console.log("断开蓝牙")  
        },  
        fail: function(err) {}  
    })  
},  

// 监听蓝牙连接状态  
NoticeConnection() {  
    var _this = this;  
    uni.onBLEConnectionStateChange((res) => {  
        console.log('开始监听蓝牙状态', res)  
        if (!res.connected) {  
            _this.linkStatus = 0;  
            console.log('连接已断开');  
            uni.showModal({  
                title: '提示',  
                content: '蓝牙已断开,请重新搜索重连!',  
                success(res) {}  
            })  
            // clearInterval(_this.data.timer)  
        }  
    })  
},  

/* ===========蓝牙模块结束================ */  

// 工具函数  
// ArrayBuffer转16进度字符串示例  
ab2hex(buffer) {  
    const hexArr = Array.prototype.map.call(  
        new Uint8Array(buffer),  
        function(bit) {  
            return ('00' + bit.toString(16)).slice(-2)  
        }  
    )  
    return hexArr.join('')  
},  

hexStringToArrayBuffer(str) {  
    if (!str) {  
        return new ArrayBuffer(0);  
    }  
    var buffer = new ArrayBuffer(str.length);  
    let dataView = new DataView(buffer)  
    let ind = 0;  
    for (var i = 0, len = str.length; i < len; i += 2) {  
        let code = parseInt(str.substr(i, 2), 16)  
        dataView.setUint8(ind, code)  
        ind++  
    }  
    return buffer;  
},  

==========蓝牙模块结束================


更多关于uni-app 小程序在iOS设备上能正常跟蓝牙设备交互数据 Android上开启蓝牙数据监听失败的实战教程也可以访问 https://www.itying.com/category-93-b0.html

2 回复

更多关于uni-app 小程序在iOS设备上能正常跟蓝牙设备交互数据 Android上开启蓝牙数据监听失败的实战教程也可以访问 https://www.itying.com/category-93-b0.html


根据你提供的代码和问题描述,在iOS上正常但在Android上开启蓝牙数据监听失败,主要问题可能出在以下几个方面:

1. Android权限问题

Android 6.0+需要动态申请位置权限才能正常使用蓝牙:

// 在初始化蓝牙前添加权限检查
uni.getLocation({
  type: 'wgs84',
  success: function () {
    console.log('位置权限已授权')
    _this.InitBle()
  },
  fail: function () {
    uni.showModal({
      title: '提示',
      content: '需要位置权限才能使用蓝牙功能',
      success: function (res) {
        if (res.confirm) {
          uni.openSetting()
        }
      }
    })
  }
})

2. 特征值选择问题

你的代码中writeIdnotifyId使用了同一个特征值:

_this.writeId = res.characteristics[0].uuid //写入id
_this.notifyId = res.characteristics[0].uuid //接收id

这可能导致Android设备无法正确识别特征值属性。需要根据特征值的properties属性区分:

res.characteristics.forEach(char => {
  if (char.properties.write) {
    _this.writeId = char.uuid
  }
  if (char.properties.notify || char.properties.indicate) {
    _this.notifyId = char.uuid
  }
})

3. Android API兼容性问题

GetDataFromBle()方法中,你使用了wx.onBLECharacteristicValueChange,这是微信小程序的API,在uni-app中应该使用:

uni.onBLECharacteristicValueChange((res) => {
  // 处理数据
})

4. 时序问题

Android设备对蓝牙操作时序要求更严格,建议在连接成功后增加延迟:

// 在ConnectBle成功后
setTimeout(() => {
  _this.GetServiceId(deviceId)
}, 1000) // 适当延长延迟时间

5. 调试建议

在Android上添加更详细的错误日志:

uni.notifyBLECharacteristicValueChange({
  state: true,
  deviceId: _this.deviceId,
  serviceId: _this.serviceId,
  characteristicId: notifyId,
  success(res) {
    console.log("监听成功", res)
  },
  fail: function(err) {
    console.log('开启监听失败详细:', 
      'errCode:', err.errCode,
      'errMsg:', err.errMsg,
      'deviceId:', _this.deviceId,
      'serviceId:', _this.serviceId,
      'characteristicId:', notifyId
    )
  }
})

6. Android特定处理

某些Android设备需要在连接后先读取一次特征值才能开启监听:

// 在开启监听前先读取一次
uni.readBLECharacteristicValue({
  deviceId: _this.deviceId,
  serviceId: _this.serviceId,
  characteristicId: notifyId,
  success() {
    // 然后再开启监听
    _this.startNoticeBle(notifyId)
  }
})
回到顶部