NFC et Android

New Future Communication

Qui suis-je ?

Jean-François GARREAU

images/jf.png
  • Consultant IT chez SQLI

  • Développeur Android à mes heures perdues

  • Un des membres fondateur du GDG Nantes

  • Créateur de CineShowTime images/cineshowtime.png

images/twitter-icon.png

@gdgnantes / @binomed / @uncle_bens1


images/google-Plus-icon.png

http://gplus.to/jefBinomed

Sommaire

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

Qu’est ce que le NFC ?

images/nfc_logo.jpg

Qu’est ce que le NFC ?

images/nfc_logo.jpg

NFC = Near Field Communication ou Communication en champ proche

images/nfc_card.jpg

Interaction / sélection physique

État de l’art

images/nfc_card.jpg

Etat de l’art

Historique

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

Etat de l’art

Technologies : RFID / SmartCard

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

Normes

images/iso-logo.png

Normes

Modes de fonctionnements

3 modes de communications :


images/smart_card_nfc.jpg

Emulation de carte




images/social-nfc-tags.png

Lecture / écriture




images/nfc_p2p.jpg

Pair à Pair




Normes Régies par le NFC Forum !

Emulation= Simulation interface carte à puce

Lecture / Ecriture : Tag

Pair à Pair : 2 Appareils

Normes

Communication

Norme ISO 14443

  • Débits compris entre 106 et 424 Kps
  • Communication inférieur à 10cm. (réellement 3/4cm)
  • Hal duplex ou full duplex

2 types de ISO 14443 :

  • ISO 14443 A (NfcA dans Android)
  • ISO 14443 B (NfcB dans Android)

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%

Normes

Autres normes tolérées par android

Felica (NfcF dans Android)


ISO 15693 (NfcV dans Android)

Felica : Pas ISO mais NFC-Forum : Japon

15693 : ISO mais pas NFC-Forum

Normes

Les types de tags du 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

Normes

NDEF : NFC Data Exchange Format


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

Normes

NDEF : NFC Data Exchange Format

images/Ndefrecod.png

Header = informations sur le tag

Sa place dans le message
Son type
Sa taille

Payload = données

Normes

NDEF - Informations sur le message

images/Ndeffullrecod.png
  • MB (Message Begin) : début de message
  • ME (Message End) : fin de message
  • CF (Chunk Flag) : permet d’indiquer que le message est tronqué
  • SR (Short Reccord) : permet d’indiquer que le message sera court (1octet)
  • IL (ID Length) : permet d’indiquer la présence d’un identifiant
  • TNF (Type Name Format) : le type de la donnée

MB = 1 ⇒ début de message | ME = 1 ⇒ Message fini dans le message

IL : si à 1 : ID Length et ID devront être remplis

Normes

NDEF - TNF (le type du tag)

  • 0x00 Vide : Enregistrement vide
  • 0x01 Well-Known Type (WKT) : Type défini par le NFC Forum
  • 0x02 : Type MIME
  • 0x03 Absolute Uri
  • 0x04 External
  • 0x05 Type non connu
  • 0x06 Type inchangé (utilisé pour les enregistrements tronqués)
  • 0x07 réservé pour un usage futur

Normes

NDEF - Taille du type

images/Ndeffullrecod.png
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

Normes

NDEF - Taille du message

images/Ndeffullrecod.png
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)

Normes

NDEF - Type & Id

images/Ndeffullrecod.png
  • Type est toujours présent : Type du Payload
  • ID dépend du champ IL : Id de l’enregistrement

Normes

NDEF - Contenu du message

images/Ndeffullrecod.png

Normes

Well Known Types

Octet Type

  • U (0x55) pour des uri
  • T (0x54) pour du texte
  • Sp (0x53,0x70) pour un smartPoster (le type a une taille de 2)

Sert à gagner encore plus de bits

Normes

Well Known Types

  • URIs, 1er bit = bit d’identification
    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
  • Texte : un octet indiquant l’encodage (UTF8 =0, UTF16 = 1) et 1 pour la langue
  • SmartPoster Nouveau Ndef avec l’URI

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

Normes

Les types personnalisés

Définition de son propre type !

Filtrer le message et donc ouvrir le message à partir d’une application précise

Usages

images/google-wallet-logo.jpg

Usages

Mode lecture


images/social-nfc-tags.png images/recharge_nfc.jpg images/foursquare-nfc.png

Infos complementaires sur des produits /////// GEOLOC /////// URLS

Codes promos ////// Dématérialisation de cartes

Usages

P2P

images/nfc_beam.jpg

Echange de contacts ///// Echange de fichiers ////// Configuration bluetooth

Usages

Emulation de carte : non disponible en natif sur Android

images/cityzi_transport.jpg images/google-wallet.jpg

Paiement securise

Authentification sur des reseaux securise

Démo

images/nfc_demo.png

Implementation

images/android_nfc.png

Implémentation

Et avec android ?

Depuis 2010 : Lecture / Ecriture de tags
Depuis 2011 : Beam
Depuis 2012 : Partage de médias
images/nfc_tag_dispatch.png

IL n’y a pas que le NDEF de reconnu !

Message transformé en Intent

Implémentation

Configuration

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" />

Implémentation

Réception de tags

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>

Implémentation

Réception de tags

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();
}

Implémentation

Lecture du tag

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];
                                        …
                                }
                        }
                }
        }
}

Implémentation

Ecriture du tag

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});

Implémentation

Ecriture du tag

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();
}

Implémentation

Ecriture BEAM

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);

NFA

Nfc For Android

images/nfa.png

Pourquoi ?

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);

Pourquoi ?

images/meme_rock.jpg

Simplifier l'écriture. Si le nfc doit percer, il faut l’aider

Objectifs

Parler du problème fréquent avec le multi héritage mais dire que ça sera dispo

Objectifs

images/meme_challenge.jpg

Implémentation

Initialisation

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 //
                );

Implémentation

Lecture - Android

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);
}

Implémentation

Lecture - NfA

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());

Implémentation

Ecriture

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());

RoadMap

Résumé

images/nfa.png

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

Résumé

images/meme_baby_win.jpg

Conclusion

images/nfc_logo.jpg

Conclusion

Liens

images/link.png

Liens

Questions

images/andquestionsag.jpg