奇巧支持NFC NDEF吗?



我正在尝试使用运行在KitKat上的MobiPrint设备读取NFC NDEF消息。

我按照文档中的说明做了,但是我似乎不能在Kitkat上使用它。

AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.pos">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.NFC" />
<uses-feature android:name="android.hardware.nfc" android:required="true"/>
<application
android:name=".App"
android:allowBackup="true"
android:fullBackupContent="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.Pos">
<activity
android:name=".ui.views.main.MainActivity"
android:theme="@style/Theme.Pos.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>

<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
</activity>
</application>
</manifest>

MainActivity.kt

class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private var adapter: NfcAdapter? = null
private var pendingIntent: PendingIntent? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
adapter = NfcAdapter.getDefaultAdapter(this)
pendingIntent = PendingIntent.getActivity(this, 0,
Intent(this, javaClass).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0)
}
override fun onResume() {
super.onResume()
adapter?.enableForegroundDispatch(this, pendingIntent, null, null)
}
override fun onPause() {
super.onPause()
adapter?.disableForegroundDispatch(this)
}
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
val rawMessages = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES)
Log.d("NFC_NDEF_MESSAGES", rawMessages.toString())
Log.d("NFC_NDEF_ACTION", intent.action.toString())
}
}
<<p>

Logcat消息/strong>MobiPrint Device with Kitkat:

NFC_NDEF_MESSAGES:nullNFC_NDEF_ACTION:android.nfc.action.TAG_DISCOVERED

S7与棉花糖有活性:

NFC_NDEF_MESSAGES:[Landroid.os.Parcelable;@6405e69NFC_NDEF_ACTION:android.nfc.action.NDEF_DISCOVERED

Kitkat不支持NDEF吗?

NXP MIFARE Classic系列NFC卡不符合NFC论坛标准(该规范早于NFC标准)

因此一些硬件不支持NXP MIFARE经典系列的NFC卡,如果你看Android文档https://developer.android.com/reference/android/nfc/tech/MifareClassic

在Android NFC设备上实现这个类是可选的。如果没有实现,那么MifareClassic将永远不会在tag# getTechList中枚举。如果它被枚举,那么所有MifareClassic I/O操作都将被支持,并且Ndef#MIFARE_CLASSIC Ndef标签也将被支持。在任何一种情况下,NfcA也将在标签上枚举,因为所有MIFARE Classic标签也是NfcA。

所以对这种类型的卡的支持在Android中是可选的,正如它所说的,如果它被支持,那么更高级别的NDEF协议将被支持在它之上(但在你的情况下,它在MifareClassic级别不被支持,那么NDEF将不被支持在顶部)

这可能就是为什么你得到android.nfc.action.TAG_DISCOVERED消息的原因,因为这来自低级别NfcA,这是MifareClassic与其他NFC规范卡的共同之处。

让MobiPrint设备读取NFC标签的解决方案是使用不同的NFC标签,不幸的是,这与Android版本无关(甚至一些后来的Android硬件不会读取它们),我建议使用NFC论坛规范类型的标签。一个接近的匹配是NXP TAG 216卡(NFC论坛类型2)或NXP Desfire (NFC论坛类型4)

出于某种原因,它将其检测为TAG_DISCOVERED(这通常暗示缺少NDEF格式)。即使没有检测到它为MifareUltralight,仍然可以将其用作NfcA,其中CC位于第3页,数据区从第4页开始(无论是否格式化或读取格式)。当标签在以后的Android版本上是可读的,这些标签绝对应该被视为"可读"。

它所需要的只是一个KitKat实现,它处理MifareUltralightNfcA

可以在不检查API级别的情况下退回:

when (intent.action.toString()) {
android.nfc.action.NDEF_DISCOVERED -> {
/* handle NDEF messages (business as usual). */
}
android.nfc.action.TAG_DISCOVERED -> {
/* Check if NDEF format is present and read it. */
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG)
MifareUltralight mifare = MifareUltralight.get(tag)
mifare.connect()
...
mifare.close()
/* When MifareUltralight is null, try NfcA: */
// NfcA nfcA = NfcA.get(tag)
}
else -> {
print("unknown intent action")
}
}

MifareUltralight知道页面,NfcA相当低级,只知道ByteArray的有效载荷。
与其建议不同的标签(这可能会触发相同的Intent,这只需要相应地处理),不如提高minApiLevel并完全停止支持KitKat (Intent仍然可能被空标签触发)。我将有NTAG216和至少一个物理API 22设备-查看它将实际触发哪个Intent,但没有时间。我们需要一个物理API 19设备来正确地复制它。

最新更新