NFC 标签有 UID/serial 编号,但 getByteArrayExtra returns 为空

NFC tag has UID/serial number but getByteArrayExtra returns null

当我被要求对它进行更改以读取 NFC 标签的唯一序列号时,我正在开发一个处于最后阶段的应用程序。没什么大问题,但是对于某些标签,序列号返回为空。

当使用 NFC Tools 应用程序检查标签时,序列号在那里,但 intent.getByteArrayExtra() 方法使用 NfcAdapter.EXTRA_ID 作为参数调用 returns null那些标签。

下面是我的 Android 清单和我用来获取 UID 的代码(如果有帮助的话)。

@Override
protected String doInBackground(Tag... params) {
    Tag tag = params[0];

    // New code to deal with multiple tag versions (supports NfcA, NDEF, MifareUltralight)

    // parse tech list
    byte[] uid = getIntent().getByteArrayExtra(NfcAdapter.EXTRA_ID);

    String serialNumber = uidByteToHexString(uid);

    if (serialNumber != null && !serialNumber.isEmpty()) {
        return serialNumber;
    }

Android 清单

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="myPackageName here" >

    <!-- Application permissions go here, mainly NFC -->
    <uses-permission android:name="android.permission.NFC" />
    <users-feature android:name="android.hardware.nfc" android:required="true"/>

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MyActivityNameHere"
            android:configChanges="orientation|keyboardHidden|screenSize"
            android:label="@string/app_name"
            android:theme="@style/FullscreenTheme" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>

            <!-- NFC Intent Filters -->
            <intent-filter>
                <action android:name="android.nfc.action.TECH_DISCOVERED" />
                <category android:name="android.intent.category.DEFAULT" />
            </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>

            <intent-filter>
                <action android:name="android.nfc.action.TAG_DISCOVERED" />
                <category android:name="android.intent.category.DEFAULT"/>
            </intent-filter>

            <meta-data android:name="android.nfc.action.TECH_DISCOVERED"
                android:resource="@xml/nfc_tech_filter" />
        </activity>
    </application>

</manifest>

我的另一个问题是:读取标签时,某些标签会触发选择器对话框,让我选择要使用哪个应用程序来处理标签。是否可以消除它并让我的应用程序在它处于活动状态时处理 NFC 事件?

我使用的标签是NfcA、MifareUltralight和Ndef。如果有帮助。

getIntent().getByteArrayExtra(NfcAdapter.EXTRA_ID) returns null时,这意味着getIntent()不是NFC意图。鉴于您发布的清单(并假设上述代码用于 MyActivityNameHere),这意味着 getIntent() 为您提供启动器意图(具有类别 LAUNCHER 的操作 MAIN)或显式意图)。

通常,这可能有两个原因:

  • 您的 activity 是通过单击其启动器图标(或从另一个 activity/component)启动的。您后来扫描了一个 NFC 标签,并且该事件是通过 onNewIntent() 方法传递的(例如,因为您注册了前台调度系统)但您没有使用 [=16= 更新 activity 的意图字段].在这种情况下,getIntent() 仍将 return 最初启动 activity 的意图,而不是您稍后收到的 NFC 意图。

  • NFC 标签包含 Android 应用程序记录 (AAR),但其第一条记录不是 text/plain 记录。由于您的 NDEF_DISCOVERED 意图过滤器需要 text/plain NDEF 记录作为第一个记录,Android 不知道您的 activity 支持该类型的标签,因此使用 MAIN 启动您的应用程序+LAUNCHER 意图而不是 NFC 意图。因此,此 Intent 既不包含标签 ID 也不包含标签句柄。

您可以使用 intent.getAction() 检查意图的类型。对于 NFC 意图,这将 return

之一
  • android.nfc.action.NDEF_DISCOVERED,
  • android.nfc.action.TECH_DISCOVERED,或
  • android.nfc.action.TAG_DISCOVERED.

关于意向选择器对话框,我建议您通读 How NFC Tags are Dispatched to Applications。本文档详尽地解释了应用程序如何获得 NFC 意图的优先权。