Search code examples
androidandroid-intentnfcintentfilterndef

Android NFC Intent-filter for all type


I would like to create an Android app that handle all of the NFC event like NDEF, TECH and TAG discovered for all categories and all data types.

These intent filters are in my Android Manifest file:

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

This code works when the event is TAG_DISCOVERED. NDEF_DISCOVERED don't call my app.

Can anyone spot what I'm doing wrong?


Solution

  • Your intent filter

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

    does not make much sense due to the fact how intent dispatching for NFC works (see How NFC Tags are Dispatched to Applications)

    1. TAG_DISCOVERED (when used in the manifest) will only ever be fired if no app is registered for a TECH_DISCOVERED or NDEF_DISCOVERED intent that matches the tag. Hence, if you also intend to register your app to handle all TECH_DISCOVERED and NDEF_DISCOVERED intents, there is typically no need to also register for TAG_DISCOVERED.

    2. The NDEF_DISCOVERED intent filter requires (on many platform versions/devices, optional on some) an additional data type that you want to listen for (see <data ... />). There is no such thing as a catch-all NDEF_DISCOVERED intent filter (though you can get close to that by using TECH_DISCOVERED for Ndef and NdefFormatable technologies). NDEF_DISCOVERED will only match the most specific intent filter. For example, if you register for all URLs that start with "http://", any app that registers for URLs starting with "http://www.example.com/" will get precedence over your app. Thus, you would need to register for an endless number of data types in order to get precedence over all other apps.

    3. The TECH_DISCOVERED intent filter requires an additional definition of tag technologies that you want to listen for (see LaurentY's answer). The available technologies are those in the namespace android.nfc.tech.*, currently:

      android.nfc.tech.IsoDep
      android.nfc.tech.MifareClassic
      android.nfc.tech.MifareUltralight
      android.nfc.tech.Ndef
      android.nfc.tech.NdefFormatable
      android.nfc.tech.NfcA
      android.nfc.tech.NfcB
      android.nfc.tech.NfcBarcode
      android.nfc.tech.NfcF
      android.nfc.tech.NfcV
      

      You specify them in an XML file. For instance, to match all NfcA and all NfcB tags, you could use this in a file called xml/nfc_tech_filter.xml:

      <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
          <tech-list>
              <tech>android.nfc.tech.NfcA</tech>
          </tech-list>
          <tech-list>
              <tech>android.nfc.tech.NfcB</tech>
          </tech-list>
      </resources>
      

      You can then attach this XML file using the <meta-data> tag (within the <activity> tag but outside the <intent-filter> tag:

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