从 0 到 1 做一个支持 NFC 写入的小程序,需要哪些 API?

小程序实现NFC写入功能所需API详解

在开发支持NFC写入的小程序时,了解其技术边界和核心API至关重要。本文将详细介绍如何使用微信小程序的NFC API来实现标签发现、连接及数据写入的功能,并提供具体的代码示例。

项目概览与目标

NFC Scan 这个小程序的核心功能是让用户通过手机NFC模块向标签上写入网页链接、应用包名或音乐直达链接,从而实现碰一碰直接跳转至指定内容。其具体流程为:

  1. 用户在小程序中填写目标URL或应用包名。
  2. 点击“开始写入”按钮后启动NFC标签发现功能。
  3. 通过NDEF标准格式将数据写入到符合要求的NFC标签上。
  4. 执行成功或失败反馈。

开发前提条件

开发支持NFC写入的小程序需要满足以下几个基础条件:

  • 设备兼容性:仅限于Android真机,且该设备必须具备有效的NFC功能。微信小程序基础库版本需与NFC能力相匹配。
  • 标签规格:使用标准的NDEF格式标签,避免容量不足、损坏或加密等情况导致写入失败。

核心API详解

实现NFC写入功能的关键在于正确调用和处理以下几个核心API:

1. 获取适配器

const nfcAdapter = wx.getNFCAdapter();

此API用于初始化并获取NFC操作的适配器实例,后续所有与NFC相关的方法都将通过这个实例来调用。

2. 开始监听标签发现

nfcAdapter.startDiscovery({
  success() {
    console.log('开始监听 NFC 标签');
  },
  fail() {
    console.log('监听失败');
  }
});

该API在用户点击“开始写入”时调用,启动对NFC标签的持续监听。

3. 监听标签发现事件

nfcAdapter.onDiscovered((res) => {
  const techs = res.techs || [];
  if (techs.includes('NDEF')) {
    this.writeNdefMessage();
  } else {
    this.showError('不支持的标签技术');
  }
});

当发现新的NFC标签时触发此回调函数,判断是否为标准NDEF格式,并决定后续操作。

4. 连接和写入NDEF消息

ndef = nfcAdapter.getNdef();
ndef.connect({
  success() {
    this.writeRecords();
  },
  fail(error) {
    if (error.errCode === 13022) { 
      this.writeRecords(); // 已连接,可以继续写入
    } else {
      this.showError('连接失败');
    }
  }
});
ndef.writeNdefMessage({
  records: [
    {
      tnf: 1,
      id: 'web',
      type: 'U',
      payload: 'https://example.com'
    }
  ],
  success() {
    console.log('写入成功');
  },
  fail() {
    console.log('写入失败');
  }
});

这些API首先获取NDEF实例,然后尝试连接标签,并最终执行具体的记录写入操作。注意确保records数组中的数据格式符合NDEF规范。

5. 清理资源

nfcAdapter.offDiscovered(); // 取消监听
nfcAdapter.stopDiscovery(); // 停止发现
ndef.close();               // 关闭连接

这些清理操作用于结束与标签的交互,避免不必要的监听和重复触发。

实际应用场景

根据不同的业务需求设计相应的NDEF记录格式:

  • 网页链接:使用URI类型的记录。

    { tnf: 1, id: 'web', type: 'U', payload: 'https://example.com' }
  • 应用包名:为Android特定的应用程序创建记录。

    { tnf: 4, id: 'pkg', type: 'android.com:pkg', payload: 'com.tencent.mobileqq' }

通过上述步骤,开发者可以基于微信小程序平台构建出功能强大的NFC标签写入应用。希望本文能够帮助开发人员更好地理解和使用此特性。完整代码及更多细节请参考项目文档和API说明。

五、完整写入流程详解

为了实现NFC写入功能的模块化和简化调用过程,可以将整个流程封装为一个单独的组件。这样做不仅能够清晰地展示每个步骤的状态变化,还便于用户直观了解操作结果。

第一步:准备写入数据

在开始具体操作前,需要根据业务需求构建一系列格式化的记录对象,并将其传递给NFC写入弹窗组件。

this.setData({
  scanVisible: true,
  records: [{
    tnf: 1,
    id: 'web',
    type: 'U',
    payload: 'https://example.com'
  }]
});

其中,tnf(技术名称格式)表示标签数据类型;id用于标识特定的URI记录;type代表NDEF消息中的资源类别;而payload则是实际需要写入的数据内容。

第二步:组件显示,开始监听

在弹窗组件被触发时,首先检查当前设备是否支持NFC功能。如果支持,则启动发现过程以寻找附近的标签。

