微信小程序读取nfc获取Ndef写入的数据

本文档介绍了如何在微信小程序中利用NFC功能读取NDEF(Near Field Communication Data Exchange Format)标签上的数据。通过创建一个utils工具类,实现了字节到字符串的转换、数据验证、UUID生成等实用方法。在Android平台上,利用NFCAdapter进行监听和数据读取,展示NDEF信息。同时,提供了WXML和WXSS样式文件来显示读取到的内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

微信小程序读取nfc获取Ndef写入的数据


提示:以下是本篇文章正文内容,下面案例可供参考

1.新建一个utils工具类里面新建utils.js文件

代码如下(示例):上面有一点事转换时间的不需要可以自己删掉

const formatTime = date => {
  const year = date.getFullYear()
  const month = date.getMonth() + 1
  const day = date.getDate()
  const hour = date.getHours()
  const minute = date.getMinutes()
  const second = date.getSeconds()

  // return `${[year, month, day].map(formatNumber).join('/')} ${[hour, minute, second].map(formatNumber).join(':')}`
  return `${[year, month, day].map(formatNumber).join('/')}`
}

const formatNumber = n => {
  n = n.toString()
  return n[1] ? n : `0${n}`
}

module.exports = {
  formatTime
}

 /**
 * 字节对象转字符串
 * @param {Object} arr
 */
export const byteToString = function (arr) {
  if (typeof arr === 'string') {
    return arr
  }

  var str = '',
    _arr = arr

  for (var i = 0; i < _arr.length; i++) {
    var one = _arr[i].toString(2),
      v = one.match(/^1+?(?=0)/)

    if (v && one.length == 8) {
      var bytesLength = v[0].length

      var store = _arr[i].toString(2).slice(7 - bytesLength)

      for (var st = 1; st < bytesLength; st++) {
        store += _arr[st + i].toString(2).slice(2)
      }

      str += String.fromCharCode(parseInt(store, 2))

      i += bytesLength - 1
    } else {
      str += String.fromCharCode(_arr[i])
    }
  }
  return str
}

/**
 * 检验数据是否为空
 */
export const isEmpty = obj => {
  if (obj === '' || obj === null || obj === undefined) {
    return true
  } else if (obj.constructor === Array && obj.length === 0) {
    return true
  } else if (obj.constructor === Object && Object.keys(obj).length === 0) {
    return true
  } else {
    return false
  }
}

/**
 * 生成UUID
 */
export const generateUUID = () => {
  let d = new Date().getTime()
  let uuid = 'xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
    // let uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
    let r = (d + Math.random() * 16) % 16 | 0
    d = Math.floor(d / 16)
    return (c == 'x' ? r : (r & 0x3) | 0x8).toString(16)
  })
  return uuid
}

/**
 * 字符串转字节
 * @param {Object} str
 */
export const stringToArrayBuffer = function (str) {
  // 首先将字符串转为16进制
  let val = ''
  for (let i = 0; i < str.length; i++) {
    if (val === '') {
      val = str.charCodeAt(i).toString(16)
    } else {
      val += ',' + str.charCodeAt(i).toString(16)
    }
  }
  // 将16进制转化为ArrayBuffer
  return new Uint8Array(
    val.match(/[\da-f]{2}/gi).map(function (h) {
      return parseInt(h, 16)
    })
  ).buffer
}

/**
 * 移除空字符
 */
export const removeNullCharacter = str => {
  return str.replace(/\\u([0-9]|[a-fA-F])([0-9]|[a-fA-F])([0-9]|[a-fA-F])([0-9]|[a-fA-F])/g, '')
}

/**
 * 格式化空字符为空字符串
 */
export const formatNullCharacter = str => {
  if (!str) return ''
  return JSON.parse(removeNullCharacter(JSON.stringify(str)))
}

/**
 * 节流函数
 * fn是我们需要包装的事件回调, interval是时间间隔的阈值
 */
