«

»

abr 15 2013

NFC (I): Explicación, tutorial básico y sorteo

Hola a todos, en este post voy a tratar de explicar qué es NFC, algunos usos que tiene y una explicación fácil para programar un editor de textos en NFC muy sencillo. Además, estad atentos al final porque regalaremos unos tags NFC para que probéis cómo hacerlo :)

androcode_nfc

El futuro y el presente de las microcomunicaciones. ¿Qué es NFC y de dónde viene?

Near Field Communication(NFC) es una tecnología de comunicación inalámbrica, de corto alcance y alta frecuencia que permite intercambio de datos entre dispositivos a menos de 10 cm.
Funciona en la banda de 16.56MHz, la cuál es una frecuencia libre que se puede usar sin licencias con distintas velocidades de 106kbit/s, 212kbit/s o 424kbit/s.

Es una evolución del anterior RFID(ISO 14443), un dispositivo NFC puede comunicarse con cualquier tarjeta inteligente y lector existentes dentro del estándar ISO/IEC 14443. La principal diferencia es que el alcance es mucho menor, por lo que se necesita que los dispositivos estén a escasos centímetros durante un instante para la transmisión de información. Aunque podría parecernos una limitación, más bien es una ventaja ya que el usuario es consciente del acto que está haciendo y refleja la voluntad de usar este servicio.

Su desarrollo comienza en 2002 y sus promotores fueron Philips y Sony para conseguir compatibilidad con sus tecnologías Mifare y FeliCa respectivamente. A finales de 2003 se aprueba como el estándar ISO 18092 y ECMA-340. En 2004 Nokia, Philips y Sony crearon NFC Forum. En 2006 salió al mercado el primer dispositivo con NFC desarrollado por Nokia , el Nokia 6131. En 2010 Samsung lanzó el primer dispositivo con Android y NFC, el Samsung Nexus S.

Usos de NFCshowcase

  • Conexión entre dispositivos: Podemos vincular nuestro dispostivo Android con un altavoz inalámbrico, la TV, o el ordenador.
  • Pago por NFC: Un ejemplo de esta aplicación puede ser Google Wallet. Una vez configurada tu tarjeta e identificada, sólo tenemos que realizar el pago acercando el dispositivo al lector y aceptar el pago. Esta opción la probé gracias a la MWC 2013 y me pareció de lo más simple, cómodo y eficaz para no tener que estar sacando la tarjeta, escribir el PIN… El dispositivo lo tenemos en la mano casi todo el día y es un simple gesto.
  • Compartir archivos: Con la nueva versión de Android 4.1 Jelly Bean compartir archivos es fácil, simplemente con acercar dos dispositivos estos se vinculan automáticamente y podemos compartir fotos o información en general.
  • Tags de Información: Durante la MWC nos encontramos muchos de estos Tags, con sólo acercar el dispositvo se nos abría la aplicación de GSMA con la información a tiempo real o una página web dónde encontrábamos la información, práctico y sencillo.
  • Más usos: La posibilidad de usar NFC en la vida diaria es probablemente algo que haremos no en un tiempo muy lejano, esta tecnología tiene muchisimas posibilidades de uso común por su facilidad en el uso y la gran aceptación que está teniendo por los usuarios que poseen dispositivos con esta tecnología.

Desarrollo de un editor de etiquetas simple de NFC

Ahora voy a explicar un simple código para poder crear mensajes en Tags. En un tutorial más avanzado hablaré de compartir entre dispositivos y otros ejemplos que surjan. Este es un “tuto” introductorio para que veáis qué fácil es el desarrollo de un editor de Tag NFC

Creamos un nuevo proyecto llamado “es.androcode.nfc” con una simple Activity llamada MainActivity.
La parte más importante de nuestro proyecto además del Activity se encuentra en nuestro Manifest. La línea señalada es la que da permisos a la aplicación para usar el NFC de nuestro dispositivo.

Nuestro AndroidManifest.xml será como sigue:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.androcode.nfc"
    android:versionCode="1"
    android:versionName="1.0" >
    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="17" />
    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.androcode.nfc.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
    <uses-permission android:name="android.permission.NFC" />
