> 技术文档 > uniapp 微信小程序读取nfc标签数据_uniapp nfc

uniapp 微信小程序读取nfc标签数据_uniapp nfc

        在开发微信小程序的时候遇到个读取nfc数据进行跳转的问题,通过查看wx的官方文档,发现有两个方法可以使用,一个是wx.startHCE(),一个是wx.getNFCAdapter()。通过尝试和查询,最后发现wx.startHCE()只适用于支付类卡,还必须传入AID值,不适用读取nfc标签数据的需求,而wx.getNFCAdapter()可以实现这个需求,但是微信小程序读取出的值会返回一个ArrayBuffer的数据类型,正常用console.log()输入会出现一个“空对象”的情况,下面我将会讲wx.getNFCAdapter()的使用方法,以及如何处理读取到的数据。

注:此方法只适用于安卓用户,苹果用户暂不支持。

一、使用wx.getNFCAdapter()开启nfc监听。

1.开启监听

// 实例化 const nfcAdapter = ref(null) // 是否开启const isReading = ref(false) // 错误信息 const errorMessage = ref(\'\') // 初始化NFCconst initNfc = () => {// 确保在微信小程序环境// #ifdef MP-WEIXINif (!wx.getNFCAdapter) {errorMessage.value = \'当前微信版本不支持NFC\'return}nfcAdapter.value = wx.getNFCAdapter()startDiscovery()// #endif}// 开始发现NFC标签const startDiscovery = () => {if (!nfcAdapter.value || isReading.value) returnnfcAdapter.value.startDiscovery({techTypes: [\'android.nfc.tech.Ndef\'], // 明确指定NDEF格式success: () => {showToast(\'nfc监听启动成功\')isReading.value = truesetupListeners()},fail: (err) => {errorMessage.value = `NFC启动失败: ${err.errMsg}`console.error(\'NFC错误:\', err)}})} // 处理读取到的nfc数据const setupListeners = () => {nfcAdapter.value.onDiscovered((res) => {console.log(\'读取到的nfc数据\',res);});};

 2.释放资源

启动监听之后,每次离开页面释放资源,以免出现重复进入页面nfc报错。

// 释放资源const releaseNfc = () => {if (nfcAdapter.value && isReading.value) {nfcAdapter.value.stopDiscovery()nfcAdapter.value.offDiscovered?.()isReading.value = false}}

 二、处理返回后的数据

一般标签的返回数据是

{\"messages\": [{\"records\": [{\"tnf\": 1,\"type\": {},\"id\": {},\"payload\": {}}]}],\"techs\": [\"NFC-4\", \"NDEF\"]}

一般数据就存储在payload里面,只不过由于微信小程序返回的数据是个buffer,所以看不到他的完整信息,也无法使用,这个时候就需要将需要的数据转换一下。

我这边使用的方法是先将buffer转为十六进制,再将十六进制转为字符串

1.buffer转为十六进制

 // 转换为十六进制字符串 function arrayBufferToHex(buffer) { return Array.from(new Uint8Array(buffer)) .map(byte => byte.toString(16).padStart(2, \'0\')) .join(\'\') }

2.十六进制手动转为字符串

 这里选择的是手动转为字符串,在查资料的时候是发现有TextDecoder()和Buffer()的方法完成数据转换的,不过可能是环境不支持吧,方法无法使用,最后还是手动转为字符串。

// 十六进制手动转为字符串 function hexToString(hex) {// 1. 移除非法字符(如空格、冒号)const cleanHex = hex.replace(/[^0-9a-fA-F]/g, \'\');// 2. 每 2 个字符解析为一个 Unicode 码点let str = \'\';for (let i = 0; i < cleanHex.length; i += 2) {const byte = cleanHex.substr(i, 2);str += String.fromCharCode(parseInt(byte, 16));}// 3. 处理中文(UTF-8 编码)try {return decodeURIComponent(escape(str));} catch (e) {return str; // 如果解码失败(如非 UTF-8 数据),返回原始字符串}}

在数据转为字符串之后,就可以正常的使用了。

以下是完整代码:

// 初始化onMounted(() => {initNfc()}) // 释放资源onUnmounted(() => {releaseNfc()}) // 实例化 const nfcAdapter = ref(null) // 是否开启const isReading = ref(false) // 错误信息 const errorMessage = ref(\'\') // 初始化NFCconst initNfc = () => {// 确保在微信小程序环境// #ifdef MP-WEIXINif (!wx.getNFCAdapter) {errorMessage.value = \'当前微信版本不支持NFC\'return}nfcAdapter.value = wx.getNFCAdapter()startDiscovery()// #endif}// 开始发现NFC标签const startDiscovery = () => {if (!nfcAdapter.value || isReading.value) returnnfcAdapter.value.startDiscovery({techTypes: [\'android.nfc.tech.Ndef\'], // 明确指定NDEF格式success: () => {showToast(\'nfc监听启动成功\')isReading.value = truesetupListeners()},fail: (err) => {errorMessage.value = `NFC启动失败: ${err.errMsg}`console.error(\'NFC错误:\', err)}})} // 处理读取到的nfc数据const setupListeners = () => {nfcAdapter.value.onDiscovered((res) => {console.log(\'读取到的nfc数据\',res);// 转化字符串后的nfc数据,具体内部传入的数据根据自身nfc返回的数据传入let nfcData = hexToString(arrayBufferToHex(res.messages[0].records[0].payload))});};// 释放资源const releaseNfc = () => {if (nfcAdapter.value && isReading.value) {nfcAdapter.value.stopDiscovery()nfcAdapter.value.offDiscovered?.()isReading.value = false}} // 转换为十六进制字符串function arrayBufferToHex(buffer) {return Array.from(new Uint8Array(buffer)).map(byte => byte.toString(16).padStart(2, \'0\')).join(\'\')}// 十六进制手动转为字符串function hexToString(hex) {// 1. 移除非法字符(如空格、冒号)const cleanHex = hex.replace(/[^0-9a-fA-F]/g, \'\');// 2. 每 2 个字符解析为一个 Unicode 码点let str = \'\';for (let i = 0; i < cleanHex.length; i += 2) {const byte = cleanHex.substr(i, 2);str += String.fromCharCode(parseInt(byte, 16));}// 3. 处理中文(UTF-8 编码)try {return decodeURIComponent(escape(str));} catch (e) {return str; // 如果解码失败(如非 UTF-8 数据),返回原始字符串}}

如有错误的地方,欢迎联系俺来纠正。