SlideShare a Scribd company logo
1 of 20
Download to read offline
Hello NFC!



      @rocboronat
SDK + Permisos + Feature

         <uses-permission android:name="android.permission.NFC" />



                   <uses-sdk android:minSdkVersion="10"/>
                 a l'sdk 9 l'interacció amb nfc era molt limitada



 <uses-feature android:name="android.hardware.nfc" android:required="true" />
                només si l'nfc és implescindible per a la nostra app
                 Google Play filtra apps basant-se en aquest valor




                                                     @rocboronat
Hola NDEF!


     ●
         NDEF és un standard definit per NFC Forum

     ●   Android suporta més tecnologies a part d'NDEF

     ●   Però no ho fa molt bé

     ●
         Si ens basem en NDEF, estalviarem molt de temps




                                              @rocboronat
Hola NDEF!
●
    Cada NdefMessage pot tenir molts NdefRecord

●
    Android reacciona al primer NdefRecord

●
    El primer NdefRecord hauria de contenir:

      ●   3-bit TNF (Type Name Format)
            ●
               TNF_ABSOLUTE_URI, TNF_MIME_MEDIA, TNF_WELL_KNOWN...
      ●   Tipus
            ● RTD_URI, RTD_TEXT, RTD_SMART_POSTER...

      ●   ID
            ●
               Un identificador únic per aquest NdefRecord
      ●   Payload
            ● Les dades en sí. Com un NdefMessage pot tenir molts NdefRecords,


               no podem assumir que el Payload té el total de les dades

●
    Android ens proporciona un mecanisme per a escriure NdefRecords i NdefMessages




                                                         @rocboronat
Dispatching

  ●
      Quan s'ha llegit l'NFC, el sistema llença un Intent d'un dels tres tipus:

        ●
            ACTION_NDEF_DISCOVERED

             ●
                 Són tags amb missatges NDEF comprensibles. Són bons.

        ●
            ACTION_TECH_DISCOVERED

             ●
                 Són tags que es basen en el tipus de tag. Evita'ls

        ●
            ACTION_TAG_DISCOVERED

             ●
                 Són tags que Android ni reconeix. Compatibilitat futura?




                                                        @rocboronat
Dispatching




              @rocboronat
Dispatching

 ●
     Si un Intent el pot capturar més d'una aplicació...

       ●
           El sistema li preguntarà a l'usuari quina aplicació vol obrir...

             ●
                  I com haurà de fer click a la pantalla, apartarà el mobil del tag!

                    ●
                        Estaria bé evitar-ho. Jo utilitzo una URI personalitzada:


                 <intent-filter>
                      <action android:name="android.nfc.action.NDEF_DISCOVERED" />
                      <category android:name="android.intent.category.DEFAULT" />
                      <data android:host="crema.cat" android:scheme="roc" />
                 </intent-filter>




                                                               @rocboronat
Dispatching

 Com llegim el tag des de la nostra app?




               tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
               ndefTag = Ndef.get(tag);




 Aquesta serà la única referència que tindrem al nostre tag. Si aquest Intent es
 perd, mai més podrem accedir al tag, de manera que més val que ens ho
 guardem en una variable.




                                                             @rocboronat
Hello AAR!

   ●
       AAR són les sigles d'Android Application Records

   ●
       Van aparèixer amb Android 4.0 – API14

   ●
       AAR assegura que l'app que s'iniciarà a l'escanejar el tag és la teva

   ●
       Si l'usuari no té la teva app instal·lada: Google Play

   ●   El preu a pagar és que no s'utilitzen Intent Filters.
         ● De manera que no pots rebre informació continguda en el tag...




   ●
       Les estacions de Bicing podrien tenir un tag NFC amb AAR.




                                                     @rocboronat