</manifest>

Una vez creado el Manifest, vamos a crear el layout activity_main que será nuestra simple interfaz.

Un simple LinearLayout con un TextView, un EditText donde escribiremos el mensaje que queremos que almacene nuestro Tag y un botón para crear la acción de escribir en el Tag.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Write you message: ">
    </TextView>

    <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginTop="20sp" >

        <EditText
            android:id="@+id/edit_message"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="2"
            android:hint="message" />

        <Button
            android:id="@+id/button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="Write!!" />
    </LinearLayout>

</LinearLayout>

Ahora estamos listos para crear la Activity que explico a continuación del código.

package com.androcode.nfc;

import java.io.IOException;
import java.io.UnsupportedEncodingException;

import android.nfc.FormatException;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.nfc.tech.Ndef;
import android.os.Bundle;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

@SuppressLint("NewApi")
public class MainActivity extends Activity {
	NfcAdapter adapter;
	PendingIntent pendingIntent;
	IntentFilter writeTagFilters[];
	boolean writeMode;
	Tag myTag;
	Context context;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //Definimos el layout a usar
        setContentView(R.layout.activity_main);
        context = this;
        //Los elementos que vamos a usar en el layout
        Button btnWrite = (Button)findViewById(R.id.button);
        final TextView message = (TextView)findViewById(R.id.edit_message);
        //setOnCLickListener hará la acción que necesitamos
        btnWrite.setOnClickListener(new OnClickListener() {
	@Override
	public void onClick(View v) {
	  try{
              //Si no existe tag al que escribir, mostramos un mensaje de que no existe.
              if(myTag == null){
		Toast.makeText(context, context.getString(R.string.error_notag), Toast.LENGTH_LONG).show();
	      }else{
               //Llamamos al método write que definimos más adelante donde le pasamos por
               //parámetro el tag que hemos detectado y el mensaje a escribir.
		write(message.getText().toString(),myTag);
	        Toast.makeText(context, context.getString(R.string.ok_write), Toast.LENGTH_LONG).show();
	     }
	   }catch(IOException e){
	Toast.makeText(context, context.getString(R.string.error_write),Toast.LENGTH_LONG).show();
		e.printStackTrace();
	}catch(FormatException e){
       Toast.makeText(context, context.getString(R.string.error_write), Toast.LENGTH_LONG).show();
	e.printStackTrace();
	}
     }
  });

        adapter = NfcAdapter.getDefaultAdapter(this);
        pendingIntent = PendingIntent.getActivity(this, 0, new Intent(this,getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
        IntentFilter tagDetected = new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED);
        tagDetected.addCategory(Intent.CATEGORY_DEFAULT);
        writeTagFilters = new IntentFilter[]{tagDetected};
    }
    //El método write es el más importante, será el que se encargue de crear el mensaje 
    //y escribirlo en nuestro tag.
    private void write(String text, Tag tag) throws IOException, FormatException{
      //Creamos un array de elementos NdefRecord. Este Objeto representa un registro del mensaje NDEF	
      //Para crear el objeto NdefRecord usamos el método createRecord(String s)
      NdefRecord[] records = {createRecord(text)};
      //NdefMessage encapsula un mensaje Ndef(NFC Data Exchange Format). Estos mensajes están 
      //compuestos por varios registros encapsulados por la clase NdefRecord      
      NdefMessage message = new NdefMessage(records);
      //Obtenemos una instancia de Ndef del Tag
      Ndef ndef = Ndef.get(tag);
      ndef.connect();
      ndef.writeNdefMessage(message);
      ndef.close();
    }
    //Método createRecord será el que nos codifique el mensaje para crear un NdefRecord
    @SuppressLint("NewApi") private NdefRecord createRecord(String text) throws UnsupportedEncodingException{
    	String lang = "us";
    	byte[] textBytes = text.getBytes();
    	byte[] langBytes = lang.getBytes("US-ASCII");
    	int langLength = langBytes.length;
    	int textLength = textBytes.length;
    	byte[] payLoad = new byte[1 + langLength + textLength];

    	payLoad[0] = (byte) langLength;

    	System.arraycopy(langBytes, 0, payLoad, 1, langLength);
    	System.arraycopy(textBytes, 0, payLoad, 1+langLength, textLength);

    	NdefRecord recordNFC = new NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_TEXT, new byte[0], payLoad);

