Pages

Tuesday, January 15, 2013

How to: Receive NFC data in an Adobe AIR Android app

Getting NFC data into an Adobe AIR for Android application is much easier than it might seem. At least, it's a lot easier than I thought it would be.

I'm currently working on an app that has just such a need. Specifically, users will run the AIR app and then swipe their device over a physical display that has some NFC tag hotspots. The app needs to receive the NFC data from each tag and react in a specific fashion. I didn't know much about NFC data when I began working on this current app, and since AIR doesn't have official support for NFC I figured I would need a native extension to properly handle things.

It turns out it is *much* simpler than needing to implement any sort of native functionality. All you have to do is add the proper intent handling to the "manifestAdditions" portion of the AIR application xml. I'll put a sample xml block here, and then explain it:


The key to making everything work is in effect "extending" the <application> node - which prior to discovering this I didn't know was possible. By adding the appropriate NFC intent filter information - the "default" way you handle NFC data in Android - the AIR application is handed the day the same way any other Android application would be.

In the xml sample above, I have  my AIR app responding to a URI. I've got placeholders for the scheme and host attribute values. Most commonly these will represent a web URL; in that case scheme would be "http" and host would be the domain - "yourdomain.com". But if you want to use proprietary data, you can do that too. Scheme and host can be anything. Scheme could be "my" and host could be "uri.value" which would represent "my://uri.value." It doesn't really matter, the data will make it to the AIR app. This is just one way of targeting NFC data into an app - there are a number of different ways to use intent filters in Android to target varied NFC data types. Virtually all of them should work as manifest extensions for an AIR app. The Android documentation has information about targeting NFC data here.

Extending the manifest only gets us so far; it doesn't tell us how the data gets into the AIR application. Thankfully, Adobe has facilitated that too. Anytime the app responds to intent filter data, an InvokeEvent.INVOKE event gets fired. Check out the below class:

To be clear, the invoke event will in fact be fired when the app starts up, but will *also* be fired whenever the NFC intent data qualifies and is passed to the app. This means that the app will be handed any and all relevant NFC data and can respond by reading the events.arguments data.

This also has the added effect of launching your AIR application whenever the relevant NFC data is swiped. That's actually what Android generally means to have happen with NFC data - the user swipes their device and the relevant specific application is opened. This will in fact do that. But as this post discusses, it will also pass in the NFC data while the application is running.

If you aren't wanting the app to be launched on NFC data but instead *only* respond to the NFC data while the application is open, that requires more complexity. It does, in fact require a native extension interacting with something called the "Foreground Dispatch". A very intelligent person has actually cracked the code and has made, well, the source code available for free! You can see it here:

http://code.google.com/p/ane-lab/source/browse/#svn%2Ftrunk%2Fmobile%2Fandroid%2Fjava%2Fnfc-foreground-dispatch

I hope this helps!

4 comments:

  1. Hi,
    I've tested this routine in a lot of different ways but I can´t get it to work. If I try to add plain text to the tag and use the text filter on the intent I get no data. If I try with your fiter and add an uri to the tag my phone leaves the application and opens a browser instead. Do you now what I might do wrong?

    Best regards
    /magnus

    ReplyDelete
    Replies
    1. Interestingly, prior to finding what this post is about, I had been playing with plain text too -- but not in an AIR app, just a normal Android app. I couldn't even get an Android app to get the plain text. The galaxy s3 I was testing on wanted to open some other default app. There has to be a way - the app "TagWriter" can override default plain text reception; but it seems Android is a bit odd with that.

      With regards to your URI option, are you separating out your URI parts? Like scheme should be "http" and host would be "yourdomain.com". If you are doing that, I seem to remember reading somewhere that perhaps the browser on some devices doesn't want to give up rights to web URIs easily. In that case you'd have to use that "foreground dispatch" option I list above so that your app can have full control of the NFC data coming into the device.

      But, I guess I'd want to know what your app is doing? If you have control over what data you're sending into your app, you should just use some fully custom URI like host="custom", scheme="myapp.uri/somecustomvalue". That is the case I'm working with and it works like a charm.

      Don't forget to add the proper permissions to your manifest as well! In fact, maybe I should add that to my post too...it's kind of important!

      Delete
  2. Lovely! In future reference i really bookmark your blog! Thank you so much for sharing this one NFC App such a Great concept for work in this field, Thanks again all Kind of peaceful info,Love it- NFC App Development

    ReplyDelete
  3. I truly cherished perusing your site. It was exceptionally very much created and simple to undertand. Not at all like extra web journals I have perused which are truly not tht great. I additionally discovered your posts exceptionally fascinating. Actually in the wake of understanding, I needed to go demonstrat to it to my companion and he ejoyed it also! RFID tags

    ReplyDelete