export const throttle = (fn, interval) => {
  // last为上一次触发回调的时间
  let last = 0

  interval = interval || 1000

  // 将throttle处理结果当作函数返回
  return function () {
    // 保留调用时的this上下文
    let context = this
    // 保留调用时传入的参数
    let args = arguments
    // 记录本次触发回调的时间
    let now = +new Date()

    // 判断上次触发的时间和本次触发的时间差是否小于时间间隔的阈值
    if (now - last >= interval) {
      // 如果时间间隔大于我们设定的时间间隔阈值,则执行回调
      last = now
      fn.apply(context, args)
    }
  }
}

/**
 * 格式化得到aid值
 * @param {Object} buffer
 */
// export const ab2hex = function (buffer) {
//   var hexArr = Array.prototype.map.call(
//     new Uint8Array(buffer),

//     function (bit) {
//       return ('00' + bit.toString(16)).slice(-2);
//     }
//   );
//   return hexArr.join('');
// };

2.在add.json里面新建页面

代码如下(示例):我建的是"pages/NFC/NFC",nfc.js

import { byteToString, isEmpty, formatNullCharacter } from '../../utils/util'
const app = getApp()

Page({
  NFCAdapter: null,
  aaa: [],
  data: {
    nfcInfo: {},
    msgTitle: '',
    typeText: { U: '网址', T: '文本' }
  },
  onShow: function () {
    this.onInit()
  },
  onInit() {
    const platform = app.globalData.platform
    if (platform == 'android') {
      this.NFCAdapter = wx.getNFCAdapter()
      this.NFClistener()
    } else {
      if (platform != 'devtools') {
        wx.showModal({
          title: '提示',
          content: '小程序NFC官方暂仅支持安卓设备',
          confirmColor: '#d93e4b',
          confirmText: '确定',
          showCancel: false
        })
      }

      this.setData({
        msgTitle: '小程序NFC官方暂仅支持安卓设备'
      })
    }
  },
  /**
   * 开始监听 NFC
   */
  NFClistener() {
    this.NFCAdapter.startDiscovery({
      success: () => {
        this.setData({
          msgTitle: '请将设备放入识别区NFC',
          msgContent: ''
        })
        // 监听 NFC 标签
        this.NFCAdapter.onDiscovered(this.discoverHandler)
      },
      fail: error => {
        this.setData({
          msgTitle: '请重试'
        })
        console.error(error)
      }
    })
  },
  /**
   * 监听回调
   */
  discoverHandler(callback) {
    console.log('==================== START ====================')
    // console.log('callback.messages[0].records[0]', callback.messages[0].records[0].payload)
    //获取ArrayBuffer 
    var buffer = callback.messages[0].records[0].payload;
    //获取Uint8Array 
    var dataview = new DataView(buffer);
    console.log('dataview', dataview)
    //获取Uint8Array数组
    var ints = new Uint8Array(buffer);
    console.log('ints', ints)
    //截取数组
    var shuzu = ints.slice(3);
    console.log('shuzu',shuzu)
    // 编译Uint8Array数组
    let unit8Arr = new Uint8Array(shuzu);
    let encodedString = String.fromCharCode.apply(null, unit8Arr),
    // 处理中文乱码
      decodedString = decodeURIComponent(escape((encodedString)));
      // 赋值
    this.setData({ aaa: decodedString })


  },

  /**
   * 注销 NFCAdapter
   */
  onHide() {
    this.closeNFC()
  },
  onUnload: function () {
    this.closeNFC()
  }
})

3.代码如下(示例):nfc.wxml

<view class="page">
  <view class="ndef-box" bindtap="onClickNDEFContent">
    <view class="title">NDEF信息</view>
    <view class="content">
        <view class="label">类型描述:</view>
        <view>{{ aaa }}</view>
      </view>
  </view>
</view>

4.代码如下(示例):nfc.wxss

.page {
  padding: 20px;
  box-sizing: border-box;
  background-color: #f1f1f1;
  height: 100vh;
}

.msg-box {
  min-height: 300rpx;
  border-radius: 30rpx;
  overflow: hidden;
  background-color: #fff;
  margin-bottom: 30rpx;
}

.msg-box .text {
  text-align: center;
  line-height: 40rpx;
  padding: 20rpx;
  font-size: 28rpx;
  color: #333;
}

