uniapp 微信小程序读取nfc标签数据
本文介绍了微信小程序中读取NFC标签数据的实现方法。通过对比wx.startHCE()和wx.getNFCAdapter()的适用场景,选择使用wx.getNFCAdapter()实现(仅支持安卓)。文章详细说明了如何初始化NFC监听、处理返回的ArrayBuffer数据(包含buffer转十六进制字符串和手动转字符串的方法),以及必要的资源释放操作。关键点包括:正确设置NDEF格式监听、数据转换
在开发微信小程序的时候遇到个读取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('')
// 初始化NFC
const initNfc = () => {
// 确保在微信小程序环境
// #ifdef MP-WEIXIN
if (!wx.getNFCAdapter) {
errorMessage.value = '当前微信版本不支持NFC'
return
}
nfcAdapter.value = wx.getNFCAdapter()
startDiscovery()
// #endif
}
// 开始发现NFC标签
const startDiscovery = () => {
if (!nfcAdapter.value || isReading.value) return
nfcAdapter.value.startDiscovery({
techTypes: ['android.nfc.tech.Ndef'], // 明确指定NDEF格式
success: () => {
showToast('nfc监听启动成功')
isReading.value = true
setupListeners()
},
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('')
// 初始化NFC
const initNfc = () => {
// 确保在微信小程序环境
// #ifdef MP-WEIXIN
if (!wx.getNFCAdapter) {
errorMessage.value = '当前微信版本不支持NFC'
return
}
nfcAdapter.value = wx.getNFCAdapter()
startDiscovery()
// #endif
}
// 开始发现NFC标签
const startDiscovery = () => {
if (!nfcAdapter.value || isReading.value) return
nfcAdapter.value.startDiscovery({
techTypes: ['android.nfc.tech.Ndef'], // 明确指定NDEF格式
success: () => {
showToast('nfc监听启动成功')
isReading.value = true
setupListeners()
},
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 数据),返回原始字符串
}
}
如有错误的地方,欢迎联系俺来纠正。

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐
所有评论(0)