Scanning
Tags
NFC tags come in a wide array of technologies and can also have data written to them in many different ways. Android and iOS has the most support for the NDEF standard, which is defined by the NFC Forum.
NDEF data is encapsulated inside a message (NdefMessage
) that contains one or more records (NdefRecord
). Each NDEF record must be well-formed according to the specification of the type of record that you want to create.
Events
Your application will get notified about NFC tag detection events via the NFCEvent
. This is independent of the mode. The most relevant event is the NFCEvent.ACTION_NDEF_DISCOVERED
which is dispatched whenever an applicable NDEF NFC tag is detected.
The NFCEvent
will contain a Tag
object in the tag
variable. This contains all the information available about the detected tag, including NdefMessage
s and NdefRecord
s contained in the tag.
- AIR
- Unity
NFC.service.addEventListener( NFCEvent.ACTION_NDEF_DISCOVERED, discoveredHandler );
function discoveredHandler( event:NFCEvent ):void
{
trace( "discoveredHandler" );
for each (var message:NdefMessage in event.tag.messages)
{
for each (var record:NdefRecord in message.records)
{
trace( "\t"+record.toString() + "::"+record.payload.toString() +" url:"+record.url );
}
}
}
NFC.Instance.OnNdefDiscovered += Instance_OnNdefDiscovered;
void Instance_OnNdefDiscovered(NFCEvent e)
{
Debug.Log("Instance_OnNdefDiscovered");
foreach (NdefMessage message in e.tag.messages)
{
foreach (NdefRecord record in message.records)
{
Log(" record.payload: " + record.payload);
}
}
}
NdefRecord
Payload
The payload of the records contains data in a specific format.
- AIR
- Unity
The payload in an NdefRecord
is encoded as a ByteArray
.
If you are expecting ascii string data you can just read the data using toString()
, eg:
var record:NdefRecord = ...;
var payloadAsString:String = record.payload.toString();
The payload in an NdefRecord
is encoded as a hexidecimal string
.
Records are actually byte data the payload which we read as hex string array to ensure it is passed from the native layer in the same format across platforms.
To convert it to a byte array:
public static byte[] StringToByteArray(string hexString)
{
byte[] bytes = new byte[hexString.Length / 2];
for (int i = 0; i < hexString.Length; i += 2)
{
bytes[i / 2] = System.Convert.ToByte(hexString.Substring(i, 2), 16);
}
return bytes;
}
If you are expecting ascii string data you can take this further:
public static string StringToASCII(string hexString)
{
try
{
string ascii = string.Empty;
for (int i = 0; i < hexString.Length; i += 2)
{
byte val = System.Convert.ToByte(hexString.Substring(i, 2), 16);
char character = System.Convert.ToChar(val);
ascii += character;
}
return ascii;
}
catch (Exception ex) { Console.WriteLine(ex.Message); }
return string.Empty;
}
Modes
There are two modes of scanning for tags, which we reference as:
- "dispatch mode", where you are listening for system dispatched events;
- "reader mode", where you are actively reading tags;
Both are very similar, and will communicate via the same events as above. The main differences being that:
- reader mode active reads tags and can read a tag multiple times if required, however;
- reader mode mode interferes with other NFC functionality disabling any peer-to-peer (Android Beam) and card-emulation modes of the NFC adapter on this device;
- reader mode is only available while your application is active, i.e only dispatch mode supports background scanning and launching your application from a tag.
As a general rule, you should use dispatch mode, unless you really need to read a tag multiple times.
There is also no reason that you can't combine the two, using dispatch mode to register your application for launches from tags and using reader mode to actively scan while your application is in use.