更新记录

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 页面中不需要引入 MyApiResultDeviceDataServerReadDataConnectPara 等 UTS 类型。

数据约定

插件的读写数据均为十六进制字符串,而不是普通文本。

client.write('5566778899')
  • 建议只传入 0-9A-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-8gbkiso-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_SCANBLUETOOTH_CONNECT
  • Android 11 及以下:扫描需要 ACCESS_FINE_LOCATION;同时声明经典蓝牙相关权限。
  • HarmonyOS:ohos.permission.ACCESS_BLUETOOTHohos.permission.DISCOVER_BLUETOOTH

用户拒绝权限时,相关回调返回 type == -1。应引导用户在系统设置中重新授权后再调用。

使用注意

  • 本插件操作的是经典蓝牙 SPP,不是 BLE。BLE 外设不能直接通过本插件连接。
  • 连接地址、UUID 和通信协议必须与目标设备一致。
  • Android 与 HarmonyOS 的接收数据空格格式可能不同,业务层不要依赖空格分隔。
  • Android 扫描、配对和开启蓝牙可能弹出系统授权或确认界面。
  • 应在页面卸载时停止扫描并关闭不再使用的客户端或服务端资源。
  • write() 没有发送结果回调;如需确认业务数据是否送达,应在通信协议中设计应答帧。
  • iOS 仅提供接口占位以保证跨平台引用,不能进行通用 SPP 通信。

相关文档

隐私、权限声明

1. 本插件需要申请的系统权限列表:

<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" /> <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" /> <uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/> <uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/> <uses-permission android:name="android.permission.BLUETOOTH"/> <uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

暂无用户评论。