Near Field Communication (NFC) es una tecnología inalámbrica de corto alcance que permite la comunicación entre dos dispositivos separados por escasos centímetros. Se trata de una tecnología abierta bajo el amparo del estándar ISO 18092 establecido a finales del año 2003. NFC opera en la frecuencia de 13.56 MHz lo que la abstiene de cualquier tipo de licencia o permiso de emisión.
Además de su carácter libre, la principal ventaja de este protocolo de comunicación es que opera a muy corta distancia, lo que dificulta cualquier intento de interceptar la señal entre los dos dispositivos que se están comunicando. Esta peculiaridad la hace ideal para realizar transferencias de datos privados y sensibles. Además se incorporan mecanismos de autenticación y verificación de datos para evitar escuchas. También permite establecer sistemas de cifrado de datos similares a los de las tarjetas bancarias.
El hecho de empotrar esta tecnología en los teléfonos móviles, es decir en útiles que nos acompañan a todas partes, da pié a infinidad de usos como por ejemplo:
Android dispone de un completo API para manejar esta tecnología. En este tutorial realizaremos una introducción a algunas de estas clases para intercambiar información entre dispositivos o con tarjetas y chips inteligentes a través de mensajes NDEF (NFC Data Exchange Format), formato estándar para la transmisión NFC.
Figura 1- http://www.xataka.com
A través de este API y usando el formato estándar NDEF, podemos trabajar con nuestro terminal en tres modos diferentes:
Figura 2-Tag
Figura 3-NFC SmartPoster
Figura 4-Tag Emulation como pase de acceso
Figura 4-Presentación de Android Beam
Actualmente los dispositivos móviles disponibles en el mercado con esta tecnología son más bien escasos. Algunos ejemplos son:
Figura 5-Terminales con NFC
A la hora de desarrollar aplicaciones NFC en Android, podremos encontrarnos con bastantes problemas si nos disponemos de algunos de los terminales enumerados anteriormente, ya que los dispositivos virtuales de la SDK (AVD) no disponen de funcionalidades para simular mensajes NFC.
En la página www.open-nfc.org podemos encontrar un sistema para emular un entorno NFC, aunque se trata de un conjunto de herramientas un tanto complejas y podríamos decir que aún no se encuentran en un estado estable como para depender de ella en nuestros desarrollos:
Figura 6- NFC Simulator
El API se aglutina en el paquete android.nfc, donde podemos encontrar algunas clases como:
NfcManager |
Servicio del sistema (getSystemService(NFC_SERVICE)) que permite obtener una instancia del adaptador NFC (NfcAdapter). |
NfcAdapter |
Adaptador NFC. Podemos definirla como la clase base para trabajar con este API. |
NdefMessage |
Encapsula un mensaje NDEF (NFC Data Exchange Format). Estos mensajes estarán compuestos por varios registros encapsulados por la clase NdefRecords. También encontramos clases para manipular mensajes en el paque android.nfc.tec. |
NdefRecord |
Representa un registro del mensaje NDEF. |
Tag |
Representa un tag NFC que ha sido descubierto. |
Tabla 1- Principales clase de android.nfc
En este paquete también encontramos algunas clases relacionadas con la definición de listeners:
NfcAdapter.CreateNdefMessageCallback |
Será invocada para enviar mensajes NDEF (Android Beam). |
NfcAdapter.OnNdefPushCompleteCallback |
Será invocada cuando el dispositivo ha enviado correctamente un mensaje (NdefMessage) a otro dispositivo. |
NfcEvent |
Evento relacionado con los “callback” anteriores. |
Tabla 2- Clases relacionadas con los listeners
Como vimos en la tabla 1, un mensaje NDEF estará representado por la clase NdefMessage, que a su vez estará compuesto por varios registros encapsulados en clases NdefRecord. El primer registro de un mensaje NDEF (NdefRecord) determina como interpretar el conjunto del mensaje. Generalmente un registro NdefRecord de un mensaje NDEF contiene al menos los siguientes cuatro campos:
- 3-bit TNF (Type Name Format): Campo que indica cómo se interpretará el mensaje. (tabla 3)
- Variable length type: Formato del registro.
- Variable length ID: Identificador único del registro.
- Variable length payload: Datos.
TNF_EMPTY |
Mensaje vacío |
TNF_WELL_KNOWN |
Mensaje NDEF correcto. De acuerdo con la especificación Record Type Definition (RTD)(Tabla 4). |
TNF_MIME_MEDIA |
Registro definido con un MIME-type, |
TNF_ABSOLUTE_URI |
URI |
TNF_EXTERNAL_TYPE |
Tipo especial definido en el NFC-Forum. |
TNF_UNKNOWN |
Desconocido |
TNF_UNCHANGED |
Trozo del mensaje. |
Tabla 3- TNF , definidos como constantes en Ndef Record
Cuando la parte correspondiente al TNF (Type Name Format) es de tipo WELL_KNOWN, significa que el mensaje NDEF contiene algunos de los siguientes tipos de información (RTD Record Type Definition):
RTD_TEXT |
Texto plano (acompañado del código ISO de idioma). |
RTD_URI |
Contiene una URI |
RTD_SMART_POSTER |
Contiene varios registros de información (URI, títulos en diferentes idiomas, acciones, etc), |
Tabla 4- RTD, definidos como constantes en Ndef Record
Antes de realizar cualquier acción con el API NFC, debemos solicitar los permisos oportunos para manipular este hardware. Para ello, añadimos la siguiente línea al descriptor de la aplicación (AndroidManifest.xml):
<uses-permission android:name="android.permission.NFC" />
Para detectar mensajes NDEF registramos componentes de tipo Broadcast Receivers, Actividades o incluso servicios. Probablemente nuestra aplicación estará preparada para procesar solamente algunos de los tipos de mensajes enumerados en el apartado anterior, por ello debe de incorporar un filtro para recibir sólo los que será capaz de tratar:
<intent-filter> <action android:name="android.nfc.action.NDEF_DISCOVERED"/> <category android:name="android.intent.category.DEFAULT"/> <data android:mimeType="text/plain" /> </intent-filter> |
Listado 1.1- Filtro TNF_WELL_KNOWN y RTD_TEXT
El ejemplo anterior muestra un filtro para recibir mensajes de tipo TNF_WELL_KNOWN y RTD_TEXT. A continuación vemos otros ejemplos para filtrar diferentes tipos de mensajes:
<intent-filter> <action android:name="android.nfc.action.NDEF_DISCOVERED"/> <category android:name="android.intent.category.DEFAULT"/> <data android:scheme="http" android:host="javahispano.org" android:path="/Test" /> </intent-filter> |
Listado 1.2- Filtro TNF_WELL_KNOWN y RTD_TEXT RTD_URI o RTD_SMART_POSTER
<intent-filter> <action android:name="android.nfc.action.NDEF_DISCOVERED"/> <category android:name="android.intent.category.DEFAULT"/> <data android:mimeType="x-urn-nfc-ext/fhnw.ch:selfserviceshop" /> </intent-filter> |
Listado 1.3- Filtro TNF_MIME_MEDIA
NOTA: En nuestros filtros de ejemplo hemos utilizado la acción android.nfc.action.NDEF_DISCOVERED, aunque existen otras acciones que componen el mecanismo de resolución de filtros NFC. No entraremos en detalles sobre este mecanismo, pero puede consultarlo en http://developer.android.com/guide/topics/nfc/nfc.html#dispatching
La aplicación (generalmente una Actividad, aunque también puede ser un Broadcast Receiver o un servicio) leerá el intent extrayendo de él los objetos definidos en la tabla 1 (NdefMessage y NdefRecord):
void resolveIntent(Intent intent) { String action = intent.getAction(); if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) { Parcelable[] rawMsgs = intent .getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES); NdefMessage[] msgs; if (rawMsgs != null) { msgs = new NdefMessage[rawMsgs.length]; for (int i = 0; i < rawMsgs.length; i++) { msgs[i] = (NdefMessage) rawMsgs[i]; } } else { // Unknown tag type byte[] empty = new byte[] {}; NdefRecord record = new NdefRecord(NdefRecord.TNF_UNKNOWN, empty, empty, empty); NdefMessage msg = new NdefMessage(new NdefRecord[] { record }); msgs = new NdefMessage[] { msg }; } } else { Log.e(TAG, "Unknown intent " + intent); finish(); return; } } |
Listado 1.4- Leer mensaje NDEF.
Tal y como comentábamos anteriormente, existen tags que pueden ser grabados fácilmente mediante nuestros dispositivos. El proceso será similar al de la lectura, tendremos un intent filter para detectar cuando el dispositivo está encima de un tag, pero en esta ocasión construiremos un objeto tipo NdefRecord que grabaremos en el objeto Tag recogido del intent. Por ejemplo podemos grabar texto en un tag, tal y como reflejan los siguientes métodos:
private NdefRecord createRecord() throws UnsupportedEncodingException { private void write(Intent intent) throws IOException, FormatException { String accion = intent.getAction(); Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); NdefRecord[] records = { createRecord() }; } |
Listado 1.5- Escribir un tag de tipo texto.
Como vimos anteriormente, podemos crear diferentes tipos de mensajes NDEF. Otro ejemplo consistiría grabar un tag con una URL:
void writeUrlToTag(Intent intent, String url) throws IOException, FormatException { String action = intent.getAction(); if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) { Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); Ndef ndefTag = Ndef.get(tag); NdefRecord rec = NdefRecordRtdUri.createRtdUriRecord(url); NdefMessage msg = new NdefMessage(new NdefRecord[] { rec }); ndefTag.connect(); ndefTag.writeNdefMessage(msg); ndefTag.close(); } } |
Listado 1.6- Escribir una URL en un tag.
Estos últimos listados, incluido el de la sección anterior (1.3), podrían formar parte de la aplicación NXP Tagwriter, que es un programa capaz de leer y escribir tags. Para escribir en un tag con esta herramienta seguiríamos los siguientes pasos:
Figura 7- Paso 1. Adquirir un tag NFC
Figura 8- Paso 2. Pantalla inicial del programa
Figura 9- Paso 3. Definir los datos a escribir. Por ejemplo una URL
Figura 10- Paso 4. Colocar el dispositivo encima del tag para comenzar el proceso de grabado
La siguiente vez que pasemos el dispositivo por encima del tag, podremos recoger y abrir la URL grabada previamente. Por ejemplo, tal y como muestra el blog http://buildcontext.com/blog/2011/nfc-tag-sticker-writing-programming-google-android-nexus-s:
Figura 11-Lectura de un tag con una URL
Figura 12- URL Ejecutada en el navegador
Android Beam permitirá intercambiar información “Per-to-Per” entre dos dispositivos Android. Un condicionante es que la aplicación que quiere transferir información debe encontrase en primer plano con el dispositivo sin bloquear. Cuando el terminal receptor se encuentre suficientemente cerca, aparecerá en la pantalla un mensaje tipo "Touch to Beam".
Podemos habilitar el uso de Android Beam de alguna de las dos formas siguientes:
A continuación se presenta un pequeño listado extraído de la aplicación NfcBeam, disponible entre los proyectos de ejemplo de eclipse:
package com.example.android.beam; * device * the AAR * code
|
Listado 1.6- Escribir una URL en un tag.
Android incorpora un API muy completo para dar soporte a cualquier mecanismo de comunicación NFC. En este tutorial tan sólo se ha realizado una pequeña introducción a este estándar, pero debe saber que existen muchos más conceptos de los aquí comentados, aunque esperamos que este artículo puede servirle para iniciarse en esta tecnología. Un impedimento en las prácticas con el API NFC, es que no es posible emularlo en un entorno de desarrollo, por ello debe disponer de un dispositivo real de última generación. Es más, en el caso de las prácticas de Android Beam, necesitará de dos dispositivos, para realizar una comunicación Per-to-Per.
Tal y como hemos querido reflejar en este artículo, NFC se trata de una tecnología con mucho futuro, y que está abriendo y abrirá nuevos mercados y líneas de negocio para nuestras empresas. Sin duda, no debemos dejar escapar la oportunidad de ahondar en ella, ni perder de vista su evolución.