3
votes

I want to launch my application by scanning an NFC tag containing an Android Application Record. However, this app shouldn't have a launcher icon, so I can't use CATEGORY_LAUNCHER.

My problem is that if I comment out the CATEGORY_LAUNCHER line in the manifest, the app is not launched anymore (a search is performed on Google Play instead):

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="app.my">

    <application android:label="@string/app_name">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <!--<category android:name="android.intent.category.LAUNCHER" />-->
            </intent-filter>
        </activity>
    </application>
</manifest>

I also tried adding the following intent filter but with no luck:

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

What should I do to make it work? Should I add code in MainActivity to handle the NDEF_DISCOVERED intent?

2
Have you checked this link:- Click herePankaj
@Clairvoyant Yes, that's the link I pointed to in my question. But it doesn't explain what exactly should be in activity in the manifest for AAR to work.Bruno Parmentier
Do you know for sure that this is possible? An app that cannot be launched from the launcher sounds like something the system would prevent you from doing. Perhaps you can check for the data that you need, and if it's not there pop up a helpful message to the user and call finish().nasch
What data does your tag contain? Just the AAR or any other NDEF records too?Michael Roland
@MichaelRoland Just the AAR (that I wrote with NdefRecord.createApplicationRecord("app.my")).Bruno Parmentier

2 Answers

1
votes

The typical way to do this is to add another record (MIME type, NFC Forum external type, or URI) to the tag in addition to the Android Application Record (AAR). In that case, the AAR must be the last (or at least not the first) record of the NDEF message on the tag.

You can then catch the tag discovery by filtering for that specific data type (i.e. the type of the first record of the NDEF message on your tag) using the NDEF_DISCOVERED intent filter. E.g. for an NFC Forum external type:

<activity android:name=".MainActivity">
    <intent-filter>
        <action android:name="android.nfc.action.NDEF_DISCOVERED" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:scheme="vnd.android.nfc"
              android:host="ext"
              android:pathPrefix="/yourdomain.com:yourtypename"/>
    </intent-filter>
</activity>

In that case, the AAR will make sure that your app gets precedence over any other apps that registered for the same type and that Play Store is opend for your app if it's not already installed.

If you do not register any activity for a matching NDEF_DISCOVERED intent filter, the AAR will cause the first activity that has a MAIN/LAUNCHER intent filter (in that case Android won't pass a handle to the tag to your activity though). Hence, if you neither register for NDEF_DISCOVERED intents nor for MAIN/LAUNCHER intents, the AAR mechanism won't work.

But what if you want your tag to only contain an AAR and no other records?

You could do this by registering an intent filter for the AAR itself. The AAR is an NFC Forum external type with the type name "urn:nfc:ext:android.com:pkg", so you could use the following intent filter:

<intent-filter>
    <action android:name="android.nfc.action.NDEF_DISCOVERED" />
    <category android:name="android.intent.category.DEFAULT" />
    <data android:scheme="vnd.android.nfc" android:host="ext"
          android:pathPrefix="/android.com:pkg" />
</intent-filter>
1
votes

I got it working by setting a custom mimeType in the intent-filter, like this:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="app.my">

    <application android:label="@string/app_name">
        <activity android:name=".MainActivity">
            <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="application/vnd.app.my" />
            </intent-filter>
        </activity>
    </application>
</manifest>

Then creating an NdefRecord to write on the tag with:

NdefRecord.createMime("application/vnd.app.my", null);

This doesn't take advantage of the AAR which, from what I understand, works at the application level (and not at the activity level) and ensures that only my app can be launched. But I guess that a custom MIME type like this is good enough.