Jean-François GARREAU
-
Consultant IT chez SQLI
-
Développeur Android à mes heures perdues
-
Un des membres fondateur du GDG Nantes
-
Créateur de CineShowTime
@gdgnantes / @binomed / @uncle_bens1
@gdgnantes / @binomed / @uncle_bens1
Qu’est ce que le NFC ?
Etat de l’art
Petit retour sur le NFC
Normes
Théories et normes associées
Usage
Qu’est ce qu’on peut faire avec du NFC
Démos
Une petite démo
Implémentation
Concrètement comment ça s’implémente ?
Nfa : Nfc For Android
Présentation de la librairie
Conclusion
Liens
NFC = Near Field Communication ou Communication en champ proche
Interaction / sélection physique
2004
Nokia, Philips et Sony créent le NFC Forum (aujourd’hui 140 sociétés). La mission est d’assurer une uniformité entre les différents acteurs
2006
Premières spécifications pour les tags NFC Premier téléphone NFC : Nokia 6131
2009
Apparition du standard P2P (communication pair à pair) entre 2 périphériques (non existant en RFID).
2010
Premier téléphone NFC Android : Samsung Nexus S avec une api associée
Le NFC est basé sur le RFID = Radio Frequency Identification
Distance Tag / Lecteur = jusqu'à 10aines de mètres !
Technologies éprouvée : premier brevet en 1983
Fréquence 13,56MHz pour des communications < 1m
Norme ISO 18092
SmartCard : carte à puces
NFC = extension de SmartCard, standardisant l’utilisation de celles-ci à travers la communication RFID
=> Norme ISO 14443-4 est la norme standardisant l’utilisation sans contact d’une SmartCard
RFID : Distance de pls mètres
→ Fréquence 13.56Mhz pour com < 1m
NFC pour SmartCard = NFC standard de smartCard pour la communication RFID
3 modes de communications :
Emulation de carte
Lecture / écriture
Pair à Pair
Normes Régies par le NFC Forum !
Emulation= Simulation interface carte à puce
Lecture / Ecriture : Tag
Pair à Pair : 2 Appareils
Norme ISO 14443
2 types de ISO 14443 :
Half-duplex : Communication dans les 2 sens mais chacun son tour. FullDuplex : Com 2 sens simultanément
NfcA : Modulation sur 100% -1 pour 0 après 1, 0 pour 0 après 0, 1 pour 1 après 0 ou 1
NfcB : Modulation sur 10%
Felica (NfcF dans Android)
ISO 15693 (NfcV dans Android)
Felica : Pas ISO mais NFC-Forum : Japon
15693 : ISO mais pas NFC-Forum
Le NFC forum prévoit 4 types de tags (gestion des données dans la mémoire et interface de commande)
NfcA = Type 1 / 2 / 4
NfcB = Type 4
NfcF = Type 3
Type | Taille Mémoire | Type Communication | Tags possibles |
---|---|---|---|
Type 1 |
96bits → 2Kbits |
ISO 14443-A |
Topaz |
Type 2 |
48bits → 2Kbits |
ISO 14443-A |
Mifare Ultra Light |
Type 3 |
? → 1Mbits |
Felica |
Felica |
Type 4 |
? → 32Kbits |
ISO 14443 A ou B |
DesFire ISO 14443-A |
Le format contient une en-tête qui permet de connaître le contenu du TAG, de le bloquer
Un message NDEF = 1 ou N Ndef records
Types prédéfinis
Texte brut, URI, …
Format d'échange standard
But des types = Gain de place
Header = informations sur le tag
Sa place dans le message
Son type
Sa taille
Payload = données
MB = 1 ⇒ début de message | ME = 1 ⇒ Message fini dans le message
IL : si à 1 : ID Length et ID devront être remplis
Taille du Type dans le payload : En Octet
Détail du type contenu dans le message : lié au TNF. TNF = premier type, Vrai type dans le payload ! ⇒ taille à préciser
Indique la taille du message en octet. Ce champ peut contenir de 1 ou 4 octets
La taille varie à cause du champ SR (Short Record)
Octet Type
Sert à gagner encore plus de bits
0x00 : pas de préfixe
0x01 : http://www.
0x03 : http://
0x05 : tel:
0x06 : mailto:
0x1D : file://
0x24...0xFF : réservés pour un usage futur
Le payload Varie en fonction du WKT
Pour les Uris : il y en a 35 !
SmartPoster contient dans son payload le nouvel enregistrement et les données annexes
Définition de son propre type !
Filtrer le message et donc ouvrir le message à partir d’une application précise
Infos complementaires sur des produits /////// GEOLOC /////// URLS
Codes promos ////// Dématérialisation de cartes
Echange de contacts ///// Echange de fichiers ////// Configuration bluetooth
Paiement securise
Authentification sur des reseaux securise
Depuis 2010 : Lecture / Ecriture de tags
Depuis 2011 : Beam
Depuis 2012 : Partage de médias
IL n’y a pas que le NDEF de reconnu !
Message transformé en Intent
AndroidManifest.xml
Ajout de l’autorisation
<uses-permission android:name="android.permission.NFC"/>
Ajout de la restriction aux téléphones ayant une puce nfc
<uses-feature android:required="true" android:name="android.hardware.nfc"/>
Ajout de la version minimum android
<uses-sdk android:minSdkVersion="10" />
On peut filtrer les tags en fonction
De la technologie Du Mime Type
<uses-permission android:name="android.permission.NFC"/>
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:scheme="http" android:host="sqli.com"/>
</intent-filter>
Interception du dispatch
@Override
protected void onCreate(Bundle savedInstanceState) {
…
mAdapter = NfcAdapter.getDefaultAdapter(this);
resoudreIntent(getIntent());
}
@Override
protected void onResume() {
super.onResume();
…
mAdapter.enableForegroundDispatch(this, pendingIntent, filters, techs);
}
@Override
protected void onPause() {
…
mAdapter.disableForegroundDispatch(this);
super.onPause();
}
On lit l’information depuis un intent
private void resoudreIntent(Intent intent) {
String action = intent.getAction();
if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) {
Parcelable[] rawMsgs = intent.getParcelableArrayExtra(
NfcAdapter.EXTRA_NDEF_MESSAGES);
NdefMessage[] messages;
NdefRecord record = null;
if (rawMsgs != null) {
messages = new NdefMessage[rawMsgs.length];
for (int i = 0; i < rawMsgs.length; i++) {
messages[i] = (NdefMessage) rawMsgs[i];
for (int j = 0; j < messages[i].getRecords().length; j++) {
record = messages[i].getRecords()[j];
…
}
}
}
}
}
Il faut créer un NDefMessage
String uri = "sqli.com";
byte[] uriField = uri.getBytes();
byte[] payload = new byte[uriField.length + 1];
payload[0] = 0x03;
System.arraycopy(uriField, 0, payload, 1, uriField.length);
NdefRecord record = new NdefRecord(NdefRecord.TNF_WELL_KNOWN,
NdefRecord.RTD_URI,
new byte[0],
payload);
NdefMessage msg = new NdefMessage(new NdefRecord[]{record});
Puis l’écrire sur un tag (à la détection du tag : Intent)
private void writeTag(Intent intent) {
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
final Ndef ndef = Ndef.get(tag);
AsyncTask<Void, Void, String> taskWrite = new AsyncTask<Void, Void, String>() {
@Override
protected String doInBackground(Void... params) {
try {
ndef.connect();
try {
ndef.writeNdefMessage(getMessage());
} catch (FormatException e) {}
ndef.close();
} catch (IOException e) {}
}
};
taskWrite.execute();
}
Surcharger le manifest.xml
<meta-data
android:name="android.nfc.disable_beam_default"
android:value="true" />
Puis d’écrire comme sur un tag via un intent
mAdapter.setNdefPushMessageCallback(this, this);
NFC & Android = byte[] !
Exemple pour écrire "Hello World"
byte[] languageData = "en".getBytes();
byte[] textData = "Hello World".getBytes(record.getEncoding());
byte[] payload = new byte[1 + languageData.length + textData.length];
byte status = (byte) 0x00;
payload[0] = status;
System.arraycopy(languageData, 0, payload, 1, languageData.length);
System.arraycopy(textData, 0, payload, 1 + languageData.length
, textData.length);
NdefRecord ndefRecord = new NdefRecord(NdefRecord.TNF_WELL_KNOWN
, NdefRecord.RTD_TEXT
, record.getId()
, payload);
Simplifier l'écriture. Si le nfc doit percer, il faut l’aider
Parler du problème fréquent avec le multi héritage mais dire que ça sera dispo
Android
// We register the default Nfc Adapter
mAdapter = NfcAdapter.getDefaultAdapter(activity);
// We register the curent activity to a the filters we wants
PendingIntent pendingIntent = PendingIntent.getActivity(activity, 0
, new Intent(activity, activity.getClass())
.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
int length = filters != null && filters.length > 0 ? filters.length : 1;
IntentFilter[] intentFilters = new IntentFilter[length];
IntentFilter ndefFilter = new IntentFilter(filter.getAction());
pendingIntentArray.put(activity.getTaskId(), pendingIntent);
NfA
// We register our activity to the NFA Manager
NFA_MANAGER.register(activity //
, NDEF_FILTER //
);
byte[] payload = ndefRecord.getPayload();
ByteArrayInputStream bais = new ByteArrayInputStream(payload);
int status = bais.read();
byte languageCodeLength = (byte) (status & TextRecord.LANGUAGE_CODE_MASK);
byte[] bytes = new byte[languageCodeLength];
bais.read(bytes, 0, bytes.length);
String languageCode = new String(bytes);
bytes = new byte[payload.length - languageCodeLength - 1];
bais.read(bytes, 0, bytes.length);
byte[] textData = bytes;
Charset textEncoding = ((status & 0x80) != 0) ? TextRecord.UTF16
: TextRecord.UTF8;
String message = null;
try {
message = new String(textData, textEncoding.name());
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
NfaRecieveBeanBuilder<TextRecord> builder = recieveBeanConfigure(); //
builder //
.activity(activity) //
.intent(intent) //
.intentRecieveRecord(new INfaIntentRecieveRecord<TextRecord>() {
@Override
public void recieveRecord(TextRecord record) {
String message = record.getText();
}
}) // INfaIntentRecieveRecord
.parser(TEXT_PARSER); //
NFA_MANAGER.manageIntent(builder.build());
Android
byte[] languageData = "en".getBytes();
byte[] textData = "Hello World".getBytes(record.getEncoding());
byte[] payload = new byte[1 + languageData.length + textData.length];
byte status = (byte) (0x00);
payload[0] = status;
System.arraycopy(languageData, 0, payload, 1, languageData.length);
System.arraycopy(textData, 0, payload, 1 + languageData.length
, textData.length);
NdefRecord ndefRecord = new NdefRecord(NdefRecord.TNF_WELL_KNOWN
, NdefRecord.RTD_TEXT, record.getId(), payload);
NfA
NFA_MANAGER.writeTag(getApplicationContext(), //
intent, //
activity, //
false, // addAndroidApplicationRecord
NfaWriteBean.writeBeanConfigure() //
.writer(TEXT_WRITER) //
.record(NfaRecordFactory.wellKnowTypeFactory()//
.textRecordInstance("Hello World")) //
.build());
Plus de Writers / Parsers / Filters / Records
Signature Record
SmartPoster enrichis
Tests unitaires
Handover Record
Module de Crypto
Ajout de classes abstraites
Optimisation du code
bugs fix
votre contribution ;)
Disponible sur maven Oss Sonatype : http://goo.gl/NAQwd
Code source disponible sous github : Github
Merci à NfcTools et Ndef tools for Android
Sample disponible ici : Play Store