更新记录
1.0.1(2026-04-29)
- 适配uniappx项目
- 新增uniappx示例代码
1.0.0(2026-04-29)
- 新版发布
平台兼容性
uni-app(4.87)
| Vue2 | Vue3 | Chrome | Safari | app-vue | app-nvue | Android | iOS | 鸿蒙 |
|---|---|---|---|---|---|---|---|---|
| √ | √ | × | × | √ | √ | √ | √ | √ |
| 微信小程序 | 支付宝小程序 | 抖音小程序 | 百度小程序 | 快手小程序 | 京东小程序 | 鸿蒙元服务 | QQ小程序 | 飞书小程序 | 小红书小程序 | 快应用-华为 | 快应用-联盟 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| × | × | × | × | × | × | × | × | × | × | × | × |
uni-app x(4.87)
| Chrome | Safari | Android | iOS | 鸿蒙 | 微信小程序 |
|---|---|---|---|---|---|
| × | × | √ | √ | √ | × |
特别提醒
- 购买本插件前,请先试用,请先试用,请先试用,确认满足需求之后再行购买。虚拟物品一旦购买之后无法退款。
- 如有使用上的疑问、bug,可以进交流群联系作者;
- 请在合法范围内使用,若使用本插件做非法开发,本方概不负责;
- iOS使用示例demo测试时,要先修改manifest中项目名称后再打包(名称长度尽量短一点),不然会因为名称过长,导致App启动不了。
- uniapp-x项目调用api需要加上 as 类型转换
yt-ble(跨端 UTS BLE 插件)
yt-ble 是一个基于 UTS 的低功耗蓝牙插件,支持 App 端:
- Android
- iOS
- HarmonyOS
支持能力:
- 蓝牙初始化
- 扫描设备(名称/服务过滤)
- 连接与断开
- 获取服务和特征
- 读特征
- 订阅通知(notify)
- 写特征(字节/字符串、UTF-8/GBK/HEX)
- 获取/设置 MTU(iOS/Harmony 根据平台能力做兼容处理)
1. 安装与引入
导入插件后,确认项目中存在目录:uni_modules/yt-ble。
在页面或业务模块中引入:
import * as BleManager from '@/uni_modules/yt-ble'
// 或相对路径:import * as BleManager from '../../uni_modules/yt-ble'
2. 推荐调用流程
initBLE()startScan(...)- 选择目标设备后
connectDevice(...) getDeviceServices(...)- 根据服务/特征调用
notify(...)/read(...)/writeData(...) - 结束时
disconnect(),必要时stopScan()
3. API 说明
initBLE(): void
初始化 BLE 管理器。建议在页面初始化时调用一次。
startScan(options: ScanPara): void
开始扫描。
ScanPara:
scantime: number扫描时长(毫秒)showEmptyName: boolean是否返回空名称设备btNameFilter?: string名称包含过滤fliterNames?: string[]名称白名单(包含任一关键字即通过)serviceUuids?: string[]服务 UUID 过滤onScanResult(res: ApiResult)扫描数据/错误回调scanComplate?()扫描结束回调
stopScan(): void
停止扫描。
connectDevice(connectPara: ConnectPara): void
连接设备。
ConnectPara:
deviceId: stringonConnectResult(res: ConnectResult)
ConnectResult.type 约定:
"0"连接成功"2"连接断开- 其它值:错误码
disconnect(): void
断开当前连接设备。
getDeviceServices(servicesPara: ServicesPara): void
获取设备服务与特征。
ServicesResult.data 为 BleServices[],其中每个特征包含属性:
readwritewriteNoResponsenotify
read(readDataPara: ReadDataPara): void
读取特征值。
成功回调 onReadDataResult:
data?: number[]hexValue?: stringutf8Value?: stringgbkValue?: string
notify(notifiDataPara: NotifiDataPara): void
订阅/取消订阅通知。
isNotifyEnabled: true开启isNotifyEnabled: false关闭
通知数据通过 onNotifyDataResult 返回,数据结构同 read。
writeData(writeDataPara: WriteDataPara): void
写入特征值。
支持两种写法:
1) 字节数组写入:data: number[]
2) 文本写入:text: string + encoding
encoding:
0:UTF-81:GBK/GB180302:HEX(支持空格、换行、0x前缀)
writeType:
0:默认写入(有响应)1:无响应写入
setMtu(setMtuPara: SETMtuPara): void
设置 MTU(不同平台能力有差异,iOS/Harmony 按平台能力兼容返回)。
getMtu(getMtuPara: GETMtuPara): void
获取当前 MTU(各平台按实现返回当前值或兼容值)。
4. 主要类型(节选)
以 utssdk/interface.uts 为准,核心类型如下:
ApiResult:{ type, msg?, data? }BleDevice:{ deviceId, name?, localName?, RSSI? ... }BleServices:{ uuid, characteristics? }ReadNotifyData:{ data?, hexValue?, utf8Value?, gbkValue? }
5. 常见错误码
不同平台可能略有差异,常见值如下:
10000参数错误 / deviceId 非法 / 连接异常10001已断开10002蓝牙不可用或扫描失败10006未连接10008写入目标特征不存在或写失败10009读取目标特征不存在或读失败10010写入中 / MTU 不支持(平台差异)10012HEX 字符串非法
6. 使用建议
- 扫描前先
initBLE(),并确保系统蓝牙已开启。 - 连接成功后先
getDeviceServices(),再进行read/write/notify。 - 写入二进制协议建议优先使用
text + encoding:2(HEX)或直接data:number[]。 - iOS 的
deviceId是 UUID 字符串;Android 常见为 MAC 字符串。 - 退出页面时建议调用
stopScan()、disconnect()做资源释放。
7. uniapp示例
<template>
<view class="content">
<view class="item">
<view style="display: flex;flex-direction: row;align-items: center;margin-top: 15rpx;">
<text class="read_title">当前连接设备:</text>
<text class="read_title">{{currentDeviceName}}</text>
</view>
<view style="display: flex;flex-direction: row;width: 750rpx;margin-top: 35rpx;align-items: center;">
<view class="brn" @click="startScan">开始扫描</view>
<view class="brn" @click="disconnect">断开连接</view>
<view class="brn" @click="stopScan">停止扫描</view>
<view class="brn" @click="getServices">获取蓝牙服务</view>
</view>
</view>
<view class="item_data">
<text style="font-size: 32rpx;color: black;">数据读写</text>
<view style="display: flex;flex-direction: row;align-items: center;margin-top: 15rpx;">
<text class="read_title">读取到的数据:</text>
<text class="read_title">{{readData}}</text>
</view>
<view style="display: flex;flex-direction: row;width: 750rpx;margin-top: 15rpx;align-items: center;">
<view class="brn" style="width: 150rpx;" @click="readAction"><text>读取数据</text></view>
<view class="brn" style="width: 150rpx;" @click="writeData"><text>写入数据</text></view>
<view class="brn" style="width: 150rpx;" @click="getMTU"><text>获取MTU</text></view>
<view class="brn" style="width: 150rpx;" @click="configMTU"><text>设置MTU</text></view>
</view>
<view style="display: flex;flex-direction: row;width: 750rpx;margin-top: 35rpx;align-items: center;">
<view class="brn" style="width: 180rpx;" @click="notify"><text>监听notify</text></view>
</view>
<view style="display: flex;flex-direction: row;align-items: center;margin-top: 15rpx;margin-bottom: 20rpx;">
<text class="read_title">notify数据:</text>
<text class="read_title">{{notifyData}}</text>
</view>
</view>
<scroll-view
style="width: 750rpx;height: 700rpx;background-color: antiquewhite;margin-top: 20rpx;padding: 0 20rpx;box-sizing: border-box;"
scroll-y>
<view class="device_view" v-for="(item,index) in devices" @click="connectDevice(item)">
<view class="item_row">
<text class="title">名称:</text>
<text class="value">{{item.name}}</text>
</view>
<view class="item_row">
<text class="title">deviceId:</text>
<text class="value">{{item.deviceId}}</text>
</view>
<view class="item_row">
<text class="title">RSSI:</text>
<text class="value">{{item.RSSI}}</text>
</view>
</view>
</scroll-view>
</view>
</template>
<script>
import * as BleManager from '../../uni_modules/yt-ble'
export default {
data() {
return {
devices: [],
currentDeviceID: '',
currentDeviceName: '无',
readData: '无', //读取到的数据
notifyData: '无', //notify数据
isNotifyEnabled: false //notify状态
}
},
onLoad() {
BleManager.initBLE();
},
methods: {
startScan() {
this.devices = [];
BleManager.startScan({
scantime: 10000,
showEmptyName: false,
onScanResult: (res) => {
if (res['type'] == "0") {
this.devices.push(res["data"]);
}
},
scanComplate: () => {
console.log('扫描完成');
}
});
},
//停止扫描
stopScan() {
BleManager.stopScan();
},
//连接设备
connectDevice(item) {
let deviceId = item["deviceId"] + ""
BleManager.connectDevice({
deviceId: deviceId,
onConnectResult: (res) => {
let type = res["type"];
if (type == "0") {
this.currentDeviceID = res.deviceId + '';
this.currentDeviceName = item.name + '';
}
console.log(res["msg"])
}
});
},
//断开连接
disconnect() {
BleManager.disconnect(this.currentDeviceID);
},
//获取所有服务
getServices() {
console.log(this.currentDeviceID);
BleManager.getDeviceServices({
deviceId: this.currentDeviceID,
onServicesResult: (res) => {
if (res.type == "0") {
console.log(res.data)
}
uni.showToast({
icon: 'none',
title: res.msg,
duration: 2000
})
}
})
},
readAction() {
//通过getDeviceServices获取
let serviceId = '00001800-0000-1000-8000-00805F9B34FB';
let characteristicId = '00002A00-0000-1000-8000-00805F9B34FB';
// if (plus.os.name == 'iOS') {
// serviceId = "180A";
// characteristicId = "2A29";
// }
BleManager.read({
deviceId: this.currentDeviceID,
serviceId: serviceId,
characteristicId: characteristicId,
onReadDataResult: (res) => {
let value = res.data; //字节数组--原始数据
let gbkValue = res.gbkValue;
let utf8Value = res.utf8Value;
this.readData = res.utf8Value; //16进制HEX格式
},
onError: (err) => {
console.log(`Read数据出错:${err}`)
}
})
},
//notify
notify() {
this.isNotifyEnabled = !this.isNotifyEnabled;
//通过getDeviceServices获取
let serviceId = '0000FFB0-0000-1000-8000-00805F9B34FB';
let characteristicId = '0000FFB2-0000-1000-8000-00805F9B34FB';
BleManager.notify({
deviceId: this.currentDeviceID,
serviceId: serviceId,
characteristicId: characteristicId,
isNotifyEnabled: this.isNotifyEnabled,
onNotifyDataResult: (res) => {
let value = res.data; //字节数组--原始数据
this.notifyData = res.hexValue; //16进制HEX格式
},
onNotifyStatu: (res) => {
console.log(res ? 'Notify监听打开' : 'Notify监听关闭')
}
})
},
///写入数据
writeData() {
//通过getDeviceServices获取
let serviceId = '00001800-0000-1000-8000-00805F9B34FB';
let characteristicId = '00002A00-0000-1000-8000-00805F9B34FB';
// if (plus.os.name == 'iOS') {
// serviceId = "FFB0";
// characteristicId = "FFB1";
// }
BleManager.writeData({
deviceId: this.currentDeviceID,
serviceId: serviceId,
characteristicId: characteristicId,
text: 'Hello Digtal Scale',
encoding: 1,
onWriteOk: (deviceId) => {
console.log(`${deviceId}写入成功`)
},
onError: (err) => {
console.log(err);
}
})
},
//获取mtu
getMTU() {
BleManager.getMtu({
deviceId: this.currentDeviceID,
onGetMtuResult: (res) => {
let mtu = res.mtu;
let deviceId = res.deviceId;
uni.showToast({
icon: 'none',
title: `当前设备MTU:${mtu}`
})
}
})
},
//设置mtu
configMTU() {
BleManager.setMtu({
deviceId: this.currentDeviceID,
mtu: 25,
onSetMtuResult: (res) => {
let mtu = res.mtu;
let deviceId = res.deviceId;
let success = res.success;
uni.showToast({
icon: 'none',
title: success ? '设置成功' : '设置失败'
})
}
})
}
}
}
</script>
<style>
.content {
width: 750rpx;
display: flex;
flex-direction: column;
height: 100%;
background-color: whitesmoke;
}
.item {
display: flex;
flex-direction: column;
width: 750rpx;
padding: 20rpx;
box-sizing: border-box;
background-color: aquamarine;
}
.brn {
background-color: cadetblue;
height: 70rpx;
padding: 0 10rpx;
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: center;
margin-left: 20rpx;
border-radius: 8rpx;
}
.device_view {
display: flex;
width: 100%;
padding: 10rpx 10rpx;
box-sizing: border-box;
display: flex;
flex-direction: column;
margin-bottom: 10rpx;
background-color: aquamarine;
border-radius: 8rpx;
}
.item_row {
display: flex;
flex-direction: row;
align-items: center;
padding: 0 20rpx;
box-sizing: border-box;
}
.title {
font-size: 32rpx;
color: #333;
font-weight: bold;
}
.value {
font-size: 32rpx;
color: brown;
font-weight: bold;
}
.item_data {
display: flex;
width: 750rpx;
background-color: burlywood;
margin-top: 20rpx;
padding: 10rpx 20rpx;
box-sizing: border-box;
flex-direction: column;
}
.read_title {
font-size: 30rpx;
color: aliceblue;
}
</style>
8. Uniapp-x示例demo
<template>
<view class="content">
<view class="item">
<view style="display: flex;flex-direction: row;align-items: center;margin-top: 15rpx;">
<text class="read_title">当前连接设备:</text>
<text class="read_title">{{currentDeviceName}}</text>
</view>
<view style="display: flex;flex-direction: row;width: 750rpx;margin-top: 35rpx;align-items: center;">
<view class="brn" @click="startScan">开始扫描</view>
<view class="brn" @click="disconnect">断开连接</view>
<view class="brn" @click="stopScan">停止扫描</view>
<view class="brn" @click="getServices">获取蓝牙服务</view>
</view>
</view>
<view class="item_data">
<text style="font-size: 32rpx;color: black;">数据读写</text>
<view style="display: flex;flex-direction: row;align-items: center;margin-top: 15rpx;">
<text class="read_title">读取到的数据:</text>
<text class="read_title">{{readData}}</text>
</view>
<view style="display: flex;flex-direction: row;width: 750rpx;margin-top: 15rpx;align-items: center;">
<view class="brn" style="width: 150rpx;" @click="readAction"><text>读取数据</text></view>
<view class="brn" style="width: 150rpx;" @click="writeData"><text>写入数据</text></view>
<view class="brn" style="width: 150rpx;" @click="getMTU"><text>获取MTU</text></view>
<view class="brn" style="width: 150rpx;" @click="configMTU"><text>设置MTU</text></view>
</view>
<view style="display: flex;flex-direction: row;width: 750rpx;margin-top: 35rpx;align-items: center;">
<view class="brn" style="width: 180rpx;" @click="notify"><text>监听notify</text></view>
</view>
<view style="display: flex;flex-direction: row;align-items: center;margin-top: 15rpx;margin-bottom: 20rpx;">
<text class="read_title">notify数据:</text>
<text class="read_title">{{notifyData}}</text>
</view>
</view>
<scroll-view
style="width: 750rpx;height: 700rpx;background-color: antiquewhite;margin-top: 20rpx;padding: 0 20rpx;box-sizing: border-box;"
scroll-y>
<view class="device_view" v-for="(item,index) in devices" @click="connectDevice(item)">
<view class="item_row">
<text class="title">名称:</text>
<text class="value">{{item.name}}</text>
</view>
<view class="item_row">
<text class="title">deviceId:</text>
<text class="value">{{item.deviceId}}</text>
</view>
<view class="item_row">
<text class="title">RSSI:</text>
<text class="value">{{item.RSSI}}</text>
</view>
</view>
</scroll-view>
</view>
</template>
<script>
import * as BleManager from '../../uni_modules/yt-ble'
export default {
data() {
return {
devices: [] as BleManager.BleDevice[],
currentDeviceID: '',
currentDeviceName: '无',
readData: '无', //读取到的数据
notifyData: '无', //notify数据
isNotifyEnabled: false //notify状态
}
},
onLoad() {
BleManager.initBLE();
},
methods: {
startScan() {
this.devices = [];
BleManager.startScan({
scantime: 10000,
showEmptyName: false,
onScanResult: (res) => {
let result = res as BleManager.ApiResult;
if (result.type == "0" && result.data != null) {
this.devices.push(result.data as BleManager.BleDevice);
}
},
scanComplate: () => {
console.log('扫描完成');
}
} as BleManager.ScanPara);
},
//停止扫描
stopScan() {
BleManager.stopScan();
},
//连接设备
connectDevice(item : BleManager.BleDevice) {
let deviceId = item.deviceId
BleManager.connectDevice({
deviceId: deviceId,
onConnectResult: (res : BleManager.ConnectResult) => {
let type = res.type;
if (type == "0") {
this.currentDeviceID = res.deviceId + '';
this.currentDeviceName = item.name + '';
}
console.log(res.msg)
}
} as BleManager.ConnectPara);
},
//断开连接
disconnect() {
BleManager.disconnect(this.currentDeviceID);
},
//获取所有服务
getServices() {
BleManager.getDeviceServices({
deviceId: this.currentDeviceID,
onServicesResult: (res : BleManager.ServicesResult) => {
if (res.type == "0") {
console.log(res.data)
}
uni.showToast({
icon: 'none',
title: res.msg,
duration: 2000
})
}
} as BleManager.ServicesPara)
},
readAction() {
//通过getDeviceServices获取
let serviceId = '00001800-0000-1000-8000-00805F9B34FB';
let characteristicId = '00002A00-0000-1000-8000-00805F9B34FB';
// if (plus.os.name == 'iOS') {
// serviceId = "180A";
// characteristicId = "2A29";
// }
BleManager.read({
deviceId: this.currentDeviceID,
serviceId: serviceId,
characteristicId: characteristicId,
onReadDataResult: (res : BleManager.ReadNotifyData) => {
let value = res.data; //字节数组--原始数据
let gbkValue = res.gbkValue;
let utf8Value = res.utf8Value;
this.readData = res.utf8Value + ''; //16进制HEX格式
},
onError: (err) => {
console.log(`Read数据出错:${err}`)
}
} as BleManager.ReadDataPara)
},
//notify
notify() {
this.isNotifyEnabled = !this.isNotifyEnabled;
//通过getDeviceServices获取
let serviceId = '0000FFB0-0000-1000-8000-00805F9B34FB';
let characteristicId = '0000FFB2-0000-1000-8000-00805F9B34FB';
BleManager.notify({
deviceId: this.currentDeviceID,
serviceId: serviceId,
characteristicId: characteristicId,
isNotifyEnabled: this.isNotifyEnabled,
onNotifyDataResult: (res : BleManager.ReadNotifyData) => {
let value = res.data; //字节数组--原始数据
this.notifyData = res.hexValue + ''; //16进制HEX格式
},
onNotifyStatu: (res) => {
console.log(res ? 'Notify监听打开' : 'Notify监听关闭')
}
} as BleManager.NotifiDataPara)
},
///写入数据
writeData() {
//通过getDeviceServices获取
let serviceId = '00001800-0000-1000-8000-00805F9B34FB';
let characteristicId = '00002A00-0000-1000-8000-00805F9B34FB';
// if (plus.os.name == 'iOS') {
// serviceId = "FFB0";
// characteristicId = "FFB1";
// }
BleManager.writeData({
deviceId: this.currentDeviceID,
serviceId: serviceId,
characteristicId: characteristicId,
text: 'Hello Digtal Scale',
encoding: 1,
onWriteOk: (deviceId) => {
console.log(`${deviceId}写入成功`)
},
onError: (err) => {
console.log(err);
}
} as BleManager.WriteDataPara)
},
//获取mtu
getMTU() {
BleManager.getMtu({
deviceId: this.currentDeviceID,
onGetMtuResult: (res : BleManager.MtuResult) => {
let mtu = res.mtu;
let deviceId = res.deviceId;
uni.showToast({
icon: 'none',
title: `当前设备MTU:${mtu}`
})
}
} as BleManager.GETMtuPara)
},
//设置mtu
configMTU() {
BleManager.setMtu({
deviceId: this.currentDeviceID,
mtu: 25,
onSetMtuResult: (res : BleManager.MtuResult) => {
let mtu = res.mtu;
let deviceId = res.deviceId;
let success = res.success;
uni.showToast({
icon: 'none',
title: success ? '设置成功' : '设置失败'
})
}
} as BleManager.SETMtuPara)
}
}
}
</script>
<style>
.content {
width: 750rpx;
display: flex;
flex-direction: column;
height: 100%;
background-color: whitesmoke;
}
.item {
display: flex;
flex-direction: column;
width: 750rpx;
padding: 20rpx;
box-sizing: border-box;
background-color: aquamarine;
}
.brn {
background-color: cadetblue;
height: 70rpx;
padding: 0 10rpx;
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: center;
margin-left: 20rpx;
border-radius: 8rpx;
}
.device_view {
display: flex;
width: 100%;
padding: 10rpx 10rpx;
box-sizing: border-box;
display: flex;
flex-direction: column;
margin-bottom: 10rpx;
background-color: aquamarine;
border-radius: 8rpx;
}
.item_row {
display: flex;
flex-direction: row;
align-items: center;
padding: 0 20rpx;
box-sizing: border-box;
}
.title {
font-size: 32rpx;
color: #333;
font-weight: bold;
}
.value {
font-size: 32rpx;
color: brown;
font-weight: bold;
}
.item_data {
display: flex;
width: 750rpx;
background-color: burlywood;
margin-top: 20rpx;
padding: 10rpx 20rpx;
box-sizing: border-box;
flex-direction: column;
}
.read_title {
font-size: 30rpx;
color: aliceblue;
}
</style>
9. 更多好用实惠插件
- 高德定位连续定位后台定位保活定位
- 百度汽车摩托车导航插件
- 百度鹰眼轨迹插件支持后台采集、保活
- 百度定位插件、连续定位、保活、坐标系转换、支持双端
- 计步器插件,支持Android、iOS双端
- uts经典蓝牙插件、蓝牙电子秤
- 获取唯一标识、ServiceID、卸载更新不变iOS+Android
- Android经典蓝牙
- 华为ScanKit统一扫码插件支持iOS+Android原生插件
- 【华为扫码】统一扫码插件支持多码连续扫码支持半屏扫码uts插件iOS+Android+HarmonyOS
- 截屏、录屏、防截屏、录屏iOS、Android
- 人脸采集插件 最新百度SDK 离线人脸采集、活体检测
- 页面截长图、截取WebView内容,生成长截图Android+iOS
- 百度OCR识别插件
- Android无预览拍照、录制、静默拍照、静默录制、抓拍插件支持
- uni高德地图功能拓展地图截图
- 科大讯飞离线合成插件支持iOS、android
- iOS保活Android保活鸿蒙保活定位插件系统定位
- 高德定位、猎鹰轨迹插件
- 海康威视综合安防平台视频播放插件

收藏人数:
购买源码授权版(
试用
赞赏(1)
下载 335
赞赏 8
下载 11753154
赞赏 1911
赞赏
京公网安备:11010802035340号