Android Question Read NFC tags without external intent

Pxs

Member
Licensed User
Hello
I'm trying to programmatically disable NFC intent handling when my app is not open.

Ideally, when the app is closed, the external NFC intent in the manifest should be handled only if a specific option is set , ignored otherwise. When the app is open and in the foreground, the user is actively using the app so all intents should be handled.

Reading around seems like the new way to do this is by using enableReaderMode (lets you set a callback in another thread) instead of the old enableForegroundDispatch.

Is this possible in B4x?
 

drgottjr

Expert
Licensed User
Longtime User
study this post:

somewhere in there is a link to a project that uses enablereadermode. if that's what you think you have to have.

i don't know how you've set up your app and exactly what you mean by "options", but i don't think you need enablereadermode
to do what you're looking to do. and depending on how you've set up your app, using enablereadermode may not help.

enableForegroundDispatch only guarantees that if your app is running in the foreground it will receive any tag discovery attempt
(even if there are other apps on the device that might take precedence). it has nothing to do with whether your app is
launched when a tag is discovered. for that matter, neither does enablereadermode.

in theory, you set up the conditions under which your app is launched when a tag discovery is made. if other apps have done
likewise, your app and the others will be suggested by the os to handle the discovery. if your app happens to satisfy uniquely
the discovery (or if your app is the only way), you get the call. so, nothing to do with enableforegrounddispatch or enablereadermode.
if you've set the manifest up, enableforegrounddispatch and enablereadermode are irrelevant.

the conditions under which your app is called are detailed in your manifest. this is discussed at length in android's nfc documentation
and in multiple SO postings. you don't indicate whether you already have this set up or not. it's not too complicated, and it works.

a typical example would be:
XML:
AddPermission(android.permission.NFC)
AddActivityText(main,<intent-filter>
    <action android:name="android.nfc.action.NDEF_DISCOVERED" />
    <category android:name="android.intent.category.DEFAULT" />
    <data android:scheme="http" />
    <data android:scheme="https" />
</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.NDEF_DISCOVERED" />
    <category android:name="android.intent.category.DEFAULT" />
    <data android:scheme="geo" />
</intent-filter>
<intent-filter>
    <action android:name="android.nfc.action.TECH_DISCOVERED" />
    <category android:name="android.intent.category.DEFAULT" />
 </intent-filter>
<meta-data android:name="android.nfc.action.TECH_DISCOVERED"
    android:resource="@xml/nfclist2" />
<intent-filter>
    <action android:name="android.nfc.action.TAG_DISCOVERED" />
    <category android:name="android.intent.category.DEFAULT" />
</intent-filter>
)

basically, these are the conditions under which i want my app to be launched.

note the line: android:resource="@xml/nfclist2" />

you set "nfclist2" (or any name you want) in your res/xml folder.
if you don't have an xml folder, make one.

"nfclist2" (or whatever name you choose) looks like this:
XML:
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
    <tech-list>
        <tech>android.nfc.tech.NfcA</tech>
    </tech-list>
</resources>

android's documentation and SO posts will explain more. it's all spelled out.
to be on the safe side, the xml folder and nfclist2 (or whatever name you choose)
should be read only. i think the compiler may clobber them otherwise. i forget.
 
  • Like
Reactions: Pxs
Upvote 0

Pxs

Member
Licensed User
Thanks for the detailed and exhaustive reply!

My app already uses the filter xml and successfully launches upon a correct nfc intent.
The problem is how this works with OTHER apps that do not ( they work with nfc, same tag technology, but do not open from intent )

What ends up happening is, my clients often have both apps installed (with workflow demanding use of both), and my app (being the only one registered in Android to handle nfcv) is automatically opened everytime a tag is detected, stealing the foreground. It gets annoying very quickly.

So, because i cant control how the other apps behave, i'm trying to to "put a toggle" on this behaviour, so that the user can disable the intent handling code in the manifest.

I'll play around with the example Erel posted, not sure if it can solve my problems, but looks very interesting!
 
Upvote 0

drgottjr

Expert
Licensed User
Longtime User
good luck with enablereadermode.

your annoyance notwithstanding, if - on a device with multiple nfc tag-reading apps - your app is
the only one that can be launched when a tag is discovered, then your app will be launched.

it sounds to me like your manifest is too inclusive. you shouldn't,
eg, respond to ndef tags unless you're telling the app to respond
in your manifest. the filtering is designed to handle levels of
discovery recognition.

in my case, i want my app to be launched in the event of any
tag discovery. of course, "competing" apps want the same thing,
hence, the os's providing a choice to the user when a tag is
discovered. to stand a fighting chance when the list of possible
apps is shown to the user, i have to cover as many eventualities as i can.

if no apps on the device handle, eg, ndef tag discovery (and nfc is
turned on), then android will handle the event (assuming a recent
device).

i haven't see your manifest, but i would think that if you limit it
to tech_discovered and specify nfcv in your nfclist2 file, you
would only be launched in that case. which, as i understand things,
is what you want.

if, what you're saying is you want to be launched and then decide
if you actually wanted to handle the event (and exit if not), you
can easily do that already. where that leaves the user is unclear.
but what you can't do is make that decision without being launched
in the first place. (tag handling must be done from the foreground).

even if you set some background thread in motion
(via enablereadermode) to monitor events, it still would have
required your app's having been launched first to set the thread
in motion, running the risk of being killed by the os (and not
being restarted).
 
Upvote 0
Top