This posts introduces Near Field Communication (NFC), its Modes, the Android APIs that can be used to deal with NFC tags and the mysterious NDEF Format (NDEFMessages, NDEFRecord, RTC, TNF, etc.).
Not all Android-based smartphones support NFC, actually the list is limited to Nexus S, Galaxy S II, Xperia Acro, Lg LU6200, Acer Liquid express, Sony Nozomi, Nexus Prime, LG Gelato nfc, etc.
The NFC API was introduced with Android 2.3 (API 9, Dec. 2010) on Nexus S. A more complete API was released win Android 2.3.3 (API 10, Feb. 2011). This API provides tools for detecting TAGs, reading infromation stored on the tag and writing information, and also communicating with other NFC tags. These operations are also called modes:
Here is a typical manafest file for an application that want to use the Android NFC API:
Android Manifest
To read a tag it is easy: unlock phone, touch tag, most likely the intent chooser will open.
For text or any other mime type:
Tech discovered
In the manifest
Tag Technologies maps to tech specifications or to pseudo-technologie or capabilities like NDEF or NDEFFormatable.
NdefRecord
Reading Tag Content
Direct Start
1. Write custom NDEF MIME-type media messages
2. Use custom IntentFilter to blind to your messages
Writing NDEF MIME
Create NDEF Message which is pushed to another active device once the other device is close
Not all Android-based smartphones support NFC, actually the list is limited to Nexus S, Galaxy S II, Xperia Acro, Lg LU6200, Acer Liquid express, Sony Nozomi, Nexus Prime, LG Gelato nfc, etc.
The NFC API was introduced with Android 2.3 (API 9, Dec. 2010) on Nexus S. A more complete API was released win Android 2.3.3 (API 10, Feb. 2011). This API provides tools for detecting TAGs, reading infromation stored on the tag and writing information, and also communicating with other NFC tags. These operations are also called modes:
- Peer-to-Peer Mode: limited support on Android
- Reader/Writer Mode: excellent support
- Card Emulation Mode: no support
Here is a typical manafest file for an application that want to use the Android NFC API:
Android Manifest
//NFC Permission <uses-permission android:name="android.permission.NFC" /> //API Level <uses-sdk android:minSdkVersion="10" /> //NFC Feature <uses-feature android:name="android.hardware.nfc" android:required="true" /> <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name=".NfcRWActivity" android:label="NfcRWActivity"> <intent-filter> <action android:name="android.nfc.action.NDEF_DISCOVERED" /> <data android:mimeType="application/json" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity> </application>NFCManager used to get the NFCAdapter the real thing that control Foreground Dispatch and P2P NDEF Push, check if NFC is turned on
NfcManager nfc_manager = (NfcManager) getSystemService(NFC_SERVICE); NFCAdapter nfc_adapter = nfc_manager.getDefaultAdapter();
To read a tag it is easy: unlock phone, touch tag, most likely the intent chooser will open.
Foreground Dispatch System
Foreground Dispatch allows the declaration of the currently active application as prioritar for handling the tags read by user. Thus the Foreground Activity may redirect all intents related to tag, technology or NDEF discovery to itself.nfcAdapter.enableForegroundDispatch(activity, pendingIntent, intentFiltersArray, techListsArray); pi = PendingIntent.getActivity(activity, 0, new Intent(activity, activity.getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0); IntentFilter ndef = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED); ndef.addDataType("*/*"); intentFiltersArray = new IntentFilter[] { ndef }; techListsArray = new String[][] {new String[] { NfcA.class.getName() } };Don't forget to enable in onResume(), disable in onPause(). The tag can be read in onNewIntent().
@Override protected void onResume() { super.onResume(); nfcAdapter.enableForegroundDispatch(this, pi, intentFiltersArray, techListsArray); } @Override protected void onPause() { super.onPause(); nfcAdapter.disableForegroundDispatch(this); } @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); tag.getId() //returns id as byte[] String techs[] = tag.getTechList(); for (String tech: techs) { if (tech.equals("android.nfc.tech.Ndef")) { Ndef ndef = Ndef.get(tag); ndef.getType(); ndef.getMaxSize(); ndef.canMakeReadOnly(); ndef.isWritable(); NFCUtil.printNdefMessageDetails(ndef.getCachedNdefMessage()); } } }
Intent Dispatch System
Ndef discoveredFor text or any other mime type:
<intent-filter> <action android:name="android.nfc.action.NDEF_DISCOVERED"/> <data android:mimeType="text/plain"/> <category android:name="android.intent.category.DEFAULT"/> </intent-filter>For url:
<intent-filter> <action android:name="android.nfc.action.NDEF_DISCOVERED"/> <data android:scheme="http" android:host="www.r0ly.fr"/> <category android:name="android.intent.category.DEFAULT"/> </intent-filter>
Tech discovered
In the manifest
<intent-filter> <action android:name="android.nfc.action.TECH_DISCOVERED"/> </intent-filter> <meta-data android:name="android.nfc.action.TECH_DISCOVERED" android:resource="@xml/techlist"/>In the xml/techlist.xml file:
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <tech-list> <tech>android.nfc.tech.IsoDep</tech> <tech>android.nfc.tech.MifareClassic</tech> </tech-list> </resources>
Tag Technologies maps to tech specifications or to pseudo-technologie or capabilities like NDEF or NDEFFormatable.
- TagTechnology The interface that all tag technology classes must implement.
- NfcA Provides access to NFC-A (ISO 14443-3A) properties and I/O operations.
- NfcB Provides access to NFC-B (ISO 14443-3B) properties and I/O operations.
- NfcF Provides access to NFC-F (JIS 6319-4) properties and I/O operations.
- NfcV Provides access to NFC-V (ISO 15693) properties and I/O operations.
- IsoDep Provides access to ISO-DEP (ISO 14443-4) properties and I/O operations.
- Ndef Provides access to NDEF data and operations on NFC tags that have been formatted as NDEF.
- NdefFormatable Provides a format operations for tags that may be NDEF formattable.
- MifareClassic Provides access to MIFARE Classic properties and I/O operations, if this Android device supports MIFARE.
- MifareUltralight Provides access to MIFARE Ultralight properties and I/O operations, if this Android device supports MIFARE.
NdefRecord
Reading Tag Content
//r = NdefRecord if (r.getTnf() == NdefRecord.TNF_ABSOLUTE_URI) { b.append(String.format("TNF_ABSOLUTE_URI: type(%1$s), id(%2$s), payload(%3$s)\n", new String(r.getType()), idBytes.toString(), new String(r.getPaylod()))); } else if (r.getTnf() == NdefRecord.TNF_MIME_MEDIA) { b.append(String.format("TNF_MIME_MEDIA: type(%1$s), id(%2$s), payload(%3$s)\n", new String(r.getType()), idBytes.toString(),new String(r.getPayload()))); }
What to listen for?
The following figure depicts how the precedent intent related to tag reading are dispatch, so if you want your application to:- receive a notification about a tag been read while your app is in foreground, then you should use for enableForegroundDispatch.
- receive a notification even if it is not the foreground app, then register for NDEF_DISCOVERED.
- receive a notification when the tag is of a specific technology TECH_DISCOVERED.
- otherwise you should register for TAG_DISCOVERED.
Tag dispatch |
1. Write custom NDEF MIME-type media messages
2. Use custom IntentFilter to blind to your messages
Writing NDEF MIME
NdefMessage msg = NFCUtil.getNdefMimeMessage("application/json", "{\"key\":\"value\"}"); Intent i = new Intent(this, WriteActivity.class); i.putExtra(WriteActivity.NDEF_MESSAGE, msg); startActivity(i);
private static NdefRecord getMimeRecord(String mimeType, String content) { NdefRecord record = new NdefRecord(NdefRecord.TNF_MIME_MEDIA, mimeType.getBytes(), getRandomIdBytes(), content.getBytes()); return record; }
Ndef ndef = Ndef.get(tag); if (ndef.isWritable() && ndef.getMaxSize() > this.msg.toByteArray().length) { ndef.connect(); ndef.writeNdefMessage(this.msg); ndef.close(); } else { // do something }P2P: NDEF Push
Create NDEF Message which is pushed to another active device once the other device is close
NfcAdapter.enableForegroundNdefPush(activity, ndefmessage); NfcAdapter.disableForegroundNdefPush(activity);
Aucun commentaire:
Enregistrer un commentaire