ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

uniapp 集成 RFID 原生插件:从选型到离线打包全流程

uniapp 集成 RFID 原生插件:从选型到离线打包全流程 1. 项目缘起与整体方案拆解RFID 识别在 uniapp 里一直是个“看起来简单、做起来全是坑”的活儿。我最早接触这个需求是给一家做仓储盘点的团队做手持终端应用客户要求用安卓 PDA 扫 RFID 标签实时把编码回传到 uniapp 的业务页面里。当时第一反应是找现成插件结果发现 uniapp 官方生态里对 RFID 的支持几乎是空白——扫码有uni.scanCodeNFC 有零散的社区方案但 RFID 这种需要主动发射射频、批量读取多标签的场景纯 JS 层根本碰不到硬件。所以这个项目的核心思路就一句话用 uniapp 做业务层和 UI用 Android 原生插件做 RFID 硬件通信层中间靠广播或回调桥接。为什么是广播因为大多数国产 RFID 模块比如常见的超高频模块厂商提供的 SDK 都是 Android 原生 AAR 包它们读取到标签后最自然的输出方式就是发一条系统广播或者通过串口回调。广播的好处是解耦——原生层只管发uniapp 层只管收双方不需要互相持有引用调试的时候也能用adb单独验证原生层是否正常工作。这里要先厘清一个高频混淆点RFID 和 NFC 不是一回事。NFC 工作距离通常 4 厘米以内频率 13.56MHz适合支付、门禁这种“贴一下”的场景RFID 尤其是超高频UHF可以做到几米甚至十几米支持同时读取上百个标签仓储、物流、盘点用的基本都是这一类。你在选型时如果发现模块标的是 860-960MHz那就是 UHF RFID通信协议通常是串口或 USB需要原生层做数据解析。方案选型上我对比过三条路。第一条是纯 H5 的 Web Bluetooth 或 Web Serial理论上浏览器能直连串口但 uniapp 打包成 App 后 WebView 对这两个 API 的支持极不稳定安卓各版本差异大直接放弃。第二条是找现成的 uni 原生插件市场方案优点是省事缺点是很多插件年久失修而且 RFID 模块型号千差万别通用插件往往只适配某几个品牌换模块就废。第三条就是自己写原生插件用 Android Studio 建一个 Library 模块把厂商 SDK 包进去暴露统一接口给 uniapp。我最终选了第三条虽然前期多花两天但后面换模块、加功能都从容得多。整个数据流是这样的RFID 模块上电后持续发射射频读到标签就通过串口把 EPC 编码传给 Android 原生层原生层解析后通过LocalBroadcastManager或sendBroadcast发出uniapp 侧在onLoad里注册广播监听收到后更新data里的列表。如果是离线打包还需要在manifest.json里配置原生插件路径和权限。下面这张表是我当时整理的关键决策点决策项可选方案最终选择理由通信方式广播 / 回调 / 串口直读广播解耦好调试方便uniapp 侧改动小插件形态市场插件 / 自研插件自研模块型号可控长期维护成本低打包方式云打包 / 离线打包离线打包原生插件必须离线云打包不支持自定义 AAR数据格式JSON / 纯字符串JSON方便扩展字段如 RSSI、读取次数提示如果你只是做 demo 验证可以先用厂商提供的 Android 测试 APK 确认模块能正常读卡再动手写 uniapp 插件。跳过这一步直接集成出了问题你分不清是硬件、原生还是 uniapp 的锅。2. 原生插件开发的核心细节与实操要点写原生插件是整个项目里最硬的部分但也没那么玄乎。你把它理解成“给 uniapp 造一个遥控器”就行——uniapp 按按钮原生层执行动作结果再传回来。Android Studio 这边我建议直接用最新稳定版安装时记得勾选 Android SDK 和 NDK汉化包可装可不装命令行的活儿其实更多。第一步是建工程。打开 Android Studio新建一个No Activity项目然后File - New - New Module选Android Library命名比如rfid-plugin。这个 Library 就是最终要打进 uniapp 的模块。接着把厂商给的.aar或.jar丢进libs目录在build.gradle里加implementation fileTree(dir: libs, include: [*.jar, *.aar])。这里有个坑有些厂商 SDK 依赖特定的minSdkVersion比如要求 21 以上你需要在 Library 和主工程里保持一致否则打包时会报 manifest 合并冲突。第二步是写插件类。uniapp 原生插件有两种模式Module无 UI纯功能和Component有 UI。RFID 识别属于前者继承UniModule用UniJSMethod注解暴露方法。核心方法一般就三个init初始化模块、startInventory开始盘存、stopInventory停止。初始化时要把厂商 SDK 的上下文传进去通常是mUniSDKInstance.getContext()。盘存开始后SDK 会在子线程回调标签数据你需要在回调里组装成JSONObject然后通过mUniSDKInstance.fireGlobalEventCallback(rfidTag, params)发给 uniapp 侧。这个fireGlobalEventCallback就是官方推荐的事件通道比广播更规范uniapp 侧用uni.$on监听即可。第三步是权限和配置。RFID 模块通常走串口或 USB需要android.permission.USB_PERMISSION或者串口权限部分模块还要ACCESS_FINE_LOCATION因为蓝牙扫描在安卓 6.0 后需要定位权限。这些要写在 Library 的AndroidManifest.xml里uniapp 离线打包时会自动合并。另外manifest.json的app-plus - plugins节点要声明插件格式如下plugins: { RFIDPlugin: { version: 1.0.0, provider: your.package.name.RFIDModule } }注意provider必须和原生插件类的完整包名一致大小写都不能错。我见过有人写成com.example.rfidmodule但实际类是com.example.RFIDModule结果运行时报“插件未找到”排查了半天。第四步是调试。原生插件没法在 HBuilderX 的模拟器里跑必须真机。我的做法是先用 Android Studio 直接跑一个测试 Activity确认 SDK 能读到卡再把同样的逻辑搬进UniModule。调试 uniapp 侧时用adb logcat | grep -i rfid过滤日志能看到原生层打的 log 和 uniapp 的报错。如果fireGlobalEventCallback没反应先检查mUniSDKInstance是否为空再检查事件名是否拼写一致。这里补充一个参数选择的经验。RFID 模块的发射功率直接影响读取距离和发热一般默认 30dBm 左右室内盘点可以降到 20-26dBm既省电又减少误读。盘存模式分“快速”和“智能”快速模式读得快但可能漏标签智能模式会做去重和信号筛选适合需要精确计数的场景。这些参数通常通过setPower和setInventoryMode方法设置具体看厂商 SDK 文档。3. uniapp 侧集成与完整实操流程原生插件编译出.aar后接下来就是 uniapp 侧的活儿。我习惯先在 HBuilderX 里建一个空白 uniapp 项目目录结构保持默认然后在根目录建nativeplugins文件夹把插件包按规范放进去nativeplugins/RFIDPlugin/android/下面放.aar和package.json。package.json里要写清楚插件 id、版本、集成方式这个文件是离线打包时识别插件的关键。页面逻辑其实不复杂。在onLoad里调用uni.requireNativePlugin(RFIDPlugin)拿到插件实例然后uni.$on(rfidTag, handler)注册事件监听。点击“开始盘点”按钮时调plugin.startInventory()收到数据后往tagList数组里 push同时用this.$set或直接赋值触发视图更新。这里有个性能细节如果标签量大比如一秒几十条频繁setData会卡顿我的做法是攒 200 毫秒批量更新一次或者用Object.freeze减少响应式开销。完整流程我整理成下面这几步你可以直接照着走环境准备安装 HBuilderX、Android Studio、配置好 Android SDK手机开启 USB 调试。原生插件编译在 Android Studio 里Build - Make Module产物在build/outputs/aar/下。插件集成把.aar和package.json放进nativeplugins在manifest.json里声明。页面开发写requireNativePlugin、事件监听、UI 列表。离线打包HBuilderX 里发行 - 原生App-本地打包生成 APK 后安装到 PDA。联调验证用真实标签测试读取距离、速度、去重逻辑。打包环节是新手最容易翻车的地方。云打包不支持自定义原生插件必须走离线打包。离线打包需要下载 Android 离线 SDK用 Android Studio 打开HBuilder-Integrate-AS工程把 uniapp 项目编译出的app资源放进去再配置dcloud_control.xml里的appid。整个过程第一次做可能要折腾半天但配好之后每次打包就是点一下的事。提示离线打包时如果报content://相关的 FileProvider 冲突多半是多个插件都声明了provider需要给每个 provider 加不同的authorities。这个报错信息里会带com.tencent.wework.fileprovider或com.baidu.searchbox.fileprovider这类字样别慌就是 authorities 重名了。UI 层面我建议做一个简单的列表加统计栏顶部显示“已读取 N 个标签”中间是scroll-view列表每条显示 EPC 编码和读取次数底部两个按钮“开始/停止”和“清空”。EPC 编码通常是一串十六进制展示时可以按 4 位一组加空格方便肉眼核对。如果需要导出用uni.saveFile存成 CSV 再分享。4. 常见问题排查与避坑经验实录做这个项目我踩的坑不算少挑几个最有代表性的说说。第一个是权限申请框监听不到。uniapp 里想实时知道用户有没有点“允许”官方没有直接 API我的做法是在原生插件里重写onRequestPermissionsResult把结果通过事件发回 uniapp。这样比在 JS 层轮询靠谱得多。第二个是小米手机打包后没有麦克风权限。这个其实和 RFID 无关但很多人会混淆。原因是小米的权限管理比较特殊需要在manifest.json里显式声明android.permission.RECORD_AUDIO并且在原生层动态申请。RFID 模块如果走 USB还要加android.hardware.usb.action.USB_DEVICE_ATTACHED的 intent filter。第三个是广播收不到数据。排查顺序是先看原生层 log 有没有打印标签数据再看fireGlobalEventCallback的事件名和 uniapp 侧uni.$on是否一致最后检查mUniSDKInstance是否在onCreate之后才初始化。我遇到过一次是事件名大小写不一致rfidTag写成了rfidtag找了两个小时。第四个是读取速度慢或漏读。这通常是功率和盘存模式的问题。把功率调到 26-30dBm盘存模式设为“智能”并且在原生层做去重——同一个 EPC 在 2 秒内只上报一次。去重逻辑用HashMap记录时间戳就行很简单但很有效。下面这张表是我整理的常见问题速查现象可能原因解决方向插件未找到provider 包名错误核对manifest.json和类名收不到标签事件名不一致 / 未初始化检查uni.$on和mUniSDKInstance读取距离短功率过低调高setPower到 26dBm 以上重复标签多未去重原生层加时间窗口去重打包失败FileProvider 冲突给每个 provider 设不同 authorities权限弹窗无响应未重写权限回调原生层onRequestPermissionsResult回传注意RFID 模块长时间满功率工作会发热手持终端连续盘点超过 30 分钟建议降功率或间歇停止。这不是软件问题是硬件特性别硬扛。最后分享一个我自己的习惯每次换新模块先写一个最小原生测试工程只做“初始化-开始-打印标签”三件事跑通了再往 uniapp 里集成。这样能把硬件问题和集成问题彻底分开省下大量扯皮时间。RFID 这东西硬件稳了软件就是顺水推舟的事。
返回列表