如何正确读取 NFC 标签?什么是"NFC_READ_COMMAND",在哪里可以找到它?



免责声明:我对NFC的东西相当陌生。官方文件让我很困惑。这是一个测试应用程序,了解NFC

所以,我在Android应用程序中有这个活动代码。我希望该活动读取NFC标签(SDK 32)。我没有机会测试它,因为我不知道NFC_READ_COMMAND是什么,因此,我无法编译它。我也不确定如何正确获取数据,我想在"text_view_nfc"显示数据TextView .

我无法编译,因为我不知道NFC_READ_COMMAND是什么。


import com.miguel_rp.nfc_gestor_test.ActividadGestoraDeNFCsBase
import android.app.Activity
import android.nfc.NfcAdapter
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.nfc.Tag
import android.nfc.tech.NfcA
import android.widget.TextView
import kotlin.jvm.internal.Intrinsics
import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import com.miguel_rp.nfc_gestor_test.R
class creador_de_cartas : ActividadGestoraDeNFCsBase() {
override var activity = this as Activity
var text_view_nfc: TextView? = null
private var nfcAdapter: NfcAdapter? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
this.setContentView(R.layout.activity_creador_de_cartas)
text_view_nfc = findViewById(R.id.textViewContenido)
this.nfcAdapter = NfcAdapter.getDefaultAdapter(this)
}

private fun enableForegroundDispatch(activity: AppCompatActivity, adapter: NfcAdapter?) {
val intent = Intent(activity.applicationContext, activity.javaClass)
intent.flags = Intent.FLAG_ACTIVITY_SINGLE_TOP
val pendingIntent = PendingIntent.getActivity(activity.applicationContext, 0, intent, 0)
val filters = arrayOfNulls<IntentFilter>(1)
val techList = arrayOf<Array<String>>()
filters[0] = IntentFilter()
with(filters[0]) {
this?.addAction(NfcAdapter.ACTION_NDEF_DISCOVERED)
this?.addCategory(Intent.CATEGORY_DEFAULT)
try {
this?.addDataType("text/plain")
} catch (ex: IntentFilter.MalformedMimeTypeException) {
throw RuntimeException("e")
}
}
adapter?.enableForegroundDispatch(activity, pendingIntent, filters, techList)
}
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
var tagFromIntent: Tag? = intent?.getParcelableExtra(NfcAdapter.EXTRA_TAG)
val nfc = NfcA.get(tagFromIntent)
val atqa: ByteArray = nfc.getAtqa()
val sak: Short = nfc.getSak()
nfc.connect()
val isConnected= nfc.isConnected()
if(isConnected)
{
val receivedData:ByteArray= nfc.transceive(NFC_READ_COMMAND)
//code to handle the received data
}else{
Log.e("ans", "Not connected")
}
}
override fun onResume() {
super.onResume()
enableForegroundDispatch(this, nfcAdapter)
}
}

如果你想知道,"ActividadGestoraDeNFCsBase"基本上是一个父类,确保NFC在使用应用程序时总是被激活。

package com.miguel_rp.nfc_gestor_test
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.nfc.NfcAdapter
import android.provider.Settings
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import java.util.*
open class ActividadGestoraDeNFCsBase() : AppCompatActivity() {
open lateinit var activity: Activity

companion object {
lateinit var nfcAdapter: NfcAdapter;
var timer = Timer()
fun isNFCEnabled(context: Context, actividad: Activity){
if (!nfcAdapter.isEnabled()) {
actividad.runOnUiThread{
Toast.makeText(context, "Esta aplicación necesita tener el NFC activado", Toast.LENGTH_SHORT).show()
}
val intent = Intent(Settings.ACTION_NFC_SETTINGS)
actividad.startActivity(intent)
}
}
}
override fun onResume() {
super.onResume()
val task = object : TimerTask() {
override fun run() {
isNFCEnabled(applicationContext, activity)
}
}
timer.scheduleAtFixedRate(task, 0, 1000)
}
override fun onPause() {
super.onPause()
timer.cancel()
timer = Timer()
}
}

以防万一,我用的是这个NFC卡:西班牙亚马逊。不好意思

所以很多NFC的东西都是自定义的NFC标签的品牌和型号,幸运的是你的亚马逊链接说你使用NTAG215这是一个NFC Type2标准标签。

这个标签的数据表告诉你所有你需要知道的" nfc_read_command;要读这张卡片

标签可以使用NfcA标准在低电平读取。

维基百科图片很好地概述了NFC中使用的所有标准。

所以从数据表"8.5内存组织"部分;你可以看到这个标签将数据存储在一些4字节的页面中,页面地址从00x00h0x86h开始,对于Ntag 215。

还是从数据表中可以看出,范围开始和结束的一些页面地址具有特定的功能,而有些则是只读的。

正如你所看到的,在NFC中有很多是关于创建和解码字节数组的。

在数据表中转到第10节。NTAG commands"您可以看到这个标签支持的各种命令及其字节值。

其中之一是Read0x30h的命令中,read命令接受第二个参数,该参数是要读取的页面的值。(注意,Java NfcA类处理添加CRC

命令返回一个字节数组,该数组将从给定的起始地址或NAK错误码中读取4页(16字节)的字节。

在你的例子中是"NFC_READ_COMMAND"可以是这样的:-

byteArrayOf(0x30.toByte(), 0x00.toByte())

从第0页开始读取(4字节)(这些地址包含UID, Capability Container和其他东西的数据)

也因为它是NFC类型2兼容,你也可以使用更高级别的NdefNFC数据格式标准来存储和访问数据,如果数据是使用这种格式存储的。

关于如何将Ndef Data存储在Type 2标签上的详细信息请参见http://apps4android.org/nfc-specifications/NFCForum-TS-Type-2-Tag_1.1.pdf

我刚刚重读了代码示例,你使用的指南很奇怪(不是完全错误,但是一种复杂而奇怪的做事方式)

当包含Ndef数据的标签出现时,它使用较旧的、功能较差/可靠的enableForegroundDispatch来获得通知。

但然后假设它是一个NfcA标签,正在存储Ndef数据(在您的情况下,它是NTAG215)

如果>如果一个标签也存储了Ndef Data,但它是一个NfcB标签,你的代码将得到一个空指针异常。

更符合逻辑val nfc = NfcA.get(tagFromIntent)

: -

val ndef = Ndef.get(tagFromIntent)

您可以使用ndef.getNdefMessage()来获取标签上的数据,而不必使用低级命令。

或者当你使用enableForegroundDispatch时,直接从Intent获取Ndef数据。

override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
...
if (NfcAdapter.ACTION_NDEF_DISCOVERED == intent.action) {
intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES)?.also { rawMessages ->
val messages: List<NdefMessage> = rawMessages.map { it as NdefMessage }
// Process the messages array.
...
}
}
}

(取自https://developer.android.com/guide/topics/connectivity/nfc/nfc#obtain-info)

相关内容

  • 没有找到相关文章

最新更新