高级 NFC 概览
作者:互联网
高级 NFC 概览
本文介绍了各种高级 NFC 主题,例如如何使用各种标签技术、如何写入 NFC 标签以及如何执行前台调度(借助前台调度,在前台运行的应用即使在其他应用过滤某些 Intent 时也能优先处理这些 Intent)。
使用支持的标签技术
将 NFC 标签与 Android 设备结合使用时,用于读取和写入标签数据的主要格式是 NDEF。当设备扫描具有 NDEF 数据的标签时,Android 会尽可能在解析消息和通过 NdefMessage
传递该消息方面提供支持。不过,在某些情况下,您扫描的标签可能不包含 NDEF 数据,或者 NDEF 数据无法映射为 MIME 类型或 URI。在这些情况下,您需要直接开启与标签的通信,并使用自己的协议(以原始字节形式)对标签执行读写操作。Android 通过 android.nfc.tech
软件包对这些用例提供一般性支持,如表 1 所述。您可以使用 getTechList()
方法确定标签支持的技术,还可以使用 android.nfc.tech
提供的一个类来创建相应的 TagTechnology
对象。
类 | 说明 |
---|---|
TagTechnology |
这是所有标签技术类都必须实现的接口。 |
NfcA |
提供对 NFC-A (ISO 14443-3A) 属性和 I/O 操作的访问权限。 |
NfcB |
提供对 NFC-B (ISO 14443-3B) 属性和 I/O 操作的访问权限。 |
NfcF |
提供对 NFC-F (JIS 6319-4) 属性和 I/O 操作的访问权限。 |
NfcV |
提供对 NFC-V (ISO 15693) 属性和 I/O 操作的访问权限。 |
IsoDep |
提供对 ISO-DEP (ISO 14443-4) 属性和 I/O 操作的访问权限。 |
Ndef |
提供对 NDEF 格式的 NFC 标签上的 NDEF 数据和操作的访问权限。 |
NdefFormatable |
为可设置为 NDEF 格式的标签提供格式化操作。 |
Android 设备还可以选择支持以下标签技术。
类 | 说明 |
---|---|
MifareClassic |
提供对 MIFARE Classic 属性和 I/O 操作的访问权限(如果此 Android 设备支持 MIFARE)。 |
MifareUltralight |
提供对 MIFARE Ultralight 属性和 I/O 操作的访问权限(如果此 Android 设备支持 MIFARE)。 |
将标签技术和 ACTION_TECH_DISCOVERED Intent 结合使用
当设备扫描包含 NDEF 数据但无法映射为 MIME 或 URI 的标签时,标签调度系统会尝试使用 ACTION_TECH_DISCOVERED
Intent 来启动 Activity。在扫描到包含非 NDEF 数据的标签时,也会使用 ACTION_TECH_DISCOVERED
。如果标签调度系统无法解析标签数据,此回退功能可让您直接处理标签数据。使用标签技术的基本步骤如下:
- 过滤一个
ACTION_TECH_DISCOVERED
Intent,指定您要处理的标签技术。如需了解详情,请参阅过滤 NFC Intent。通常,如果 NDEF 消息无法映射为 MIME 类型或 URI,或者扫描到的标签不包含 NDEF 数据,那么标签调度系统会尝试启动ACTION_TECH_DISCOVERED
Intent。如需详细了解具体的确定方式,请参阅标签调度系统。 - 应用收到 Intent 时,会从该 Intent 获取
Tag
对象: KotlinJava
-
var tagFromIntent: Tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG)
- 通过调用
android.nfc.tech
软件包中类的get
工厂方法,获取TagTechnology
的实例。您可以枚举支持的标签技术,只需在调用get
工厂方法之前调用getTechList()
即可。例如,要从Tag
获取MifareUltralight
的实例,请执行以下操作: KotlinJava
-
MifareUltralight.get(intent.getParcelableExtra(NfcAdapter.EXTRA_TAG))
对标签执行读写操作
对 NFC 标签执行读写操作涉及从 Intent 获取标签以及开启与标签的通信。您必须定义自己的协议栈才能读写标签数据。不过,请注意,在直接处理标签时,您仍然可以读写 NDEF 数据,具体取决于您要如何设计其结构。下面的示例展示了如何使用 MIFARE Ultralight 标签。
KotlinJavapackage com.example.android.nfc
import android.nfc.Tag
import android.nfc.tech.MifareUltralight
import java.io.IOException
import java.nio.charset.Charset
class MifareUltralightTagTester {
fun writeTag(tag: Tag, tagText: String) {
MifareUltralight.get(tag)?.use { ultralight ->
ultralight.connect()
Charset.forName("US-ASCII").also { usAscii ->
ultralight.writePage(4, "abcd".toByteArray(usAscii))
ultralight.writePage(5, "efgh".toByteArray(usAscii))
ultralight.writePage(6, "ijkl".toByteArray(usAscii))
ultralight.writePage(7, "mnop".toByteArray(usAscii))
}
}
fun readTag(tag: Tag): String? {
return MifareUltralight.get(tag)?.use { mifare ->
mifare.connect()
val payload = mifare.readPages(4)
String(payload, Charset.forName("US-ASCII"))
}
}
}
}
使用前台调度系统
借助前台调度系统,Activity 可以拦截 Intent 并声明自己可优先于其他 Activity 处理同一 Intent。使用此系统涉及为 Android 系统构造一些数据结构,以便将合适的 Intent 发送到您的应用。要启用前台调度系统,请执行以下操作:
- 在 Activity 的
onCreate()
方法中添加以下代码:- 创建一个
PendingIntent
对象,这样 Android 系统会使用扫描到的标签的详情对其进行填充。 KotlinJava
- 创建一个
-
val intent = Intent(this, javaClass).apply {
addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)
}
var pendingIntent: PendingIntent = PendingIntent.getActivity(this, 0, intent, 0)
- 声明 Intent 过滤器,以处理您要拦截的 Intent。前台调度系统会对照设备扫描标签时所获得的 Intent 来检查所指定的 Intent 过滤器。如果匹配,那么应用会处理该 Intent。如果不匹配,那么前台调度系统会回退到 Intent 调度系统。指定 Intent 过滤器和技术过滤器的
null
数组,以指明要过滤所有回退到TAG_DISCOVERED
Intent 的标签。以下代码段会处理NDEF_DISCOVERED
的所有 MIME 类型。您应只处理需要的内容。 KotlinJava -
val ndef = IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED).apply {
try {
addDataType("*/*") /* Handles all MIME based dispatches.
You should specify only the ones that you need. */
} catch (e: IntentFilter.MalformedMimeTypeException) {
throw RuntimeException("fail", e)
}
}
intentFiltersArray = arrayOf(ndef)
- 设置应用要处理的一组标签技术。调用
Object.class.getName()
方法以获取要支持的技术的类。 KotlinJava -
techListsArray = arrayOf(arrayOf<String>(NfcF::class.java.name))
-
- 替换以下 Activity 生命周期回调,并添加相应逻辑,以分别在 Activity 失去 (
onPause()
) 焦点和重新获得 (onResume()
) 焦点时启用和停用前台调度。enableForegroundDispatch()
必须从主线程调用,并且只能在 Activity 在前台运行时调用(在onResume()
中调用可确保这一点)。您还需要实现onNewIntent
回调以处理扫描到的 NFC 标签中的数据。
public override fun onPause() {
super.onPause()
adapter.disableForegroundDispatch(this)
}
public override fun onResume() {
super.onResume()
adapter.enableForegroundDispatch(this, pendingIntent, intentFiltersArray, techListsArray)
}
public override fun onNewIntent(intent: Intent) {
val tagFromIntent: Tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG)
//do something with tagFromIntent
}
如需查看完整示例,请参阅 API 演示中的 ForegroundDispatch 示例。
Content and code samples on this page are subject to the licenses described in the Content License. Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates.
Last updated 2019-12-27 UTC.
标签:调度,NFC,标签,概览,高级,NDEF,DISCOVERED,Intent 来源: https://www.cnblogs.com/jiftle/p/16508340.html