2. Présentation
• Olivier GONTHIER
o Etudiant 5A à l'ESIEA
o Développeur chez SMS-BACKING
o Portfolio : r0ly.fr
o Twitter : @rolios
A la recherche d'un stage de fin d'études…
3. Plan
• Etat de l’art
• NFC sur Android
1) Présentation API
2) Permissions requises
3) "Foreground dispatch system"
4) "Intent dispatch system"
NDEF discovered
Tech discovered
Tag discovered
5) Data
Lecture
Ecriture
Peer to peer
• Conclusion
5. Etat de l'art
• Sur Android, une dizaine d'appareils (Nexus S, Galaxy S II,
Xperia Acro, Lg LU6200, Acer Liquid express, Sony Nozomi,
Nexus Prime, LG Gelato nfc, ...)
• Les prochains blackberry
• Iphone 5 ?
• Nokia N9 sous meego
• Nokia-6131 ( le premier téléphone nfc) , nokia C7
• Windows phone 7: peu probable pour le moment
7. Présentation API
• Introduit avec Android 2.3 et le Nexus S
• Première API nfc avec Android 2.3 (API 9, Décembre 2010)
Très limitée
• API complète avec Android 2.3.3 (API 10, Février 2011)
• Fournit des outils pour détecter les Tags, lire ou écrire le
contenu de ces tags, et communiquer avec d'autres puces
NFC
9. Permissions requises
• Pour utiliser le nfc:
<uses-permission android:name="android.permission.NFC" />
• Pour n'apparaître sur l'android market que pour les devices
ayant une puce nfc:
<uses-feature android:name="android.hardware.nfc" android:required="true" />
• Pour définir le niveau d'api nécessaire:
<uses-sdk android:minSdkVersion="10"/>
11. Foreground dispatch system
Permet de déclarer l’application active comme prioritaire pour le traitement des tags
pi =
PendingIntent.getActivity(this, 0, new Intent(this,getClass()).addFlags(Intent.FLAG_ACTI
VITY_SINGLE_TOP) , 0);
ndef = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
try{
ndef.addDataType("text/plain");
}catch (MalformedMimeTypeException e) {
Log.e("NfcForecast", e.getMessage());
}
intentFiltersArray = new IntentFilter[] {ndef};
techList = new String[][]{new String[] {NfcA.class.getName() }};
12. Foreground dispatch system
@Override
protected void onResume() {
super.onResume();
adapter.enableForegroundDispatch(this, pi, intentFiltersArray, techList);
}
@Override
protected void onPause() {
super.onPause();
adapter.disableForegroundDispatch(this);
//ne pas oublier de désactiver quand l’application est suspendue
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
//Reaction
}
14. Ndef discovered
LE NFC SUR ANDROID
4 - I N T E N T D I S PAT C H S Y S T E M
15. NdefDiscovered
• Pour du texte, ou autre type mime :
<intent-filter >
<action android:name="android.nfc.action.NDEF_DISCOVERED"/>
<data android:mimeType="text/plain"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
• Pour une 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>
16. Tech discovered
LE NFC SUR ANDROID
4 - I N T E N T D I S PAT C H S Y S T E M
17. Présentation des technologies
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.
18. Tech discovered
• Dans le 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"/>
• Dans un fichier xml/techlist.xml:
<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>
19. Tag discovered
LE NFC SUR ANDROID
4 - I N T E N T D I S PAT C H S Y S T E M
20. Tag discovered
Dans le manifest:
<intent-filter>
<action android:name="android.nfc.action.TAG_DISCOVERED"/>
</intent-filter>
Moins fréquent, surtout si d'autres applications nfc sont installées.
22. Récupérer la référence du tag
• Si on utilise le dispatch system:
@Override
protected void onResume() {
super.onResume();
Intent i = this.getIntent();
if(i.getAction().equals(NfcAdapter.ACTION_NDEF_DISCOVERED))
Tag tagFromIntent = i.getParcelableExtra(NfcAdapter.EXTRA_TAG);
}
• Si on utilise le foreground system:
@Override
protected void onNewIntent(Intent i) {
super.onNewIntent(intent);
if(i.getAction().equals(NfcAdapter.ACTION_NDEF_DISCOVERED))
Tag tagFromIntent = i.getParcelableExtra(NfcAdapter.EXTRA_TAG);
}
24. Récupérer les NdefMessage
Les tags contiennent un ensemble de NdefMessage qui contiennent les données.
public NdefMessage[] getNdefMessages(Intent intent){
NdefMessage[] messages=null;
Parcelable[] rawMsgs =
intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
if (rawMsgs != null) {
messages = new NdefMessage[rawMsgs.length];
for (int i = 0; i < rawMsgs.length; i++) {
messages[i] = (NdefMessage) rawMsgs[i]; }
} else { // Type du tag inconnu
byte[] empty = new byte[] {};
NdefRecord record = new NdefRecord(NdefRecord.TNF_UNKNOWN, empty,
empty, empty);
NdefMessage msg = new NdefMessage(new NdefRecord[] {record});
messages = new NdefMessage[] {msg};
}
return messages; }
25. NdefRecord
Chaque NdefMessage contient un ensemble de NdefRecord.
Chaque NdefRecord est composé de :
_ un id : byte[] id = record.getId();
_ un TypeNameFormat : short tnf = record.getTnf();
_ un type: byte[] type = record.getType();
_ un payload = byte[] payload = record.getPayload();
Problème: Il faut "décoder" les informations.
26. Récupérer les NdefRecords
public NdefRecord[][] getNdefRecords(NdefMessage[] msgs) {
NdefRecord[][] records=null;
if(msgs!=null){
records = new NdefRecord[msgs.length][];
for(int i=0; i<msgs.length; i++){
records[i]= new NdefRecord[msgs[i].getRecords().length];
records[i]= msgs[i].getRecords(); }
}
return records;
}
27. Décodage, byte[ ] to String
new String(byte[]) est déconseillé, car l'encodage peut varier.
Une solution :
String getTextData(byte[] payload) {
try {
String texteCode = ((payload[0] & 0200) == 0) ? "UTF-8" : "UTF-16";
int langageCodeTaille = payload[0] & 0077;
return new String(payload, langageCodeTaille + 1, payload.length -
langageCodeTaille - 1, texteCode);
}
catch(UnsupportedEncodingException e){
Log.e("NfcReaderActivity", e.getMessage());
return null;
}
}
29. Instancier un NdefRecord
NdefRecord createRecord(String message) {
byte[] langBytes =
Locale.ENGLISH.getLanguage().getBytes(Charset.forName("US-ASCII"));
byte[] textBytes = message.getBytes(Charset.forName("UTF-8"));
char status = (char) (langBytes.length);
byte[] data = new byte[1 + langBytes.length + textBytes.length];
data[0] = (byte) status;
System.arraycopy(langBytes, 0, data, 1, langBytes.length);
System.arraycopy(textBytes, 0, data, 1 + langBytes.length,
textBytes.length);
return new NdefRecord(NdefRecord.TNF_WELL_KNOWN,
NdefRecord.RTD_TEXT, new byte[0], data);
}
30. Ecrire le tag
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
try{
NdefRecord[] records = {createRecord("Test Message")};
NdefMessage message = new NdefMessage(records);
Ndef ndef = Ndef.get(tag);
ndef.connect();
ndef.writeNdefMessage(message);
ndef.close();
}(...)
32. Peer to peer
Moyen de communication intéressant : envoie continuellement des NdefMessage.
public void onResume() {
super.onResume();
if (mAdapter != null)
mAdapter.enableForegroundNdefPush(this,myNdefMessage);
}
public void onPause() {
super.onPause();
if (mAdapter != null)
mAdapter.disableForegroundNdefPush(this);
}
34. Conclusion
Points importants à retenir :
• Etre le plus précis possible pour la récupération des tags : définir la
technologie attendue ainsi que son contenu
• Pour la lecture, faire attention au décodage
• Pour l’écriture, bien construire son NdefRecord