首页 > 解决方案 > Kitkat 是否支持 NFC NDEF?

问题描述

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

我按照Docs中的说明进行操作,但似乎无法让它在 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())
    }
}

Logcat 消息

带有 Kitkat 的 MobiPrint 设备:

NFC_NDEF_MESSAGES:null NFC_NDEF_ACTION:android.nfc.action.TAG_DISCOVERED

S7 Active 与棉花糖:

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

Kitkat 不支持 NDEF 吗?

标签: androidnfcandroid-4.4-kitkatndef

解决方案


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

因此,某些硬件不支持 NXP MIFARE Classic 系列 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 Forum 规范类型的标签。NXP TAG 216 卡(NFC 论坛类型 2)或 NXP Desfire(NFC 论坛类型 4)是最接近的匹配项


推荐阅读