Howto AAR by Google



  NdefMessage msg = new NdefMessage(
      new NdefRecord[] {
        ...,
        NdefRecord.createApplicationRecord("com.example.android.beam")}




                                               @rocboronat
Howto AAR by me
 public static NdefMessage createAAR() {
      try {
           NdefRecord aar = null;
           try{
                Class c = Class.forName("android.nfc.NdefRecord");
                c.getMethods();
                Method m = c.getMethod ("createApplicationRecord", String.class);
                aar = (NdefRecord) m.invoke(aar, "net.rocboronat.android.nfc.car");
           } catch (Exception e) {
                return null;
           }

          NdefMessage msg = new NdefMessage(new NdefRecord[] {
               new NdefRecord(
                    aar.getTnf(),
                    aar.getType(),
                    RandomUtil.randomNumeric().getBytes(Charset.forName("US-ASCII")),
                    aar.getPayload())
               });
          return msg;
     } catch (Exception e) {
          e.printStackTrace();
          return null;
     }
 }




                                                        @rocboronat
Howto AAR by me
  private static boolean writeNdefAar(){
        boolean result = false;

          Ndef ndefTag = null;
          try {
               NdefMessage aar = AndroidApplicationRecordsUtil.createAAR();
               ndefTag = Ndef.get(NfcActivity.tag);
               Log.i("NfcNdefAar","Message: "+(aar.toByteArray().length));
               Log.i("NfcNdefAar","NFC max: "+ndefTag.getMaxSize());

              if (aar.toByteArray().length>ndefTag.getMaxSize()){
                    Log.i("NfcNdefAar", "message is too big for this NFC");
              }

               if (!ndefTag.isConnected()){
                     ndefTag.connect();
               }
              ndefTag.writeNdefMessage(aar);
              result = true;
          } catch (IOException e) {
              Log.e("TagWriter", "IOException while writing...", e);
          } catch (FormatException e) {
              Log.e("TagWriter", "FormatException while writing...", e);
               } catch (NullPointerException e) {
              Log.e("TagWriter", "NullPointerException while writing...", e);
               } finally {
              try {
               if (ndefTag!=null){
                     ndefTag.close();
               }
              } catch (Exception e) {
                  Log.e("TagWriter", "Exception while closing...", e);
              }
          }
          return result;
      }




                                                                              @rocboronat
Creating NdefMessage

 private static final String CUSTOM_URI = "roc://crema.cat/";
 public static NdefMessage createCustom() {
      NdefRecord uri = NdefRecord.createUri(CUSTOM_URI.concat(RandomUtil.randomNumeric()));
      NdefMessage msg = new NdefMessage(new NdefRecord[] { new NdefRecord(
               uri.getTnf(), uri.getType(), RandomUtil.randomNumeric()
                    .getBytes(Charset.forName("US-ASCII")),
               uri.getPayload()) });

     return msg;
 }




                                                         @rocboronat
Foreground Dispatch System


 ●
     Quan es troba un NFC, Android el tracta. Aquest fet limita.

 ●
     Si activem el FDS, ens fem responsables de tractar els NFC des de la nostra app.

 ●
     NFCar utilitza aquest sistema per a formatar tags.




                                                          @rocboronat
Foreground Dispatch System
   private static String[][] techListsArray = null;
   private static IntentFilter[] intentFiltersArray = null;
   private static IntentFilter intentFilter = null;
   private static PendingIntent pendingIntent = null;

   private static void init(Activity a){
        pendingIntent = PendingIntent.getActivity(a, 0,
                     new Intent(a, a.getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
              intentFilter = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
        try {
              intentFilter.addDataType("*/*"); // Handles all MIME based dispatches.
        } catch (MalformedMimeTypeException e) {
              throw new RuntimeException("fail", e);
        }
        intentFiltersArray = new IntentFilter[] { intentFilter, };
        techListsArray = new String[][] {
                     new String[] { NfcA.class.getName(), NfcB.class.getName() },
                     new String[] { NfcV.class.getName() },
                     new String[] { NfcF.class.getName() },
                     new String[] { MifareClassic.class.getName() },
                     new String[] { MifareUltralight.class.getName() },
                     new String[] { Ndef.class.getName() },
                     new String[] { NdefFormatable.class.getName() },
                     new String[] { IsoDep.class.getName() } };
   }




                                                              @rocboronat
Foreground Dispatch System

   public static void enable(Activity a){
        if (NfcUtil.nfcAvailable(a)){
               try{
                     init(a);
                     NfcUtil.enableForeground(a, pendingIntent, intentFiltersArray, techListsArray);
               }catch (IllegalStateException e) {
                     // TODO: handle exception
               }
        }
   }
   public static void disable(Activity a){
        if (NfcUtil.nfcAvailable(a)){
               NfcUtil.disableForeground(a);
        }
   }




                                                                 @rocboronat
Foreground Dispatch System

  @Override
  public void onResume() {
       super.onResume();
       IntercepterUtil.enable(this);
  }

  @Override
  protected void onPause() {
       super.onPause();
       IntercepterUtil.disable(this);
  }

  public void onNewIntent(Intent intent) {
       NfcActivity.processarTag(intent, PreferenceManager.getDefaultSharedPreferences(this), this);
       repintarLogo();
  }




                                                               @rocboronat
Arquitectura proposada

 ●
     L'Activity que reb l'Intent del tag NFC no ha de tenir vista

 ●
     L'Activity que reb l'Intent del tag NFC fa coses amb el tag NFC

 ●
     L'Activity que reb l'Intent del tag NFC pot llençar Intents


       <activity
                android:name=".NfcActivity"
                android:theme="@android:style/Theme.NoDisplay" >
                <intent-filter>
                   <action android:name="android.nfc.action.NDEF_DISCOVERED" />
                   <category android:name="android.intent.category.DEFAULT" />
                   <data android:host="crema.cat" android:scheme="roc" />
                </intent-filter>
       </activity>




                                                                @rocboronat
All your base


          http://developer.android.com/guide/topics/connectivity/nfc/index.html
                              article oficial de Google


 http://rocboronat.net/index.php/en/blog/72-coses-que-he-apres-sobre-lnfc-a-android
                          experiències i batalletes d'en Roc


                             http://fewlaps.com
                 empresa catalana de desenvolupament mobil
                         fem ponències sobre NFC!




                                                      @rocboronat
Gràcies!



           roc@fewlaps.com

More Related Content

Similar to Hello NFC!

Programació - PAC 2 correcció - Multimèdia (UOC) - Paquita Ribas
Programació - PAC 2 correcció - Multimèdia (UOC) - Paquita RibasProgramació - PAC 2 correcció - Multimèdia (UOC) - Paquita Ribas
Programació - PAC 2 correcció - Multimèdia (UOC) - Paquita RibasPaquita Ribas
 
Turbo Gears, Framework De Python Per Aplicacions Web
Turbo Gears, Framework De Python Per Aplicacions WebTurbo Gears, Framework De Python Per Aplicacions Web
Turbo Gears, Framework De Python Per Aplicacions WebTomàs Reverter
 
Programació - PAC 2 - Multimedia (UOC) - Paquita Ribas
Programació - PAC 2 - Multimedia (UOC) - Paquita RibasProgramació - PAC 2 - Multimedia (UOC) - Paquita Ribas
Programació - PAC 2 - Multimedia (UOC) - Paquita RibasPaquita Ribas
 
Programació Web - PAC 2 correcció - Multimèdia (UOC) - Paquita Ribas
Programació  Web - PAC 2 correcció - Multimèdia (UOC) - Paquita RibasProgramació  Web - PAC 2 correcció - Multimèdia (UOC) - Paquita Ribas
Programació Web - PAC 2 correcció - Multimèdia (UOC) - Paquita RibasPaquita Ribas
 
Introducció a Python
Introducció a PythonIntroducció a Python
Introducció a PythonGDGMallorca
 

Similar to Hello NFC! (7)

Programació - PAC 2 correcció - Multimèdia (UOC) - Paquita Ribas
Programació - PAC 2 correcció - Multimèdia (UOC) - Paquita RibasProgramació - PAC 2 correcció - Multimèdia (UOC) - Paquita Ribas
Programació - PAC 2 correcció - Multimèdia (UOC) - Paquita Ribas
 
Turbo Gears, Framework De Python Per Aplicacions Web
Turbo Gears, Framework De Python Per Aplicacions WebTurbo Gears, Framework De Python Per Aplicacions Web
Turbo Gears, Framework De Python Per Aplicacions Web
 
Programació - PAC 2 - Multimedia (UOC) - Paquita Ribas
Programació - PAC 2 - Multimedia (UOC) - Paquita RibasProgramació - PAC 2 - Multimedia (UOC) - Paquita Ribas
Programació - PAC 2 - Multimedia (UOC) - Paquita Ribas
 
Sync toasync
Sync toasyncSync toasync
Sync toasync
 
Metasploit framework mini how-to
Metasploit framework mini how-toMetasploit framework mini how-to
Metasploit framework mini how-to
 
Programació Web - PAC 2 correcció - Multimèdia (UOC) - Paquita Ribas
Programació  Web - PAC 2 correcció - Multimèdia (UOC) - Paquita RibasProgramació  Web - PAC 2 correcció - Multimèdia (UOC) - Paquita Ribas
Programació Web - PAC 2 correcció - Multimèdia (UOC) - Paquita Ribas
 
Introducció a Python
Introducció a PythonIntroducció a Python
Introducció a Python
 

Hello NFC!

  • 1. Hello NFC! @rocboronat
  • 2. SDK + Permisos + Feature <uses-permission android:name="android.permission.NFC" /> <uses-sdk android:minSdkVersion="10"/> a l'sdk 9 l'interacció amb nfc era molt limitada <uses-feature android:name="android.hardware.nfc" android:required="true" /> només si l'nfc és implescindible per a la nostra app Google Play filtra apps basant-se en aquest valor @rocboronat
  • 3. Hola NDEF! ● NDEF és un standard definit per NFC Forum ● Android suporta més tecnologies a part d'NDEF ● Però no ho fa molt bé ● Si ens basem en NDEF, estalviarem molt de temps @rocboronat
  • 4. Hola NDEF! ● Cada NdefMessage pot tenir molts NdefRecord ● Android reacciona al primer NdefRecord ● El primer NdefRecord hauria de contenir: ● 3-bit TNF (Type Name Format) ● TNF_ABSOLUTE_URI, TNF_MIME_MEDIA, TNF_WELL_KNOWN... ● Tipus ● RTD_URI, RTD_TEXT, RTD_SMART_POSTER... ● ID ● Un identificador únic per aquest NdefRecord ● Payload ● Les dades en sí. Com un NdefMessage pot tenir molts NdefRecords, no podem assumir que el Payload té el total de les dades ● Android ens proporciona un mecanisme per a escriure NdefRecords i NdefMessages @rocboronat
  • 5. Dispatching ● Quan s'ha llegit l'NFC, el sistema llença un Intent d'un dels tres tipus: ● ACTION_NDEF_DISCOVERED ● Són tags amb missatges NDEF comprensibles. Són bons. ● ACTION_TECH_DISCOVERED ● Són tags que es basen en el tipus de tag. Evita'ls ● ACTION_TAG_DISCOVERED ● Són tags que Android ni reconeix. Compatibilitat futura? @rocboronat
  • 6. Dispatching @rocboronat
  • 7. Dispatching ● Si un Intent el pot capturar més d'una aplicació... ● El sistema li preguntarà a l'usuari quina aplicació vol obrir... ● I com haurà de fer click a la pantalla, apartarà el mobil del tag! ● Estaria bé evitar-ho. Jo utilitzo una URI personalitzada: <intent-filter> <action android:name="android.nfc.action.NDEF_DISCOVERED" /> <category android:name="android.intent.category.DEFAULT" /> <data android:host="crema.cat" android:scheme="roc" /> </intent-filter> @rocboronat
  • 8. Dispatching Com llegim el tag des de la nostra app? tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); ndefTag = Ndef.get(tag); Aquesta serà la única referència que tindrem al nostre tag. Si aquest Intent es perd, mai més podrem accedir al tag, de manera que més val que ens ho guardem en una variable. @rocboronat
  • 9. Hello AAR! ● AAR són les sigles d'Android Application Records ● Van aparèixer amb Android 4.0 – API14 ● AAR assegura que l'app que s'iniciarà a l'escanejar el tag és la teva ● Si l'usuari no té la teva app instal·lada: Google Play ● El preu a pagar és que no s'utilitzen Intent Filters. ● De manera que no pots rebre informació continguda en el tag... ● Les estacions de Bicing podrien tenir un tag NFC amb AAR. @rocboronat
  • 10. Howto AAR by Google NdefMessage msg = new NdefMessage( new NdefRecord[] { ..., NdefRecord.createApplicationRecord("com.example.android.beam")} @rocboronat
  • 11. Howto AAR by me public static NdefMessage createAAR() { try { NdefRecord aar = null; try{ Class c = Class.forName("android.nfc.NdefRecord"); c.getMethods(); Method m = c.getMethod ("createApplicationRecord", String.class); aar = (NdefRecord) m.invoke(aar, "net.rocboronat.android.nfc.car"); } catch (Exception e) { return null; } NdefMessage msg = new NdefMessage(new NdefRecord[] { new NdefRecord( aar.getTnf(), aar.getType(), RandomUtil.randomNumeric().getBytes(Charset.forName("US-ASCII")), aar.getPayload()) }); return msg; } catch (Exception e) { e.printStackTrace(); return null; } } @rocboronat
  • 12. Howto AAR by me private static boolean writeNdefAar(){ boolean result = false; Ndef ndefTag = null; try { NdefMessage aar = AndroidApplicationRecordsUtil.createAAR(); ndefTag = Ndef.get(NfcActivity.tag); Log.i("NfcNdefAar","Message: "+(aar.toByteArray().length)); Log.i("NfcNdefAar","NFC max: "+ndefTag.getMaxSize()); if (aar.toByteArray().length>ndefTag.getMaxSize()){ Log.i("NfcNdefAar", "message is too big for this NFC"); } if (!ndefTag.isConnected()){ ndefTag.connect(); } ndefTag.writeNdefMessage(aar); result = true; } catch (IOException e) { Log.e("TagWriter", "IOException while writing...", e); } catch (FormatException e) { Log.e("TagWriter", "FormatException while writing...", e); } catch (NullPointerException e) { Log.e("TagWriter", "NullPointerException while writing...", e); } finally { try { if (ndefTag!=null){ ndefTag.close(); } } catch (Exception e) { Log.e("TagWriter", "Exception while closing...", e); } } return result; } @rocboronat
  • 13. Creating NdefMessage private static final String CUSTOM_URI = "roc://crema.cat/"; public static NdefMessage createCustom() { NdefRecord uri = NdefRecord.createUri(CUSTOM_URI.concat(RandomUtil.randomNumeric())); NdefMessage msg = new NdefMessage(new NdefRecord[] { new NdefRecord( uri.getTnf(), uri.getType(), RandomUtil.randomNumeric() .getBytes(Charset.forName("US-ASCII")), uri.getPayload()) }); return msg; } @rocboronat
  • 14. Foreground Dispatch System ● Quan es troba un NFC, Android el tracta. Aquest fet limita. ● Si activem el FDS, ens fem responsables de tractar els NFC des de la nostra app. ● NFCar utilitza aquest sistema per a formatar tags. @rocboronat
  • 15. Foreground Dispatch System private static String[][] techListsArray = null; private static IntentFilter[] intentFiltersArray = null; private static IntentFilter intentFilter = null; private static PendingIntent pendingIntent = null; private static void init(Activity a){ pendingIntent = PendingIntent.getActivity(a, 0, new Intent(a, a.getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0); intentFilter = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED); try { intentFilter.addDataType("*/*"); // Handles all MIME based dispatches. } catch (MalformedMimeTypeException e) { throw new RuntimeException("fail", e); } intentFiltersArray = new IntentFilter[] { intentFilter, }; techListsArray = new String[][] { new String[] { NfcA.class.getName(), NfcB.class.getName() }, new String[] { NfcV.class.getName() }, new String[] { NfcF.class.getName() }, new String[] { MifareClassic.class.getName() }, new String[] { MifareUltralight.class.getName() }, new String[] { Ndef.class.getName() }, new String[] { NdefFormatable.class.getName() }, new String[] { IsoDep.class.getName() } }; } @rocboronat
  • 16. Foreground Dispatch System public static void enable(Activity a){ if (NfcUtil.nfcAvailable(a)){ try{ init(a); NfcUtil.enableForeground(a, pendingIntent, intentFiltersArray, techListsArray); }catch (IllegalStateException e) { // TODO: handle exception } } } public static void disable(Activity a){ if (NfcUtil.nfcAvailable(a)){ NfcUtil.disableForeground(a); } } @rocboronat
  • 17. Foreground Dispatch System @Override public void onResume() { super.onResume(); IntercepterUtil.enable(this); } @Override protected void onPause() { super.onPause(); IntercepterUtil.disable(this); } public void onNewIntent(Intent intent) { NfcActivity.processarTag(intent, PreferenceManager.getDefaultSharedPreferences(this), this); repintarLogo(); } @rocboronat
  • 18. Arquitectura proposada ● L'Activity que reb l'Intent del tag NFC no ha de tenir vista ● L'Activity que reb l'Intent del tag NFC fa coses amb el tag NFC ● L'Activity que reb l'Intent del tag NFC pot llençar Intents <activity android:name=".NfcActivity" android:theme="@android:style/Theme.NoDisplay" > <intent-filter> <action android:name="android.nfc.action.NDEF_DISCOVERED" /> <category android:name="android.intent.category.DEFAULT" /> <data android:host="crema.cat" android:scheme="roc" /> </intent-filter> </activity> @rocboronat
  • 19. All your base http://developer.android.com/guide/topics/connectivity/nfc/index.html article oficial de Google http://rocboronat.net/index.php/en/blog/72-coses-que-he-apres-sobre-lnfc-a-android experiències i batalletes d'en Roc http://fewlaps.com empresa catalana de desenvolupament mobil fem ponències sobre NFC! @rocboronat
  • 20. Gràcies! roc@fewlaps.com