【问题标题】:Not proper action shown for NFC intents未针对 NFC 意图显示正确的操作
【发布时间】:2014-07-17 09:26:20
【问题描述】:

我正在处理配备 Android NFC 的设备,只是试图读取标签并从 Activity 接收信息。标签的类型为MifareUltralight。只是在Android docs 中阅读了该案例,似乎我首先必须在清单文件中注册 Intent 以启动我的 Activity,然后我才能从中接收 NFC Intent。这就是我的清单文件的样子:

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

    <uses-feature android:name="android.hardware.nfc" android:required="false" />
    <uses-permission android:name="android.permission.NFC" />

    <application
        android:allowBackup="true"
        android:label="Test">

        <activity
            android:name="com.mycompany.android.activities.NfcTestActivity"
            android:launchMode="singleTop"
            android:label="Test">
            <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.TECH_DISCOVERED"/>
            </intent-filter>
            <meta-data android:name="android.nfc.action.TECH_DISCOVERED"
                android:resource="@xml/nfc_tech_filter" />
            <intent-filter>
                <action android:name="android.nfc.action.TAG_DISCOVERED"/>
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

    </application>

</manifest>

我将 nfc 功能设置为不需要,因为这对我的应用程序运行来说不是必需的。关于 NFC 技术过滤器,这是我的 nfc_tech_filter.xml 文件:

<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
    <tech-list>
        <tech>android.nfc.tech.IsoDep</tech>
        <tech>android.nfc.tech.NfcA</tech>
        <tech>android.nfc.tech.NfcB</tech>
        <tech>android.nfc.tech.NfcF</tech>
        <tech>android.nfc.tech.NfcV</tech>
        <tech>android.nfc.tech.Ndef</tech>
        <tech>android.nfc.tech.NdefFormatable</tech>
        <tech>android.nfc.tech.MifareClassic</tech>
        <tech>android.nfc.tech.MifareUltralight</tech>
    </tech-list>
</resources>

好吧,配置完成后,我的NfcTestActivity 似乎应该能够接收 NFC Intent。我就是这样实现的:

public class NfcTestActivity  extends Activity {

    final String TAG = NfcTestActivity.class.getSimpleName();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.i(TAG, "IntentAction (onCreate): " + getIntent().getAction());
        NfcManager manager = (NfcManager) getSystemService(Context.NFC_SERVICE);
        NfcAdapter adapter = manager.getDefaultAdapter();
        if (adapter != null && adapter.isEnabled()) {
            Log.i(TAG, "NFC adapter is enabled");
        } else {
            Log.i(TAG, "NFC adapter is disabled");
        }
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        Log.i(TAG, "IntentAction (onNewIntent): " + getIntent().getAction());
    }

    @Override
    public void onResume() {
        super.onResume();
        Log.i(TAG, "IntentAction (onResume): " + getIntent().getAction());
    }

}

当我启动应用程序时,我会得到以下日志:

05-28 10:41:52.044  31182-31182/com.mycompany.android I/NfcTestActivity? IntentAction (onCreate): android.intent.action.MAIN
05-28 10:41:52.054  31182-31182/com.mycompany.android I/NfcTestActivity? NFC adapter is enabled
05-28 10:41:52.054  31182-31182/com.mycompany.android I/NfcTestActivity? IntentAction (onResume): android.intent.action.MAIN

后来,我阅读了我的标签并显示了此日志:

05-28 10:41:59.661  31182-31182/com.mycompany.android I/NfcTestActivity? IntentAction (onResume): android.intent.action.MAIN

这意味着读取标签时会调用Activity#onResume 方法,正如文档所述,但是,我在这里得到的是android.intent.action.MAIN 而不是NFC 方法(ACTION_NDEF_DISCOVEREDACTION_TECH_DISCOVERED 或@987654327 @)。

此外,作为线索,当我从我的 Activity 声明中删除这段代码时,当我阅读标签时不会出现 onResume 日志:

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

看来TAG_DISCOVERED 动作肯定是以某种方式启动的,而不是其他方式,但我无法从活动中正确捕获它。

有人知道吗?

【问题讨论】:

    标签: android android-intent nfc intentfilter


    【解决方案1】:

    首先,您的 nfc_tech_filter.xml 不正确。过滤器

    <tech-list>
        <tech>android.nfc.tech.IsoDep</tech>
        <tech>android.nfc.tech.NfcA</tech>
        <tech>android.nfc.tech.NfcB</tech>
        <tech>android.nfc.tech.NfcF</tech>
        <tech>android.nfc.tech.NfcV</tech>
        <tech>android.nfc.tech.Ndef</tech>
        <tech>android.nfc.tech.NdefFormatable</tech>
        <tech>android.nfc.tech.MifareClassic</tech>
        <tech>android.nfc.tech.MifareUltralight</tech>
    </tech-list>
    

    表示您要匹配IsoDep NfcA NfcB NfcF and ... 但是,NfcX 标签技术是相互排斥的(NdefNdefFormatable 也是如此),因此过滤器不会匹配任何标签。你真正想要的是这样的:

    <tech-list>
        <tech>android.nfc.tech.NfcA</tech>
    </tech-list>
    <tech-list>
        <tech>android.nfc.tech.NfcB</tech>
    </tech-list>
    <tech-list>
        <tech>android.nfc.tech.NfcF</tech>
    </tech-list>
    <tech-list>
        <tech>android.nfc.tech.NfcV</tech>
    </tech-list>
    

    这将与 任何 标记技术相匹配。或者如果你只想匹配MifareUltralight,你可以简单地使用:

    <tech-list>
        <tech>android.nfc.tech.MifareUltralight</tech>
    </tech-list>
    

    使用 TAG_DISCOVERED 意图过滤器通常不是一个好主意。它只是作为一种备用方案,并与第一个 Android NFC API 向后兼容。

    如果您想在应用处于前台时接收 NFC 意图,通常最好注册 foreground dispatch system,而不是依赖应用清单中的意图过滤器。这将确保您的 Activity 接收事件,并且即使其他应用也具有这些事件的 Intent 过滤器,也不会显示任何 Activity 选择器。

    【讨论】:

    • 非常感谢您的回答 ;-) 它向我阐明了技术过滤的概念。这似乎绝对是问题的关键。
    【解决方案2】:

    经过一番头脑风暴,我意识到默认 android.nfc.action.TAG_DISCOVERED 而不是 android.nfc.action.NDEF_DISCOVERED 对我有用:

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

    当我的标签类型被TECH_DISCOVERED 覆盖时,我仍然不知道为什么我应该使用TAG_DISCOVERED,这是最好使用的。无论如何,这就是我稍后用来获取标签 ID 的代码:

    @Override
    public void onResume() {
        super.onResume();
        Log.d(TAG, "onResume: action-"+getIntent().getAction());
        if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(getIntent().getAction())) {
            Tag tag = getIntent().getParcelableExtra(NfcAdapter.EXTRA_TAG);
            String tagId = bytesToHexString(tag.getId());
            Log.i(TAG, "NFC tag: " + tagId);
        }
    }
    

    另请参阅:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多