概述
NFC(近场通信)在门禁卡、公交卡、支付等场景广泛使用。本文说明App Inventor 2中NFC的能力边界和实现方法。
⚠️ 重要限制
App Inventor不能复制门禁卡! 原因:
- 大多数门禁卡使用加密扇区(如Mifare Classic的Key A/B)
- 复制门禁卡需要专门的NFC写入硬件
- Android系统限制了NFC卡模拟的权限
- 这涉及安全和法律问题
App Inventor能做的:
- 读取NFC标签的基本信息(UID、NDEF数据)
- 读取未加密的NFC标签内容
- 写入NDEF数据到可写标签
- 基于NFC标签触发App操作
NFC组件
组件位置
App Inventor没有内置NFC组件,需要使用扩展。推荐:
| 扩展 | 功能 | 来源 |
|---|---|---|
| NFCTools | 读写NFC标签 | 社区 |
| NfcExtension | 基本NFC读取 | GitHub |
| TaifunNFC | 读写+高级功能 | puravidaapps |
添加NFC扩展
- 下载NFC扩展.aix文件
- App Inventor → Designer → Extension → Import Extension
- 选择.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卡 | 完全加密 | ❌ | ❌ |
为什么手机不能当门禁卡?
- 硬件限制:大多数手机的NFC控制器不支持卡模拟模式(Card Emulation)
- 系统限制:Android只允许系统级应用(如Google Pay)进行卡模拟
- 安全密钥:门禁卡的加密密钥不对用户开放
- 部分手机支持:华为、小米等支持模拟未加密的门禁卡,但这不是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身份识别 | ✅ |
扫码添加客服咨询