    	return recordNFC;

    }
    //en onnewIntent manejamos el intent para encontrar el Tag
    @SuppressLint("NewApi") protected void onNewIntent(Intent intent){
    	if(NfcAdapter.ACTION_TAG_DISCOVERED.equals(intent.getAction())){
    		myTag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
    		Toast.makeText(this, this.getString(R.string.ok_detected) + myTag.toString(), Toast.LENGTH_LONG).show();

    	}
    }

    public void onPause(){
    	super.onPause();
    	WriteModeOff();
    }
    public void onResume(){
    	super.onResume();
    	WriteModeOn();
    }

    @SuppressLint("NewApi") private void WriteModeOn(){
    	writeMode = true;
    	adapter.enableForegroundDispatch(this, pendingIntent, writeTagFilters, null);
    }

    @SuppressLint("NewApi") private void WriteModeOff(){
		writeMode = false;
		adapter.disableForegroundDispatch(this);
    }
}

Como Adapter usamos el NfcAdapter que viene por defecto en nuestro dispositivo con NFC.

El PendingIntent que usamos, le pasamos como Flag el Intent.FLAG_ACTIVITY_SINGLE_TOP para que la Activity no se cree de nuevo y se reutilice si ya está presente en la pila de actividades.
Luego definimos el IntentFilter. Este IntentFilter será el que nos indique si un Tag es encontrado. Y a nuestro array de IntentFilters le añadimos éste que hemos creado.
Al método write le pasamos por parámetros el mensaje a escribir y el Tag. En createRecord creamos el NdefRecord. Con el objeto Ndef obtenemos el tag, escribimos el mensaje NdefRecord y cerramos.

Comprendiendo los mensajes NFC

Un mensaje NDEF está representado por la clase NdefMessage, que está compuesto por varios registros encapsulados de tipo NdefRecord. El primer registro de un mensaje NDEF determina cómo interpretar el conjunto del mensaje. Un registro NdefRecord tiene los siguientes campos:

  • 3-bit TNF(Type Name Format) Campo que indicará cómo se interpretará el mensaje.
  • length type: Formato del registro.
  • length ID: Identificador único del registro.
  • length payload: Datos.

Tipos de formato. Los TNFs vienen definidos por los siguientes tipos: TNF_EMPTY (Mensaje vacío), TNF_WELL_KNOWN(Mensaje bien definido.), TNF_MIME_MEDIA(Registro definido con un MIME-type), TNF_ABSOLUTE_URI(URI), TNF_EXTERNAL_TYPE(Tipo especial), TNF_UNKNOWN(Desconocido), TNF_UNCHANGED(Trozo del mensaje).
Cuando el TNF es del tipo TNF_WELL_KNOWN significa que el mensaje NDEF  tiene alguno de los siguientes RTDs: RTD_TEXT(Texto plano con ISO del idioma correspondiente), RTD_URI(Contiene una URI), RTD_SMART_POSTER(Contiene varios registros como URI, acciones,…)

Es un simple ejemplo de cómo hacer un editor de texto para un tag. Como véis no es nada complicado y bastante efectivo en un simple código de no más de 100 lineas tenemos una aplicación completa para poder interactuar con nuestro NFC Tag y probar así la API relacionada con NFC.

En próximos posts contaré más sobre NFC y algún ejemplo de nivel más avanzado.

Espero que os haya gustado :)

Sorteo de pines con Tag NFC

Aprovechando los pines con NFC que nos dieron en la MWC de Barcelona, vamos a sortear algunos de estos entre nuestros lectores. Participar es muy fácil, sólo queremos oir vuestras ideas para usos de los Tags. Aquí tenéis las bases del concurso y a continuación el formulario para participar.

pin2

Important!

Resultado

Primer premio: Jorge; por su idea: “Desarrollaría una app para fichar en mi trabajo, y luego la ampliaría para que sirviera de control de acceso a varias zonas“.