.ndef-box {
  border-radius: 30rpx;
  overflow: hidden;
  min-height: 500rpx;
  padding-bottom: 10px;
  background-color: #fff;
}


.msg-box .title,
.ndef-box .title {
  font-weight: 700;
  text-align: center;
  line-height: 100rpx;
  border-bottom: 1px solid #f2f2f2;
}

.ndef-box .content {
  display: flex;
  padding: 10px;
  font-size: 28rpx;
  line-height: 36rpx;
}

.ndef-box .content .label {
  font-weight: 700;
  min-width: 90rpx;
}

.ndef-box .placeholder {
  line-height: 188rpx;
  text-align: center;
  color: #666;
  font-size: 28rpx;
}

<think>好的,我需要帮助用户在UniApp开发的微信小程序中实现NFC读取功能。首先,用户提到了微信小程序NFC调起能力,参考了引用中的步骤,包括申请硬件设备、设备能力等。UniApp作为跨平台框架,可能需要通过条件编译或插件来支持微信小程序的特定API。 首先,用户需要在微信小程序后台申请NFC权限,这部分应该和原生小程序步骤类似,比如添加硬件设备,申请NFC调起能力,获取model_id。然后,在UniApp中,可能需要使用uni-app的条件编译,针对微信小程序平台调用wx.getHCEState等原生API。需要确认UniApp是否支持这些API,或者是否需要使用第三方插件。 接着,具体实现步骤可能包括:在UniApp项目中编写NFC读取逻辑,处理NFC标签的发现和读取,解析NDEF数据。需要注意的是,UniApp可能对微信原生API的支持有限,可能需要通过自定义组件或插件桥接。同时,测试时需要使用支持NFC的安卓设备,并且小程序需要在真机调试模式下运行。 可能遇到的问题包括UniAppNFC API的兼容性,以及如何正确传递参数。此外,用户可能需要处理不同NFC标签类型的兼容性,比如NDEF格式的数据解析。需要建议用户查阅UniApp微信小程序的官方文档,确保API的可用性,并在必要时联系UniApp的技术支持。</think>在 UniApp 中实现微信小程序NFC 读取功能,需通过以下步骤完成: --- ### 一、申请 NFC 调起能力 1. **添加硬件设备** 在微信小程序后台的【行为能力-硬件设备】中添加 NFC 设备,填写设备品牌和型号(可参考兼容的第三方 NFC 卡片厂商信息)[^1]。 2. **申请设备能力** 审核通过后,申请【NFC 调起小程序】能力,最终获取 `model_id`(用于绑定 NFC 标签)。 --- ### 二、UniApp 代码实现 #### 1. 配置 `manifest.json` ```json // 微信小程序专属配置 "mp-weixin": { "appid": "你的小程序AppID", "requiredBackgroundModes": ["nfc"], "permission": { "scope.userNFC": { "desc": "用于读取NFC标签信息" } } } ``` #### 2. 调用 NFC API ```javascript // 检查设备是否支持 NFC uni.getSystemInfo({ success(res) { if (res.host.nfcSupported) { // 初始化 NFC 模块 wx.startHCE({ aidList: ['你的NFC应用ID'], // 需与 model_id 关联 success() { // 监听 NFC 标签 wx.onHCEMessage(res => { const data = res.data; // 解析 NFC 数据(HEX 或 Base64) console.log('NFC数据:', data); }); } }); } } }); ``` #### 3. 解析 NDEF 格式数据 ```javascript // 示例:解析文本类型的 NDEF 数据 function decodeNDEF(buffer) { const view = new DataView(buffer); const typeLength = view.getUint8(0); let payload = ''; for (let i = 3; i < view.byteLength; i++) { payload += String.fromCharCode(view.getUint8(i)); } return payload; } ``` --- ### 三、注意事项 1. **真机调试** NFC 功能仅支持安卓设备,需通过微信开发者工具的【真机调试】验证。 2. **标签格式兼容性** 确保 NFC 标签已格式化为 NDEF 标准类型(如 `android.nfc.tech.Ndef`)。 3. **UniApp 限制** 部分微信原生 API 需通过条件编译实现: ```javascript // #ifdef MP-WEIXIN wx.startHCE({ ... }); // #endif ``` --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值