npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@nokecy/qc-bluetooth-print

v1.1.0

Published

Android 蓝牙打印插件(UTS 原生)。同时支持经典蓝牙 SPP(RFCOMM)和 BLE(GATT 自动协商 MTU + 分包写)。避开 plus.android JS 桥的同步/异步不确定行为。

Readme

qc-bluetooth-print

Android 蓝牙打印插件(UTS 原生)。同时支持:

  • 经典蓝牙 SPP(RFCOMM)—— 已配对的小票/标签热敏打印机
  • BLE 低功耗蓝牙(GATT,自动协商 MTU + 分包写)—— BLE-only 打印机

直接调用 android.bluetooth.* 原生类,避开 plus.android JS 桥的同步/异步不确定行为。

解决什么问题

uni-app App 端做经典蓝牙打印,长期被一组顽固问题困扰:

  • 连续打印第二张失败,要退出页面再进
  • isConnected() 报已连接,但 write 不出纸
  • 第一次连接 1.5 秒返回但 socket 没真连上,第二次才好

根因都是 plus.android.invoke JS 桥让 socket.connect() 立即返回(实际未阻塞)、isConnected() 在打印机端单方断开时不可靠、状态机层重复 connect 导致 socket 端点泄漏。

本插件用 UTS(编译成 Kotlin)直接调原生 API:

  • socket.connect() 在 IO 线程真正阻塞到 RFCOMM 建立完成
  • 写入失败 → 主动 close socket + 清状态,下次自动建新链路
  • 同地址乐观复用,由 write 失败做最终判活
  • 不再有「state 显示 CONNECTED 但 socket 已死」的幽灵状态

安装与同步

# 1. 安装 npm 包
npm install @nokecy/qc-bluetooth-print
# 或 pnpm
pnpm add @nokecy/qc-bluetooth-print

# 2. 同步插件到项目的 src/uni_modules/
npx qc-bluetooth-print sync

sync 命令会把 node_modules/@nokecy/qc-bluetooth-print/uni_modules/qc-bluetooth-print/ 完整复制到当前项目的 src/uni_modules/qc-bluetooth-print/(如果存在会询问是否覆盖,加 --force 强制覆盖)。

为什么需要 sync 步骤

uni-app 的 UTS 插件机制要求源码必须在 src/uni_modules/<plugin>/ 目录下才能被 HBuilderX 编译。npm 包本身不能直接被 HBuilderX 识别——这是 uni_modules 的设计约束,所有 UTS 类 npm 包都需要这一步。

打包要求

UTS 插件需要自定义基座才能在真机调试:

  1. HBuilderX 中:运行 → 运行到 Android App 基座 → 制作自定义调试基座
  2. 等基座打包完成(5-10 分钟)
  3. 真机运行时勾选「使用自定义基座」

API — 经典蓝牙 SPP

import * as qcbt from '@/uni_modules/qc-bluetooth-print'

// 获取系统已配对的蓝牙设备列表
const devices = qcbt.getBondedDevices()
// → [{ name: 'XP-365B', address: 'XX:XX:XX:XX:XX:XX' }, ...]

// 连接(同地址且 socket 仍活着会复用,不重连)
await qcbt.connect('XX:XX:XX:XX:XX:XX')

// 发送 CPCL / TSPL 文本指令(默认 GBK 编码,支持中文)
await qcbt.writeString('! 0 200 200 200 1\r\nTEXT 4 0 0 0 Hello\r\nPRINT\r\n')

// 发送 ESC/POS 字节指令(含位图)
await qcbt.writeBytes([0x1b, 0x40, 0x1b, 0x61, 0x01])

// 主动断开
qcbt.disconnect()

// 查询当前连接状态
qcbt.isConnected()

API — BLE 低功耗蓝牙

import * as qcbt from '@/uni_modules/qc-bluetooth-print'

// 扫描发现 BLE 设备(每发现一台调一次 callback)
qcbt.bleStartScan((device) => {
  console.log('BLE found:', device.name, device.address)
})
// 必须自己设置超时停止扫描(避免耗电)
setTimeout(() => qcbt.bleStopScan(), 8000)

// 连接(自动 discoverServices + 找首个可写 char + 协商 MTU 247)
await qcbt.bleConnect('XX:XX:XX:XX:XX:XX')

// 查看协商到的 MTU(决定单次写入容量 = mtu - 3)
console.log('BLE MTU:', qcbt.bleGetMtu())  // 典型值 247

// 发送字符串(自动按 mtu-3 分包 + 串行写入)
await qcbt.bleWriteString('! 0 200 200 200 1\r\nTEXT 4 0 0 0 Hello\r\nPRINT\r\n')

// 发送字节数组
await qcbt.bleWriteBytes([0x1b, 0x40, /* ... */])

// 断开
qcbt.bleDisconnect()

// 是否已连接
qcbt.bleIsConnected()

SPP vs BLE 怎么选

| 你的打印机 | 用哪组 API | |---|---| | 设备能在系统「已配对蓝牙设备」里看到 | 经典蓝牙 SPP | | 设备必须扫描发现,不出现在已配对列表 | BLE | | 同时支持两种 | 优先用 SPP,更稳定 |

平台支持

| 平台 | 支持 | |------|------| | App Android (5.0+) | ✅ 经典蓝牙 SPP | | App iOS | ❌ 需要 MFi 认证,复杂度大,未实现 | | 小程序 | ❌ | | H5 | ❌ |

设计取舍

  • 薄包装:不封装 CPCL/TSPL/ESC 指令,前端只做透传。指令字符串/字节流由调用方(或后端)生成
  • 单连接:模块级 socket 单例,符合打印机使用场景
  • 失败即清理:写入失败立即 close + 置 null,下次 connect() 自动重建——这是经典蓝牙唯一可靠的失效检测

已知风险点

UTS 是 DCloud 自研语法(编译到 Kotlin),有几处细节可能因 HBuilderX 版本不同而编译失败。完整 fallback 写法见 uni_modules/qc-bluetooth-print/readme.md

License

MIT © nokecy