uni-app 蓝牙打印失败主因是适配器未就绪、权限缺失(iOS需授权,Android需位置权限)、服务UUID不匹配、特征值未正确获取及数据格式错误(须用ArrayBuffer);务必分步执行连接、发现服务、获取特征值、设置MTU、分段写入二进制指令。

uni-app 调用 uni.openBluetoothAdapter 失败的常见原因
多数连接失败不是因为代码写错,而是蓝牙适配器未就绪或权限未触发。iOS 必须先调用 uni.openBluetoothAdapter,且需用户主动授权;Android 部分机型(如华为 EMUI、小米 MIUI)即使已开启蓝牙,也需额外授予「位置权限」——因为系统将蓝牙扫描视为定位行为。
实操建议:
- 在
onLoad或按钮点击后立即调用uni.openBluetoothAdapter,不要放在onLaunch里(此时页面未挂载,uni.showToast可能不显示) - 捕获
fail回调,若报错errCode: 10001(适配器不可用),提示用户手动打开蓝牙并重试 - Android 端务必在 manifest 或
android.permission.ACCESS_FINE_LOCATION中声明位置权限,且运行时请求(uni.authorize({scope: 'scope.location'}))
搜索蓝牙打印机时为什么扫不到设备
不是所有蓝牙打印机都广播可被发现的设备名,尤其热敏打印机(如 ZJ-5890、BIXOLON SRP-350II)默认使用 BLE(Bluetooth Low Energy)模式,但只响应特定服务 UUID 的连接请求,而非通用广播。直接调用 uni.startBluetoothDevicesDiscovery 后用 uni.onBluetoothDeviceFound 监听,大概率收不到回调。
实操建议:
- 优先使用
uni.getConnectedBluetoothDevices检查是否已配对过该打印机(部分设备配对后会自动连接) - 若需主动发现,设置
services参数为打印机支持的 UUID,例如 ESC/POS 打印常用['000018f0-0000-1000-8000-00805f9b34fb'](自定义服务)或标准串口服务['00001101-0000-1000-8000-00805f9b34fb'] - 避免长时间扫描(建议
duration: 10秒),否则 iOS 会强制中断,且 Android 后台扫描受限
调用 uni.createBLEConnection 连接后立即写数据失败
连接成功不代表服务和特征值已就绪。uni-app 的 BLE API 是异步分步的:连接 → 获取设备服务 → 获取服务特征值 → 启用 notify 或 write。跳过中间步骤直接 uni.writeBLECharacteristicValue,会报错 errCode: 10008(未找到特征值)或 10009(特征值不可写)。
实操建议:
- 必须在
uni.onBLEConnectionStateChange回调中确认connected: true后,再调用uni.getBLEDeviceServices - 获取服务后,立刻调用
uni.getBLEDeviceCharacteristics,并检查返回的characteristics数组中properties.write === true的项(注意大小写敏感) - 写入前确保已调用
uni.setBLEDeviceMTU(某些打印机要求 MTU ≥ 256),否则大数据量(如图片)会截断
uni-app 打印机指令发送不生效或乱码
根本问题在于数据格式:uni-app 的 uni.writeBLECharacteristicValue 要求 value 是 ArrayBuffer,而多数开发者直接传字符串或 hex 字符串(如 "1D 56 30"),导致底层协议解析失败。
实操建议:
- 将十六进制指令转为
Uint8Array再封装成 ArrayBuffer,例如 ESC/POS 指令0x1B 0x40(初始化)应写为:const buffer = new Uint8Array([0x1B, 0x40]).buffer
- 避免一次性写入超长数据(> 20 字节易丢包),拆分为多次
write,每次间隔 50ms 以上(可用setTimeout控制节奏) - 热敏打印机通常需要先写入初始化指令,再写文本或图片;若跳过初始化,可能处于异常状态(如缩放模式、中文编码错误)
真正卡住的地方往往不在连接动作本身,而在服务发现后的特征值匹配、MTU 协商、以及二进制数据构造这三个环节。尤其是不同品牌打印机对 UUID 和特征值属性的实现差异极大,最好手头有一台目标设备,用 nRF Connect 先抓包确认其真实服务结构。



















