If you’ve got an NFC sensor on your phone or tablet then there is a reasonable chance you’ve played around with apps like Trigger, which perform various actions on your device when you wave it over NFC tags in stickers or on key fobs etc. after a bit of setup.
So, for example, you could have an NFC sticker by the front door that has been coded by Trigger to turn off Wi-Fi and Bluetooth. With a variety of of NFC tags around and about you can set up your phone how you need it when you need it by a simple wave, avoiding a whole lot of fiddling about in the device settings.
Anyway, that’s one application of NFC tags. There are, of course, plenty more.
Indeed there have been a good number of questions in various forums asking how to get programmable NFC support in Delphi. Of course NFC is not currently “wrapped up” by Delphi’s RTL so up until now it’s been in the hands of the “creative”.
NFC tag scanning support in Android falls into 2 areas:
- You install an app that advertises that it can respond to some NFC tag content. When the device is waved against such a tag the app can be automatically launched. If more than 1 app is registered Android will initially launch a chooser dialog to allow the user to pick the app they require.
Actually this support is easy enough to do in Delphi so long as you can locate a suitable import unit or two containing the required Android APIs for NFC. - You run an app that permits the user to scan NFC tags while it is in the foreground and it directly responds to any scanned tags.
This seems to be more commonly required in commercial applications and alas is much more difficult to achieve with Delphi. It falls into the category of problem that requires some Java smarts and some command prompt hackery to achieve.
Bummer.
Anyway, I was recently looking into writing some NFC support, given the frequency of questions being asked. Part way through my research I discovered that Daniel Magin was simultaneously trying to do the same thing, primarily for a talk at Delphi Tage.
I helped Daniel out with the Java callback and command-line building trickery – that seems to be an area where I can readily add value to Android low level chicanery – and he helped me out overcoming a nasty crash bug with Java arrays of NFC data records not being surfaced correctly by the Delphi RTL.
In the end we both had some sample apps that permit NFC scanning and also, just as an added bonus, NFC writing!
You can find my solutions written up in quite some detail here:
- NFC support in Delphi XE5
- NFC support in Delphi XE6
- NFC support in Delphi XE7 and XE8
- NFC support in Delphi 10 Seattle and Delphi 10.1 Berlin
Daniel’s efforts will also be made available very soon.
Enjoy coding up your NFC apps, everyone!
Update - Dec '15
A number of people had tried to use the code on versions of Android more recent than was current when I worked all this and hit problems with the code crashing. This was down to some inappropriate use of JNI constructs where the problem didn't originally show up but did show up as later versions of Android got more picky about things. I've remedied this issue in 2 ways.
1) I've updated the samples and code snippet in the article (it's OnNewIntentNative that has changed, FYI, in its usage of the intent JNI value).
2) However I've also devised a different sample app (for XE7, XE8 and 10 Seattle) that does much the same thing but doesn't really use explicit JNI. Instead it uses a listener interface implemented in Delphi and called from Java. The app has been slightly extended to allow the NFC support to be toggle on and off via a checkbox.
Updated samples:
Update – Sep ‘16
While catching up on what’s new in recent releases of Delphi I realised a change had been snuck into Delphi 10 Seattle that makes the whole NFC exercise much more straightforward now in Delphi. No more Java required! No more activity subclassing! No more debugging challenges!
It turns out that the key activity callback that NFC foreground dispatch relies upon (Activity.onNewIntent) is now hookable from Delphi code (with the right know-how) and so all the Java shenanigans can be put behind us (at least in the context of NFC access).
I have updated the article to show the more direct means of accessing NFC from Delphi 10 Seattle and later and provided corresponding updated samples for Delphi 10 Seattle and Delphi 10.1 Berlin.
Not found - 404
ReplyDeleteURL requested (/Articles/Articles/DelphiXE6NFC/NFC.htm) not found
Lol. What a rookie mistake
DeleteFixed now!
Go it:
ReplyDeletehttp://blong.com/Articles/DelphiXE7NFC/NFC.htm
Thanks for posting the correction Robert. I fixed the post now.
Deletei prepared parallel with brian the nfc stuff. my article is now also online:
ReplyDeletehttp://www.danielmagin.de/blog/index.php/2014/09/nfc-android-application-with-delphi-xe6-and-xe7/
Thanks for posting the link Daniel.
DeleteYour comment on problems with the Delphi RTL not being able to surface Java array of NFC records seem to gel with my G+ comment nearly a year ago regarding issues with Java arrays.
ReplyDeleteChewy, quite possibly, though the details of a conversation from that long ago escape me now :o)
DeleteYou might be interested in this request of mine:
ReplyDeletehttps://quality.embarcadero.com/browse/RSP-9715
If I could get onto the web site I'd take a look :-/
DeleteHello Brian, I'm developing a app based on your code, i made some modifications to read and write Mifare Classic cards. When i test in your app everything works and i can read and write the cards, but when i run in my app the app fail to start when i change the AndroidManifest. Can you give me some ligth?!! thanks in advance,
ReplyDeleteHello Laurence. First thing to do is run the Android SDK log utility by running monitor.bat or ddms.bat (they are in the Android SDK directory tree) and see what the log says about the failure to start. It should give a clue.
DeleteHello Brian, Your code works fine, but if I try to install the app on a device with no NFC support, the Application crashes. I'm using the Nfc as a login so in case of no NFC support, the user could enter something like a password. WHat can I do to prevent the crash in that case?
ReplyDeleteHi Gianluca. It's a good question that I hadn't considered. I'd need to look at such a scenario to see *why* it is failing in that manner, but I assume I have a lack of defensive coding somewhere along the line, making too many assumptions. I'm unlikely to be able to check this out in the immediate short-term future, but hopefully that gives you a clue where to look. If I get a handle on the problem, I'll update the blog post.
DeleteDear Brian,
ReplyDeleteI use Delphi XE7 and I were bult your sample NFC project to my porject. Whewn I want to run my project on an NFC phone it wokrs fine. But if I want to run a phone what doesn't has NFC my app has stopped after the splash screen.
Hello Arpad, see my reply to Gianluca just above
DeleteHello Brian, I succesfully installed the example on foreground dispatch on my nexus 7 (2013) with android 5.0.2. Compiled with XE7 Update1.
ReplyDeleteIf i scan a tag when the program is active the program crashes.
I receive the following message in the debug log: "W/InputEventReceiver(15107): attempted to finish an input event but the input event receiver has already been disposed".
Hello. I haven't got Android 5 on any of my devices yet, but I know it impacts the JNI bridge stuff notably, hence the (currently beta) fix for FMX and Lollipop (http://cc.embarcadero.com/item/30110).
DeleteI see this download now has source/headers in so I can potentially see what changes have been made to support Lollipop.
In short, I'm *guessing* your crash may be more to do with running code on a Lollipop device than not having followed the steps, and my code doesn't take Lollipop into account.
It would be a useful exercise to see if installing that beta fix (on a VM snapshot or something) helped improve the situation.
I use XE7 and Mobile Android 5.0.
ReplyDeleteUse Delphi XE7 NFC support Code
Touch NFC, The program will close
I would like to ask how to deal with this issue.
Thank you!
So you're saying with Android 5, as soon as you engage with an NFC tag the app closes unexpectedly? Have you installed Embo's Lollipop fix? http://cc.embarcadero.com/item/30110
DeleteDefinitely try that, If that doesn't help, you'll need to use DDMS or Monitor (from Android SDK) to look at logcat messages to get an inkling as to what the crash relates to, I'd imagine.
Thank you for your reply.
Deletehttp://cc.embarcadero.com/item/30110 I have installed,but Touch NFC, The program will close.
My Mobile Sony Z2 Android 5.0.2. XE7 up1
Use you Delphi XE7 NFC support
I did not modify the program
The program will close.
I would like to try to identify the problem,but I have insufficient capacity.
If I open the program will crash with NFC sensors
DeleteTouch NFC, The program will close
But if I can run directly sensing NFC induction program and will open
But only once
When the program opens after they die
I think it might be related with NFC android Beam
DeleteI did hear people saying that on Android 5.x, code that references fully qualified Android classes needs to now use a '/' instead of a '.' to separate the different parts of the class name.
DeleteMaybe that might help?
I haven't seen the issue, so it's tricky for me.
From the comments it doesn't look like you've examined the logcat messages in monitor/DDMS. They may be instructive.
I have 2 devices running greater than Android 5.X. On the initial read, it works great. but then requires the user to exit the application in order to get any further reads. Somehow every subsequent read (I think) is reloading the application and trying to access NFC. I don't know if that helps.
DeleteRather late I know, but I sorted out that issue. Probably irrelevant for many of you, but the issue turned out to be the way I was using JNI code in the sample, which in later versions of Android started failing, but was fine in earlier versions.
DeleteI've updated the samples and the snippet of code in the articles. If you pull down the current sample and do a compare with the original version (or just check out OnNewIntentNative in the article) you pulled down, you should see the subtle change in the use of the JNIObject parameter.
There's also an additional example that doesn't really use JNI at all - it uses a listener interface, which is a neat way round the problem.
Apologies for not getting to this sooner.
Brian, I am fairly certain now that it is a Android 5.x issue. I've run the same set of test APKs on both styles 4.4 and 5.X and 5.X has an issue getting the second intent in the same application or getting an intent in an already running app.
ReplyDeleteDuly noted, Mary. I'll re-run the sample on my 5.0.2 device, though I am reasonably confident it was at 5.0.2 the last time I tried.
DeleteI'll see what happens though.
Rather late I know, but I sorted out that issue. Probably irrelevant for many of you, but the issue turned out to be the way I was using JNI code in the sample, which in later versions of Android started failing, but was fine in earlier versions.
DeleteI've updated the samples and the snippet of code in the articles. If you pull down the current sample and do a compare with the original version (or just check out OnNewIntentNative in the article) you pulled down, you should see the subtle change in the use of the JNIObject parameter.
There's also an additional example that doesn't really use JNI at all - it uses a listener interface, which is a neat way round the problem.
Apologies for not getting to this sooner.
Same problem, android 5 (samsung s5 stock rom)
ReplyDeleteRather late I know, but I sorted out that issue. Probably irrelevant for many of you, but the issue turned out to be the way I was using JNI code in the sample, which in later versions of Android started failing, but was fine in earlier versions.
DeleteI've updated the samples and the snippet of code in the articles. If you pull down the current sample and do a compare with the original version (or just check out OnNewIntentNative in the article) you pulled down, you should see the subtle change in the use of the JNIObject parameter.
There's also an additional example that doesn't really use JNI at all - it uses a listener interface, which is a neat way round the problem.
Apologies for not getting to this sooner.
I brian, si there some information to implement nfc on IOS devices?
ReplyDeleteHi Carlos, unfortunately I haven't done much on iOS lately, so I don't have any information on surfacing NFC support. It's one of the many things I hope to get onto as and when the current workload dies down, but I am unaware of when this will be.
Delete