Besides introducing the famous ARKit, Apple made a former private API usable in every App with iOS 11: CoreNFC. CoreNFC allows reading NFC tags with your iPhone 7/7+ and maybe soon with your iPhone 8 ;) And of course the Xamarin team has worked hard to make it usable with C#. In this blog post I’ll show you how to quickly read a message from a NFC tag formatted in NDEF.
Setup
Development environment
Because iOS 11 is still beta, the setup up effort is a bit higher. You can skip this if Apple and Xamarin have released the stable verions.
- Download and install XCode 9 beta 6
- Download and install the Xamarin release for XCode 9 support here and read carefully!
App Identifier
Unfortunately, you can’t just use the API with any App. You have to enable the NFC Tag Reading
feature in your developer account.
- Go to developer.apple.com and sign into your developer account
- Open App IDs
- Create a new Explicit App ID e.g.
com.smstuebe.test.nfc
(Wildcard App IDs don’t allow enabling this feature) - check
NFC Tag Reading
and continue - make sure the App ID is included in a provisioning profile
Project
In your iOS project you have to add some more stuff.
Info.plist
In your Info.plist file you have to set the CFBundleIdentifier
and add the NFCReaderUsageDescription
.
Entitlements.plist
Add the following lines to the Entitlements.plist file. Because we want to read Tags using the NDEF format, we add NDEF
to the com.apple.developer.nfc.readersession.formats
.
Code
Finally, the setup is done. Coding will be much easier :) You can easily asyncify the API by using a TaskCompletionSource
.
NFCNdefReaderSession
is the class that handles the reading of NDEF tags. It creates a system dialog (see Test section) when calling BeginSession()
. This dialog isn’t customizable, yet. Because of my experiences with the fingerprint API, I think Apple will add some possibilities for customization (mainly localizing the shown texts) in later releases.
You can read a single tag or multiple tags in one session. The 3rd constructor parameter invalidateAfterFirstRead
is set to true, because we want to read just one tag.
The AsyncNfcReader
implements the INFCNdefReaderSessionDelegate
and thats why it inherits from NSObject
. In the DidDetect
we read the message from the first record. In my case the Record is of type T
. This means the first 3 bytes contain the Encoding and the language. In the interests of simplification I just ignore the first 3 bytes with Skip(3)
and decode the remaining bytes as UTF8 string. The format is specified in the NDEF specification. There are libraries like NDEF NFC that allow decoding the payload correctly.
You can use the AsyncNfcReader
like this in your code:
Test
For testing I bought some NFC tags with 4kB storage and wrote some data to it with an Android App. Simply start the App and scan the tag. The antenna is located at the upper egde of your iPhone.
Discussion
- Error handling and decoding is very sloppy. This has to be hardened in production apps.
- The documentation from Apple isn’t complete. The API supports other formats than NDEF (e.g. ISO15693).
- The API doesn’t seem to support writing tags (06.09.2017)
- I started implementing a Plugin for reading NFC tags. I’ll publish it in the next months after the features are available in the stable releases.
Found a typo? Send me a pull request!