免责声明:我对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字节的页面中,页面地址从00x00h
到0x86h
开始,对于Ntag 215。
还是从数据表中可以看出,范围开始和结束的一些页面地址具有特定的功能,而有些则是只读的。
正如你所看到的,在NFC中有很多是关于创建和解码字节数组的。
在数据表中转到第10节。NTAG commands"您可以看到这个标签支持的各种命令及其字节值。
其中之一是Read在0x30h
的命令中,read命令接受第二个参数,该参数是要读取的页面的值。(注意,Java NfcA类处理添加CRC
读命令返回一个字节数组,该数组将从给定的起始地址或NAK错误码中读取4页(16字节)的字节。
在你的例子中是"NFC_READ_COMMAND"可以是这样的:-
byteArrayOf(0x30.toByte(), 0x00.toByte())
从第0页开始读取(4字节)(这些地址包含UID, Capability Container和其他东西的数据)
也因为它是NFC类型2兼容,你也可以使用更高级别的Ndef
NFC数据格式标准来存储和访问数据,如果数据是使用这种格式存储的。
关于如何将Ndef Data存储在Type 2标签上的详细信息请参见http://apps4android.org/nfc-specifications/NFCForum-TS-Type-2-Tag_1.1.pdf
我刚刚重读了代码示例,你使用的指南很奇怪(不是完全错误,但是一种复杂而奇怪的做事方式)
当包含Ndef数据的标签出现时,它使用较旧的、功能较差/可靠的enableForegroundDispatch
来获得通知。
但然后假设它是一个NfcA
标签,正在存储Ndef数据(在您的情况下,它是NTAG215)
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)