更新记录
1.0.7(2026-08-14)
数据接收回调改为必填参数,确保 UTS 持续回调不会在首次调用后被释放。
1.0.6(2026-08-13)
优化服务端消息接收
1.0.5(2026-08-11)
服务端 API 改为静态调用,关闭服务时释放监听 socket 与全部客户端连接,修复重启服务后设备无法正常收发消息的问题。
查看更多平台兼容性
uni-app(4.61)
| Vue2 | Vue3 | Chrome | Safari | app-vue | app-nvue | Android | iOS | 鸿蒙 |
|---|---|---|---|---|---|---|---|---|
| √ | √ | - | - | √ | √ | 5.0 | - | √ |
| 微信小程序 | 支付宝小程序 | 抖音小程序 | 百度小程序 | 快手小程序 | 京东小程序 | 鸿蒙元服务 | QQ小程序 | 飞书小程序 | 小红书小程序 | 快应用-华为 | 快应用-联盟 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| - | - | - | - | - | - | - | - | - | - | - | - |
uni-app x(4.56)
| Chrome | Safari | Android | iOS | 鸿蒙 | 微信小程序 |
|---|---|---|---|---|---|
| - | - | 5.0 | - | √ | - |
其他
| 多语言 | 暗黑模式 | 宽屏模式 |
|---|---|---|
| √ | √ | √ |
xtf-sppbt
经典蓝牙 SPP(Serial Port Profile)UTS 插件,提供客户端扫描、配对、连接、收发数据,以及 SPP 服务端监听和多连接收发能力。
平台支持
| 平台 | uni-app | uni-app x | 说明 |
|---|---|---|---|
| Android App | 支持 | 支持 | Android 5.0(API 21)及以上 |
| HarmonyOS App | 支持 | 支持 | 使用系统 SPP RFCOMM 能力 |
| iOS App | 不支持 | 不支持 | iOS 不开放通用经典蓝牙 SPP;相关异步 API 返回 9010001 |
| Web、小程序 | 不支持 | 不支持 | 浏览器和小程序不提供通用 SPP 能力 |
插件使用原生蓝牙能力。首次集成或修改插件源码后,需要重新制作并安装自定义调试基座,普通热更新不会替换基座中的原生插件。
引入
import {
BtClient,
BtServer,
openBtBluetooth,
isEnabled,
setConnectUUID,
string2ByteStrWithCharset,
byte2StringWithCharset,
MyApiResult,
DeviceData,
ServerReadData,
ConnectPara
} from '@/uni_modules/xtf-sppbt'
在 uni-app JavaScript 页面中不需要引入 MyApiResult、DeviceData、ServerReadData 和 ConnectPara 等 UTS 类型。
数据约定
插件的读写数据均为十六进制字符串,而不是普通文本。
client.write('5566778899')
- 建议只传入
0-9、A-F组成的偶数长度字符串,不要带0x前缀。 - 收到的数据通过
res.data返回。Android 端可能返回55 66 77 88 99,HarmonyOS 端通常返回5566778899;跨平台解析前建议统一去除空格、换行等空白字符。 - 文本数据可先使用
string2ByteStrWithCharset()转为十六进制,收到后再用byte2StringWithCharset()解码。 - 一次回调对应一次底层读取,不代表一条完整业务消息。存在拆包或粘包要求时,应由业务层按长度、分隔符或协议帧自行组包。
返回结构
所有异步回调统一返回 MyApiResult:
export type MyApiResult = {
type: number
message: string
data: any
}
常用 type 值如下。具体含义需要结合调用的 API 判断。
| type | 含义 |
|---|---|
-1 |
用户未授予蓝牙权限 |
0 |
操作成功、扫描到设备或读取到客户端数据 |
1 |
开启蓝牙失败或用户取消开启 |
10000 |
客户端读取已启动,或服务端有设备连接成功 |
10001 |
操作失败、连接失败、读取异常或服务端设备断开 |
10002 |
服务端已启动,或服务端收到设备数据 |
9010001 |
当前平台不支持经典蓝牙 SPP(iOS) |
设备结构:
export type DeviceData = {
mac?: string
alias?: string
name?: string
bondState?: number
}
服务端收包结构:
export type ServerReadData = {
mac: string
data?: string
name?: string
}
ServerReadData.mac 是插件内部的连接标识。Android 上通常为设备 MAC 地址;HarmonyOS 上为 socket:<id>。调用 BtServer.write() 或 BtServer.closeSocket() 时,必须原样使用回调返回的该值。
基础 API
判断蓝牙状态
const enabled = isEnabled()
返回 true 表示系统蓝牙已开启。该方法不申请权限。
请求权限并开启蓝牙
openBtBluetooth((res: MyApiResult) => {
if (res.type == 0) {
console.log('蓝牙已开启')
} else {
console.log(res.message)
}
})
Android 会请求运行时权限,并在蓝牙关闭时显示系统开启确认界面;HarmonyOS 会请求蓝牙权限并尝试开启蓝牙。
设置 SPP UUID
默认使用标准 SPP UUID:
00001101-0000-1000-8000-00805F9B34FB
如服务端使用自定义 UUID,请在扫描、连接或启动服务端之前设置:
setConnectUUID('00001101-0000-1000-8000-00805F9B34FB')
客户端和服务端必须使用相同 UUID。
文本与十六进制互转
const hex = string2ByteStrWithCharset('您好 经典蓝牙', 'gbk')
// C4FABAC320BEADB5E4C0B6D1C0
const text = byte2StringWithCharset(hex, 'gbk')
// 您好 经典蓝牙
code 为字符集名称,例如 utf-8、gbk、iso-8859-1。字符集不受系统支持或转换失败时返回空字符串。
客户端
每个 BtClient 实例维护一个 SPP 连接:
const client = new BtClient()
扫描设备
client.onStartScanDevice((res: MyApiResult) => {
if (res.type == 0) {
const device = res.data as DeviceData
console.log(device.name, device.mac, device.bondState)
} else {
console.log(res.message)
}
})
每发现一个设备会回调一次。扫描结束或离开页面时应停止扫描:
client.stopScan()
连接前也建议先停止扫描,避免扫描影响连接速度和稳定性。
查询和发起配对
const result = client.getBondDevices()
const devices = result.data as DeviceData[]
const state = client.bondState('41:42:8D:29:21:47')
client.bond('41:42:8D:29:21:47', (res: MyApiResult) => {
console.log(res.message, res.data)
})
bond() 的回调表示配对流程或配对状态发生变化,最终结果仍可能需要用户在系统配对界面确认。bondState 使用各平台系统蓝牙 API 的原始状态值。
连接并自动接收数据
注意:公开 API 名为 onConnnect,其中包含三个字母 n,调用时必须保持该拼写。
client.stopScan()
client.onConnnect({
mac: '41:42:8D:29:21:47',
connectCallback: (res: MyApiResult) => {
if (res.type == 0) {
console.log('连接成功')
} else {
console.log('连接失败:' + res.message)
}
},
dataCallback: (res: MyApiResult) => {
if (res.type == 0) {
console.log('收到十六进制数据:' + (res.data as string))
} else if (res.type == 10001) {
console.log('连接已断开或读取异常')
}
}
} as ConnectPara)
传入 dataCallback 后,连接成功会自动调用 onStartAutoReadData()。其首次回调 type == 10000 仅表示读取已启动,不是设备数据。
如果连接时没有传 dataCallback,可在连接成功后手动开启读取:
client.onStartAutoReadData((res: MyApiResult) => {
console.log(res)
})
发送、查询状态和断开
client.write('5566778899')
const connected = client.isBtConnect()
client.stopAutoRead()
client.close()
write() 只接收十六进制字符串。页面卸载或不再使用连接时应调用 close() 释放 socket 和读写资源。
服务端
BtServer 的所有方法均为静态方法,无需创建实例。建议先注册事件,再启动服务端。
完整示例
BtServer.onSppServerEvent((res: MyApiResult) => {
if (res.type == 10000) {
const device = res.data as DeviceData
console.log('设备已连接:' + device.mac)
} else if (res.type == 10001) {
const device = res.data as DeviceData
console.log('设备已断开:' + device.mac)
} else if (res.type == 10002) {
const packet = res.data as ServerReadData
console.log('收到数据:' + packet.data)
// 使用事件返回的连接标识回复当前设备。
BtServer.write(packet.mac, '5566778899')
}
})
BtServer.startSppServer('xtf', (res: MyApiResult) => {
if (res.type == 0) {
console.log('服务端已启动')
} else {
console.log(res.message)
}
})
服务端可同时维护多个客户端连接。onSppServerEvent() 事件如下:
| type | data | 说明 |
|---|---|---|
10000 |
DeviceData |
设备连接成功 |
10001 |
DeviceData |
设备断开或读取异常 |
10002 |
ServerReadData |
收到设备发送的十六进制数据 |
主动发送和断开设备
// connectionId 必须来自服务端事件的 res.data.mac。
BtServer.write(connectionId, '5566778899')
BtServer.closeSocket(connectionId)
关闭和重启服务端
BtServer.closeServer()
closeServer() 会关闭监听 socket、断开全部客户端并清空连接状态。之后可以再次调用 startSppServer() 启动服务。
API 一览
| API | 返回值 | 说明 |
|---|---|---|
isEnabled() |
boolean |
判断系统蓝牙是否开启 |
openBtBluetooth(callback) |
void |
请求权限并开启蓝牙 |
setConnectUUID(uuid) |
void |
设置客户端和服务端使用的 SPP UUID |
string2ByteStrWithCharset(data, code) |
string |
文本按指定字符集转十六进制 |
byte2StringWithCharset(data, code) |
string |
十六进制按指定字符集转文本 |
new BtClient() |
BtClient |
创建客户端实例 |
client.onStartScanDevice(callback) |
void |
开始扫描并持续返回设备 |
client.stopScan() |
void |
停止扫描 |
client.getBondDevices() |
MyApiResult |
获取系统已配对设备 |
client.bond(mac, callback) |
void |
发起配对 |
client.bondState(mac) |
number |
获取配对状态原始值 |
client.onConnnect(options) |
void |
连接 SPP 服务端 |
client.onStartAutoReadData(callback) |
void |
开始读取连接数据 |
client.stopAutoRead() |
void |
停止读取循环或移除读取监听 |
client.write(hex) |
void |
发送十六进制数据 |
client.isBtConnect() |
boolean |
获取当前连接状态 |
client.close() |
void |
关闭客户端连接 |
BtServer.onSppServerEvent(callback) |
void |
注册服务端连接和数据事件 |
BtServer.startSppServer(name, callback) |
void |
启动 SPP 服务端 |
BtServer.write(connectionId, hex) |
void |
向指定连接发送数据 |
BtServer.closeSocket(connectionId) |
void |
关闭指定连接 |
BtServer.closeServer() |
void |
关闭服务端及全部连接 |
权限说明
插件已在平台配置中声明所需权限,并会在调用相关 API 时请求运行时权限:
- Android 12 及以上:
BLUETOOTH_SCAN、BLUETOOTH_CONNECT。 - Android 11 及以下:扫描需要
ACCESS_FINE_LOCATION;同时声明经典蓝牙相关权限。 - HarmonyOS:
ohos.permission.ACCESS_BLUETOOTH、ohos.permission.DISCOVER_BLUETOOTH。
用户拒绝权限时,相关回调返回 type == -1。应引导用户在系统设置中重新授权后再调用。
使用注意
- 本插件操作的是经典蓝牙 SPP,不是 BLE。BLE 外设不能直接通过本插件连接。
- 连接地址、UUID 和通信协议必须与目标设备一致。
- Android 与 HarmonyOS 的接收数据空格格式可能不同,业务层不要依赖空格分隔。
- Android 扫描、配对和开启蓝牙可能弹出系统授权或确认界面。
- 应在页面卸载时停止扫描并关闭不再使用的客户端或服务端资源。
write()没有发送结果回调;如需确认业务数据是否送达,应在通信协议中设计应答帧。- iOS 仅提供接口占位以保证跨平台引用,不能进行通用 SPP 通信。

收藏人数:
购买源码授权版(
试用
使用 HBuilderX 导入示例项目
赞赏(0)
下载 13335
赞赏 75
下载 12629386
赞赏 1950
赞赏
京公网安备:11010802035340号