Ganadores del sorteo: José Antonio BlayaIván CarloChristianMiguel Ramírez Díaz

Enhorabuena a los ganadores.

Bases del concurso

  • Para participar debes publicar un mensaje en Google+, Twitter o Facebook contando brevemente para qué usarías los pines NFC, con un enlace directo a esta publicación y el hashtag #AndrocodeNFC.
  • Debes seguir la cuenta de Androcode de la red social que uses para participar. Aquí están nuestra cuenta de Google+, Twitter y Facebook.
  • Introduce en el formulario los enlaces a cada publicación que escribas para participar. Tiene que ser un enlace directo a ésta, no a tu perfil.
  • La publicación debe ser visible desde cualquier cuenta. De lo contrario no contará como válida.
  • De entre todos los participantes el equipo del blog elegirá la idea más original, que recibirá 3 pines NFC. Entre los demás se elegirán aleatoriamente 4 ganadores y cada uno recibirá 2 pines.
  • Sólo se puede participar 1 vez por persona. Si detectamos cualquier indicio de trampa el participante quedará fuera del sorteo. Sin embargo, por cada medio que se utilice para participar se tendrá una oportunidad de ganar. Por tanto si usas las tres redes sociales tendrás más posibilidad que usando sólo una.
  • Se podrá participar hasta el domingo día 21 de abril, a las 12 de la noche. Descartaremos las participaciones inválidas y el miércoles siguiente publicaremos aquí los nombres de los ganadores y contactaremos con ellos por correo electrónico para concretar el envío.
  • Si pasadas las 48 horas del envío del correo electrónico no obtenemos respuesta, el premio queda anulado y se lo pasaremos a otro participante escogido al azar.
  • Por motivos de envío, el sorteo sólo es válido para España.

¡Mucha suerte a todos!

Acerca del autor

InmaculadaAlcon

Me entusiasma aprender y desarrollar software de calidad. Crear aplicaciones para Android es lo que más me gusta y por lo que me muevo cada día. Soy muy flamenca, enamorada de Sevilla y con el sueño de trabajar algún día en Silicon Valley. Me encanta el fútbol y soy del Betis manque pierda.

  • http://gravatar.com/ueshiba Jose Antonio

    Buen artículo! Código claro y limpio, y por supuesto muy útil

  • Nas

    Buenas noches necesito ayuda con este código por más que intento ejecutarlo me salta este error todo el rato:

    java.lang.RuntimeException: Unable to resume activity {com.androcode.nfc/com.androcode.nfc.MainActivity}: java.lang.NullPointerException
    at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2120)
    at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2135)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1668)
    at android.app.ActivityThread.access$1500(ActivityThread.java:117)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:931)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:123)
    at android.app.ActivityThread.main(ActivityThread.java:3683)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:507)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)

    ¿Qué puedo hacer?

    muchas gracias

  • Eduardo Moreno

    El tutorial es muy bueno, y muy muy al grano.
    Felicitaciones y agradecimientos para Inmaculada

  • Alan

    Muy buen tutorial, felicidades!
    Cuando subirás otro ejemplo con NFC?

  • Fernando

    sip, Cuando??
    Exelente aporte!!
    Felicidades ;)!!

  • jorge marambio

    Por-favor mas ejemplos de NFC

  • Eloy

    Hola! un muy buen aporte! pero la verdad es que podrias hacer lo mismo pero para leer de los tags?? yo no lo consigo hacer! Un saludo Inmaculada ;)

    • Oswaldo

      Hola Eloy, encontraste la forma de leer los tags? te agradecería mucho si me pudieses ayudar, compartiendome como lo hiciste. Muchas Gracias.

  • Pato Sepúlveda Ortega

    Algun curso o tutorial mas avanzado con el uso de etiquetas nfc?? gracias

  • Lucifago Rofocale

    Que saben acerca del desarrollo de Duoskin? podremos desarrollar algo similar para el control de dispositivos con alguna tecnologia nfc como apagar, encender y hasta programar tareas? estoy desarrollando algunos scrips pero necesito ayuda algun interesado???