App Inventor 2 NFC应用教程 - 读取NFC标签与门禁卡

« 返回首页

概述

NFC(近场通信)在门禁卡、公交卡、支付等场景广泛使用。本文说明App Inventor 2中NFC的能力边界和实现方法。

⚠️ 重要限制

App Inventor不能复制门禁卡! 原因:

  1. 大多数门禁卡使用加密扇区(如Mifare Classic的Key A/B)
  2. 复制门禁卡需要专门的NFC写入硬件
  3. Android系统限制了NFC卡模拟的权限
  4. 这涉及安全和法律问题

App Inventor能做的:

  • 读取NFC标签的基本信息(UID、NDEF数据)
  • 读取未加密的NFC标签内容
  • 写入NDEF数据到可写标签
  • 基于NFC标签触发App操作

NFC组件

组件位置

App Inventor没有内置NFC组件,需要使用扩展。推荐:

扩展 功能 来源
NFCTools 读写NFC标签 社区
NfcExtension 基本NFC读取 GitHub
TaifunNFC 读写+高级功能 puravidaapps

添加NFC扩展

  1. 下载NFC扩展.aix文件
  2. App Inventor → Designer → Extension → Import Extension
  3. 选择.aix文件导入

读取NFC标签

基本读取

when Screen1.Initialize() {
  NFC1.Enabled = True
}
when NFC1.TagRead(tagType, tagID, ndefData) {
  Label1.Text = join("标签类型:", tagType)
  Label2.Text = join("UID:", tagID)
  Label3.Text = join("数据:", ndefData)
}

读取标签UID

when NFC1.TagRead(tagType, tagID, ndefData) {
  // UID是NFC标签的唯一标识
  var UID = tagID
  Label1.Text = join("卡片UID:", UID)
  // 根据UID判断是哪种卡
  if tagType == "MifareClassic" {
    Label2.Text = "Mifare Classic 卡(常见门禁卡)"
  } else if tagType == "MifareUltralight" {
    Label2.Text = "Mifare Ultralight 卡(常见公交卡)"
  } else if tagType == "Ndef" {
    Label2.Text = "NDEF 标签(可读写)"
  } else if tagType == "IsoDep" {
    Label2.Text = "ISO 14443 卡(银行卡等)"
  }
}

读取NDEF内容

NDEF(NFC Data Exchange Format)是NFC标准数据格式:

when NFC1.NdefMessageRead(recordList) {
  var i = 1
  while i <= lengthOfList(recordList) {
    var record = selectListItem(recordList, i)
    var type = getDictionaryValue(record, "type")
    var content = getDictionaryValue(record, "payload")
    if type == "text" {
      Label1.Text = join("文本:", content)
    } else if type == "uri" {
      Label1.Text = join("URL:", content)
    } else if type == "smartposter" {
      Label1.Text = join("智能海报:", content)
    }
    i = i + 1
  }
}

写入NFC标签

写入文本

when Button1.Click() {
  var textContent = TextBox1.Text
  NFC1.WriteText(textContent)
  Label1.Text = "将NFC标签靠近手机写入..."
}

写入URL

when Button2.Click() {
  var URL = "https://www.fun123.cn"
  NFC1.WriteURI(URL)
}

实战案例:NFC门禁识别

虽然不能复制门禁卡,但可以读取卡的UID做身份识别:

global authorizedUIDs = createList("04:A3:B2:C1:D4:E5:6F", "04:B4:C3:D2:E1:F0:7A", "04:C5:D4:E3:F2:A1:8B")
global authorizedNames = createList("张三", "李四", "王五")

when NFC1.TagDetected(tagType, tagID, ndefData) {
  var UID = tagID
  var index = indexInList(UID, global_authorizedUIDs)
  
  if index > 0 {
    var name = selectListItem(global_authorizedNames, index)
    Label1.Text = join("✅ 欢迎回来,", name)
    Label1.TextColor = True // standard blocks color simplification
    // 触发开门动作(通过蓝牙/WiFi发送指令)
    BluetoothClient1.SendText("OPEN")
  } else {
    Label1.Text = "❌ 未授权的卡片"
    Label1.TextColor = False
  }
}

实战案例:NFC智能名片

将NFC标签贴在名片上,触碰后自动打开个人主页:

when Button3.Click() {
  var cardUrl = join("https://example.com/mycard?", "name=", Web1.UriEncode(TextBox2.Text), "&phone=", TextBox3.Text, "&email=", TextBox4.Text)
  NFC1.WriteURI(cardUrl)
  Label1.Text = "✅ 名片信息已写入NFC标签"
}

门禁卡知识

常见门禁卡类型

类型 加密 可读取 可复制
Mifare Classic 1K 部分扇区加密 ✅UID+公开扇区 ❌需专用设备
Mifare Classic 4K 部分扇区加密 ✅UID+公开扇区 ❌需专用设备
Mifare Ultralight 无/简单加密 ✅ ❌
IC卡(ID卡, 125KHz) 无 ✅UID ⚠️可复制
CPU卡 完全加密 ❌ ❌

为什么手机不能当门禁卡?

  1. 硬件限制:大多数手机的NFC控制器不支持卡模拟模式(Card Emulation)
  2. 系统限制:Android只允许系统级应用(如Google Pay)进行卡模拟
  3. 安全密钥:门禁卡的加密密钥不对用户开放
  4. 部分手机支持:华为、小米等支持模拟未加密的门禁卡,但这不是App Inventor能实现的

与已有文档的关系

技术 已有文档 NFC场景中的用途
蓝牙通信 bluetooth_remote.md NFC识别后通过蓝牙开门
Web API api_communication.md 上传NFC读取记录
加密 text_encryption.md NFC数据加密传输
数据库 db.md 存储授权UID列表

常见问题

Q1: 能用App Inventor复制门禁卡吗?

不能。 门禁卡复制需要:专用NFC读写器(如ACR122U)、解密密钥、专用软件。手机NFC硬件不支持写入门禁卡所需的加密扇区。

Q2: 读取NFC时提示”不支持”?

  • 确认手机有NFC硬件(设置→NFC→开启)
  • 部分低价手机没有NFC芯片
  • Android版本需要4.0+

Q3: 读取银行卡安全吗?

只读取UID和非加密数据是安全的。App Inventor无法读取银行卡的加密交易数据。

总结

能力 支持
读取NFC标签UID ✅
读取NDEF数据 ✅
写入NDEF数据 ✅
复制门禁卡 ❌
手机模拟门禁卡 ❌
NFC身份识别 ✅
文档反馈