onShow() {
  if (!wx.getNFCAdapter) {
    this.setData({ scanStatus: 'error', errorMessage: '当前设备不支持 NFC' });
    return;
  }

  const adapter = wx.getNFCAdapter();
  adapter.startDiscovery({
    success: () => {
      adapter.onDiscovered(this.handleDiscovered);
    },
    fail: () => {
      this.setData({ scanStatus: 'error', errorMessage: '发现NFC设备失败' });
    }
  });
}

如果检测到不支持,组件将直接报告错误状态并提醒用户。

第三步:发现标签后判断类型

当接收到onDiscovered()回调时,会传回一个包含技术信息的对象数组。根据这些数据来判断是否能进行NDEF写入操作。

handleDiscovered(res) {
  const techs = Array.isArray(res.techs) ? res.techs : [];

  if (techs.includes('NDEF')) {
    this.ndefAdapterWrite();
  } else {
    this.setData({ scanStatus: 'error', errorMessage: '不支持的标签技术' });
  }
}

这里只处理NDEF技术,其他类型则记录错误信息并停止进一步操作。

第四步:连接并写入

当确认了目标标签后,便可以发起与该标签建立连接,并根据先前定义的数据对象进行数据写入。

ndefAdapterWrite() {
  const ndef = this.data.baseNfcAdapter.getNdef();

  ndef.connect({
    success: () => {
      ndef.writeNdefMessage({
        records: this.buildRecords(),
        success: () => {
          this.setData({ scanStatus: 'success' });
        },
        fail: () => {
          this.setData({ scanStatus: 'error', errorMessage: '写入失败,请重试' });
        }
      });
    },
    fail: (error) => {
      if (error.errCode === 13022) {
        // 已连接,直接写入
        ndef.writeNdefMessage({ ... });
      } else {
        this.setData({ scanStatus: 'error', errorMessage: '连接失败' });
      }
    }
  });
}

成功后更新状态为"成功";否则记录更具体的错误信息并提示用户尝试重新操作。

六、除了 NFC API,还要配哪些能力

NFC写入功能的实现不仅仅是调用一些API那么简单。通常还需要配合其他方法来确保整体流程的顺畅和用户体验的良好:

  • wx.request():用于获取远程数据或解析特定格式的内容(如音乐分享链接)。
  • wx.getClipboardData():提供快速粘贴文本的功能,便于用户直接使用已复制的信息进行操作。
  • wx.canIUse():检查当前小程序是否具备执行某项功能所需的条件。
  • wx.getUpdateManager():监控版本更新情况并提示用户升级。

这些辅助API的合理应用能够大幅增强NFC写入组件的实际可用性和灵活性。

七、最容易踩的 5 个坑

在开发此类功能时,开发者可能会遇到一些常见的问题:

  1. 不做重复发现保护:标签靠近设备时可能触发多次探测事件。为了避免这种情况导致的频繁重试或数据丢失,应该实施适当的锁定机制。
  2. 只管写,不管清理:当用户的操作结束(如关闭弹窗)后,如果不执行必要的清理步骤,则可能导致后续调用出现问题。
  3. URI Payload 直接裸写字符串:直接将普通文本放入NDEF URI记录中可能会导致解析失败或不正确的结果。必须遵循相应的编码规则以确保数据格式正确无误。
  4. 忽略平台差异:不同操作系统上的实现细节可能存在区别,如Android和iOS的处理逻辑可能完全不同。应当针对每个平台定制解决方案。
  5. 只做成功态,不做失败态:在实际部署过程中将会遇到各种各样的意外情况,因此应该准备详尽且准确地报告所有可能出现的问题。

八、项目结构一览

miniprogram/
├── components/               # 自定义组件
│   ├── pixel-navbar/         # 导航栏组件
│   ├── pixel-toast/          # 通知提示组件
│   ├── pixel-icon/           # 图标库
│   └── scan-dialog/          # NFC写入弹窗
├── pages/                    # 页面
│   ├── write-menu/           # 功能入口页面
│   ├── write-app/            # 应用写入页面
│   ├── write-music/          # 音乐写入页面
│   └── write-web/            # 网页写入页面
├── styles/                   # 样式文件
├── utils/                    # 工具函数集合
│   ├── convert.js           # 数据转换工具
│   └── extract.js           # 内容解析器
└── app.js

合理的项目结构有助于代码的维护和扩展,使得每一个组件或页面都有明确的功能定位。

九、最后

在开发微信小程序NFC写入功能时,最重要的是要在微信提供的能力和边界内设计完整的交互流程。这包括标签格式的选择、平台差异的支持以及对失败状态的有效处理。通过专注于这三个核心方面,并按照规范进行实现,可以确保最终产品的稳定性和用户友好性。

建议开发者从最基本的步骤开始做起,在深入研究和实践的基础上逐步扩展功能范围。这样不仅能提高代码质量和用户体验,还能帮助更好地应对未来可能出现的各种挑战。