Los servicios web son una tecnología interesante para las aplicaciones MIDP, ya que nos permiten acceder a información de nuestras aplicaciones corporativas de forma estándar sobre protocolo HTTP.
En una aplicación MIDP no nos servirá de nada obtener un documento HTML, ya que no es adecuado para presentarlo en la interfaz del móvil, y será muy complicado extraer de él información porque normalmente estará escrito en lenguaje natural y con un formato adecuado para su presentación, pero no para ser entendido por una máquina.
Los servicios web nos permiten obtener únicamente la información que necesitamos, pero no la presentación. Esta información vendrá codificada en XML de forma estándar. Podemos ver los servicios web como una web para aplicaciones, frente a los documentos HTML que serían una web para humanos.
El problema que encontramos con los servicios web es que el procesamiento de XML es bastante costoso en términos de procesamiento y memoria, lo cual lo hace poco adecuado para dispositivos muy limitados. Además la información codificada en XML ocupa mucho más espacio que utilizando la codificación binaria, por lo que tendremos que transferir una mayor cantidad de información a través de la red. Cuando la red es lenta y cara, esto es un gran inconveniente, que hace que los servicios web por el momento no se puedan utilizar en la práctica para este tipo de dispositivos.
Sin embargo, ya existen APIs que nos permiten utilizar esta tecnología desde móviles. Web Services API (WSA) nos permite crear clientes de servicios web SOAP desde dispositivos móviles. Podremos acceder a servicios existentes proporcionados por terceros, o crear nuestros propios servicios para acceder a nuestra aplicación.
Si queremos acceder a servicios proporcionados por terceros deberemos tener
en cuenta que WSA sólo soporta servicios de tipo document/literal
.
Si el servicio al que queremos acceder no es de este tipo (podemos consultar
esta información en su documento WSDL) como solución podremos
crearnos un servicio propio compatible con WSA que encapsule una llamada al
servicio proporcionado por terceros.
Vamos a ver como crear un servicio compatible con WSA. Para esto deberemos
especificar que debe ser de tipo document/literal
. Consideraremos
el caso de la creación del servicio con JWSDP 1.3.
Lo primero que deberemos hacer es implementar el servicio, creando una interfaz remota con los métodos que nos ofrece el servicio y una clase Java que implemente esta interfaz donde se definirá la funcionalidad del servicio.
Por ejemplo, podemos crear un servicio con la siguiente interfaz:
package es.ua.jtech.sw.hola;
import java.rmi.Remote; import java.rmi.RemoteException;
public interface HolaMundoIF extends Remote { public String saluda(String nombre) throws RemoteException; }
Y con la siguiente implementación de la anterior interfaz:
package es.ua.jtech.sw.hola;
import java.rmi.RemoteException;
public class HolaMundoImpl implements HolaMundoIF {
public String saluda(String nombre) throws RemoteException { return "Hola " + nombre; }
}
Para que el servicio creado sea del tipo document/literal
antes
de generar el servicio, deberemos generar un modelo donde se especifique el
tipo de servicio. Podemos generar el modelo con la herramienta wscompile
.
Para utilizar esta herramienta necesitamos crear un fichero de configuración
de nuestro servicio (config.xml
) como el siguiente:
<?xml version="1.0" encoding="UTF-8"?> <configuration xmlns="http://java.sun.com/xml/ns/jax-rpc/ri/config"> <service name="HolaMundoMovil" targetNamespace="http://jtech.ua.es/sw" typeNamespace="http://jtech.ua.es/sw" packageName="es.ua.jtech.sw.hola"> <interface name="es.ua.jtech.sw.hola.HolaMundoIF"/> </service> </configuration>
Podemos ejecutar la herramienta wscompile
desde línea de
comando o desde ant. Para utilizarla desde ant deberemos declarar en el fichero
build.xml
esta tarea y el classpath necesario para ejecutarla:
<!-- Propiedades -->
<property name="jwsdp.home" value="c:\\jwsdp-1.3"/> <!-- Classpath -->
<path id="compile.classpath"> <fileset dir="${jwsdp.home}/jwsdp-shared/lib"> <include name="*.jar"/> </fileset> <fileset dir="${jwsdp.home}/jaxp/lib"> <include name="*.jar"/> </fileset> <fileset dir="${jwsdp.home}/jaxp/lib/endorsed"> <include name="*.jar"/> </fileset> <fileset dir="${jwsdp.home}/jaxrpc/lib"> <include name="*.jar"/> </fileset> <fileset dir="${jwsdp.home}/saaj/lib"> <include name="*.jar"/> </fileset> <fileset dir="${jwsdp.home}/apache-ant/lib"> <include name="*.jar"/> </fileset> </path>
<!-- Definicion de tareas -->
<taskdef name="wscompile" classname="com.sun.xml.rpc.tools.ant.Wscompile"> <classpath refid="compile.classpath"/> </taskdef> <taskdef name="wsdeploy" classname="com.sun.xml.rpc.tools.ant.Wsdeploy"> <classpath refid="compile.classpath"/> </taskdef>
En la llamada a la tarea wscompile
deberemos especificar como
parámetro que el tipo de servicio es documentliteral
y el
fichero donde queremos que se genere el modelo:
<target name="generate"> <wscompile keep="true" define="true" features="documentliteral" base="." xPrintStackTrace="true" verbose="true" model="model.gz" config="config.xml"> <classpath> <path refid="compile.classpath"/> </classpath> </wscompile> </target>
Una vez tenemos el modelo generado, podemos crear un fichero descriptor de
servicios web (jaxrpc-ri.xml
) que utilice este modelo:
<?xml version="1.0" encoding="UTF-8"?> <webServices xmlns="http://java.sun.com/xml/ns/jax-rpc/ri/dd" version="1.0" targetNamespaceBase="http://jtech.ua.es/wsdl" typeNamespaceBase="http://jtech.ua.es/types" urlPatternBase="/ws">
<endpoint name="HolaMundo" displayName="Servicio HolaMundo" description="Servicio Web Hola Mundo" interface="es.ua.jtech.sw.hola.HolaMundoIF" model="/WEB-INF/model.gz" implementation="es.ua.jtech.sw.hola.HolaMundoImpl"/>
<endpointMapping endpointName="HolaMundo" urlPattern="/hola"/>
</webServices>
Una vez tenemos implementado el servicio, creado el modelo y el fichero descriptor de servicios web, organizaremos estos ficheros utilizando la estructura de directorios que deben seguir los servicios web de JWSDP:
/WEB-INF/web.xml /WEB-INF/jaxrpc-ri.xml /WEB-INF/model.gz /WEB-INF/classes/es/ua/jtech/sw/hola/HolaMundoIF.class /WEB-INF/classes/es/ua/jtech/sw/hola/HolaMundoImpl.class
Empaquetaremos toda esta estructura en un fichero WAR, y entonces podremos
utilizar la tarea wsdeploy
para generar el servicio a partir de
dicho fichero, de la misma forma que se hace con cualquier otro servicio web
en JWSDP. La única novedad en este caso ha sido que hemos incluido en
el servicio un fichero model.gz
donde se especifica el tipo de
servicio que queremos generar.
Si observamos el fichero WSDL generado para el servicio, podremos comprobar
que en el apartado binding
se especifica que es de tipo document
y literal
:
<binding name="HolaMundoIFBinding" type="tns:HolaMundoIF"> <operation name="saluda"> <input> <soap:body use="literal"/> </input> <output> <soap:body use="literal"/> </output> <soap:operation soapAction=""/>
</operation> <soap:binding transport="http://schemas.xmlsoap.org/soap/http"
style="document"/>
</binding>
Cualquier servicio que sea de este tipo se podrá ejecutar desde clientes
J2ME. De esta forma, para comprobar si un servicio es compatible con la implementación
de J2ME, podremos consultar su fichero WSDL y ver el tipo especificado en el
apartado binding
.
Para acceder al servicio desde nuestra aplicación deberemos crear una capa stub. Esta capa será la encargada de acceder al servicio, de forma que el desarrollador no tenga que preocuparse de implementar este acceso. Simplemente accederemos al stub para invocar los métodos del servicio como si se tratase de un objeto local, sin tenernos que preocupar del mecanismo de invocación subyacente.
WTK, a partir de su versión 2.1, incluye herramientas para la generación automática de este stub. Podremos generar un stub en nuestro proyecto utilizando la opción Project > Stub Generator ... :
Cuando pulsemos sobre dicha opción, se abrirá una ventana donde deberemos introducir los datos del servicio para el cual queremos generar el stub:
En esta ventana indicaremos la dirección donde se encuentra el documento WSDL del servicio al que vamos a acceder, y el paquete donde generaremos las clases del stub. Una vez hayamos introducido los datos pulsaremos OK y el stub se generará automáticamente.
Una vez tenemos generado el stub para acceder al servicio, podemos
utilizar este stub desde nuestra aplicación MIDP. El stub
generado será una clase con el nombre de la interfaz de nuestro servicio
añadiendo el sufijo _Stub
.
Esta clase implementará la misma interfaz que nuestro servicio, de forma que podremos instanciarla e invocar los métodos de este objeto para acceder a las operaciones del servicio como si se tratase de un acceso a un objeto local.
Por ejemplo, en el caso de nuestro servicio web "Hola Mundo", podemos acceder a él desde nuestra aplicación cliente de la siguiente forma:
HolaMundoIF hola = new HolaMundoIF_Stub(); try { String saludo = hola.saluda("Miguel"); } catch(RemoteException re) { // Error }
Bluetooth es una tecnología que nos permite conectar dispositivos próximos por radio, sustituyendo de esta forma a las conexiones por cable o infrarrojos. Además bluetooth nos ofrece distintos servicios como voz, fax, modem, conexión por puerto serie para transmisión de datos, etc.
No se debe ver bluetooth como un competidor de las redes inalámbricas 802.11b, ya que cada tecnología tiene un fin distinto. Bluetooth se utilizará para conectar pequeños dispositivos en un radio pequeño (unos 10 metros), mientras que las redes 802.11b se utilizarán para conectar dispositivos más potentes como ordenadores de sobremesa y portátiles en un área más grande. Nos podemos referir a las redes 802.11b como redes de área local (LAN), y a las redes bluetooth como redes de área personal (PAN).
Aunque el alcance normal de bluetooth son 10 metros, aumentando la potencia del punto de acceso bluetooth podemos aumentar su radio de alcance hasta 100 metros.
La tecnología bluetooth se puede utilizar para conectar dispositivos, como por ejemplo kits de manos libres, para intercambiar datos con otros dispositivos, para acceder a funcionalidades u obtener información de dispositivos de nuestro entorno, etc. Podemos crear una red de dispositivos que se conecten entre si utilizando esta tecnología.
Las redes que se crean utilizando bluetooth son redes "ad hoc", es decir, se crean dinámicamente. La comunicación entre distintos dispositivos hace que se cree un red de forma espontánea.
Los dispositivos bluetooth tienen la capacidad de "descubrir" otros dispotivos bluetooth de su entorno. De esta forma, los dispositivos pueden localizarse entre ellos y conectarse formando una red de forma dinámica, sin tener que haber creado previamente ninguna infraestructura para dicha red. Cada dispositivo tendrá un identificador bluetooth único con el que se identificará.
Las redes bluetooth se forman en grupos llamados piconets. Cada piconet es un grupo que puede contener hasta 8 dispositivos como máximo, en el que uno de ellos será el maestro, y los demás serán esclavos que estarán conectados a este maestro.
Figura 3. Topología de una red bluetooth
Un mismo dispositivo puede pertenecer a dos piconets distintas. Es más, puede que el dispositivo tenga una función distinta en cada piconet, por ejemplo puede actuar como maestro en uno de ellos, y como esclavo en el otro.
Cuando un dispositivo pertenece a varias piconets, estas piconets estarán conectadas entre ellas. Cuanto tenemos varias piconets conectadas de esta forma, todas ellas formarán lo que se conoce como una scatternet. En el caso de las scatternet, dado que existen dispositivos que están conectados al mismo tiempo a dos piconets, el ancho de banda de la red será menor. Además, hay muchos dispositivos que no soportan este tipo de redes.
Vamos a ver los protocolos que se utilizan en la comunicación mediante bluetooth.
Figura 4. Capas de bluetooth
Encontramos las siguientes capas:
Para las comunicaciones bluetooth utiliza multiplexado en el tiempo, para poder utilizar una comunicación full-duplex. Los datos se envían en ranuras de tiempo de 625ms cada una, el maestro utilizará las ranuras impares y los esclavos utilizarán las pares. Un paquete podrá enviarse en un máximo de 5 ranuras de tiempo (2745 bits de longitud).
Las capas por encima de L2CAP serán los distintos protocolos de comunicaciones que podremos utilizar en las aplicaciones que establezcan conexiones bluetooth. Los protocolos que podremos utilizar para comunicarnos mediante bluetooth son:
Cuando dos dispositivos se conectan por primera vez, por motivos de seguridad deben establecer un secreto compartido. Esto es lo que se conoce como pairing. Es decir, los usuarios de los distintos dispositivos que vayan a conectarse deben ponerse de acuerdo e introducir en ellos el mismo código, para de esta forma evitar que se realicen conexiones no deseadas a nuestro dispositivo. Una vez se ha realizado el pairing, este código se guarda en el dispositivo y ya no hará falta introducirlo para las sucesivas conexiones.
Una vez realizado el pairing de los dispositivos, estos pueden conectarse para formar una red bluetooth. Esta red se formará de la siguiente forma:
En las redes bluetooth el dispositivo maestro es el que establece los tiempos y el acceso en la piconet. Además hemos visto que tiene la responsabilidad de añadir a los esclavos a la piconet.
Podemos ver el maestro como el servidor de la red, que gestiona las conexiones con varios clientes que en este caso serían los esclavos. En las conexiones cliente/servidor normalmente el servidor permanece a la escucha esperando peticiones de conexión de los clientes. Sin embargo, en el caso de bluetooth ocurre al contrario, es el servidor (maestro) el que se encarga de solicitar a los clientes (esclavos) que se añadan a la piconet. Para ello estos esclavos deben haber ofrecido (publicado) el servicio necesario, para que el maestro pueda descubrirlo y conectarse a él.
En el caso de conexiones punto-a-punto, es indiferente quien se conecte como esclavo y quien como maestro. Esta decisión tendrá mayor relevancia en el caso de conexiones punto-a-multipunto, en las que todos los esclavos estarán conectados a un mismo maestro.
Vamos a ver ahora cómo establecer estas conexiones bluetooth utilizando las APIs de Java para Bluetooth (JSR-82). Esta API es el primer estándar no propietario que ha aparecido para desarrollar aplicaciones bluetooth utilizando este lenguaje. Podemos distinguir dos APIs independientes:
javax.bluetooth javax.obex
Esto es así porque OBEX puede funcionar sobre distintos tipos de conexiones como cable o infrarrojos. De esta forma la API OBEX no estará ligada a la de bluetooth, sino que será independiente, pudiendo así ser utilizada para trabajar con estro protocolo sobre los demás tipos de conexiones.
La API de bluetooth soporta los protocolos L2CAP, SDP y RFCOMM, pero no soporta comunicaciones de voz. Con la API OBEX también podremos utilizar este protocolo.
A partir de WTK 2.2 se incluye soporte para bluetooth en este kit de desarrollo. Para poder probar las aplicaciones bluetooth podemos usar esta versión que, además de incorporar la API JSR-82, incluye emuladores que simulan este tipo de conexiones. Podremos ejecutar varias instancias del emulador y simular conexiones bluetooth entre ellos, sin necesitar disponer de dispositivos bluetooth reales.
Lo primero que deberemos hacer para crear una red bluetooth es registrar los servicios de los esclavos, para que el maestro sea capaz de localizarlos y establecer una comunicación con ellos.
Deberemos asignar un UUID al servicio que vayamos a crear. Deberemos asegurarnos de que el UUID que generemos sea un identificador único que identifique el tipo de servicio que estamos implementando.
Un UUID es un número de 128 bits que tiene la siguiente forma (en hexadecimal):
UUID = 00000000-0000-1000-8000-0014e3a325f9 32 16 16 16 48
bits bits bits bits bits
Podemos distinguir varios bloques dentro de este número con distinto número de bits cada uno de ellos.
Para generar este UUID podemos utilizar herramientas como uuidgen
,
que suelen generar este número basándose en el instante de tiempo
actual o en generación de números aleatorios.
También podemos generar este número manualmente. Para garantizar que sea único, podemos poner como el último bloque de 48 bits el identificador de nuestro dispositivo bluetooth, y en el resto de bloques podremos poner lo que queramos, siempre que para dos servicios que hagamos no utilicemos el mismo UUID.
Una vez hayamos generado un UUID para nuestro servicio, podemos introducirlo como constante en el código de nuestra aplicación para tener acceso a él cuando sea necesario, tanto desde el cliente como desde el servidor.
public final static String UUID = "000000000000010008000123456789ab";
Para poder registrar nuestro servicio, lo primero que debemos hacer es establecer
nuestro dispositivo como descubrible. Para ello accederemos a nuestro dispositivo
local a través de un objeto LocalDevice
que obtenemos de
la siguiente forma:
LocalDevice ld = LocalDevice.getLocalDevice();
Con este objeto LocalDevice
podremos obtener datos de nuestro
dispositivo local como su dirección bluetooth o su nombre.
String bt_addr = ld.getBluetoothAddress(); String bt_name = ld.getFriendlyName();
Una vez tenemos acceso a este objeto, podremos cambiar el modo de ser descubierto
del mismo utilizando el método setDiscoverable
. Hay tres
modos de ser descubiertos:
DiscoveryAgent.GIAC
: Es el modo general que
se utiliza para que los dispositivos bluetooth sean descubiertos (GIAC). DiscoveryAgent.LIAC
: Se trata de un modo limitado
para acotar la búsqueda (LIAC, o también conocido como DIAC).
Será de utilidad cuando estemos en un entorno con muchos dispositivos
bluetooth y estemos buscando uno de ellos en concreto. Haciendo una analogía,
sería como cuando estamos buscando a un conocido entre una multitud,
y nuestro conocido levanta la mano para que le podamos encontrar rápidamente.DiscoveryAgent.NOT_DISCOVERABLE
: No descubrible.
Nuestro dispositivo no podrá ser localizado por ningún otro
dispositivo de nuestro entorno.Si no consiguiésemos hacer nuestro dispositivo localizable, lanzaremos una excepción para interrumpir el flujo del programa, ya que no podremos publicar servicios si nadie va a poder descubrirlos.
if (!ld.setDiscoverable(DiscoveryAgent.GIAC)) { // Lanzar excepcion, no se puede descubrir }
Una vez establecido el dispositivo local como descubrible, pasaremos a crear
y registrar el servicio. Deberemos definir una URL para nuestro servicio a partir
de su UUID. En la URL especificaremos el protocolo de comunicaciones que vamos
a utilizar. Para utilizar RFCOMM utilizaremos el protocolo btspp
(Bluetooth Serial Port Protocol), mientras que para L2CAP utilizaremos btl2cap
:
String url = "btspp://localhost:" + UUID;
Utilizando esta URL crearemos una conexión que será la encargada de atender para prestar dicho servicio:
StreamConnectionNotifier scn =
(StreamConnectionNotifier)Connector.open(url);
Con esto tendremos ya nuestro servicio registrado en el dispositivo. Podemos obtener un registro del servicio que será accesible tanto desde el lado del cliente como desde el servidor. En este objeto podremos añadir atributos que el cliente del servicio podrá leer.
ServiceRecord sr = ld.getRecord(scn);
Ahora que tenemos el servicio creado y registrado, deberemos atender las conexiones
que se produzcan a dicho servicio. Con acceptAndOpen
nos quedaremos
bloqueados esperando que se conecte algún cliente a nuestro servicio.
Una vez conectado obtendremos una conexión de tipo StreamConnection
,
a partir de la cual podremos abrir flujos de entrada y salida para comunicarnos
con el dispositivo remoto según el protocolo que hayamos establecido.
while(true) { StreamConnection sc = (StreamConnection)scn.acceptAndOpen();
// Se ha conectado un maestro InputStream is = sc.openInputStream(); OutputStream os = sc.openOutputStream(); // Enviar y recibir datos según el protocolo que establezcamos os.flush(); is.close(); os.close(); sc.close(); }
Para establecer una conexión con otro dispositivo, lo primero que necesitaremos es localizar (descubrir) dicho dispositivo.
Para localizar los dispositivos necesitaremos utilizar un objeto DiscoveryAgent
que obtendremos a partir del objeto LocalDevice
:
LocalDevice ld = LocalDevice.getLocalDevice(); DiscoveryAgent da = ld.getDiscoveryAgent();
La búsqueda se podrá hacer de tres formas diferentes:
startInquiry
se realiza una búsqueda de todos los dispositivos que haya actualmente
en nuestro entorno. Deberemos proporcionar un listener, que será
llamado cada vez que se encuentre un nuevo dispositivo.RemoteDevice[] dispositivos =
da.retrieveDevices(DiscoveryAgent.CACHED);
RemoteDevice[] dispositivos =
da.retrieveDevices(DiscoveryAgent.PREKNOWN);
Vamos a ver cómo descubrir los dispositivos que hay actualmente en nuestro
entorno con startInquiry
. Necesitaremos definir un listener que
herede de DiscoveryListener
e implemente los siguientes métodos:
public void deviceDiscovered(RemoteDevice rd, DeviceClass dc); public void inquiryCompleted(int tipo); public void servicesDiscovered(int transID, ServiceRecord[] servicios); public void serviceSearchCompleted(int transID, int estado);
Los dos primeros métodos se utilizarán durante el descubrimiento de dispositivos, mientras que los dos últimos se utilizarán para el descubrimiento de servicios de un dispositivo, como veremos más adelante.
El método deviceDiscovered
se invocará cada vez
que un dispositivo remoto sea descubierto. El código que introduciremos
en él normalmente será para añadir dicho dispositivo a
una lista de dispositivos descubiertos:
public void deviceDiscovered(RemoteDevice rd, DeviceClass dc) { remoteDevices.addElement(rd); }
A partir del objeto RemoteDevice
obtenido podremos obtener información
sobre el dispositivo remoto, como su nombre o su dirección bluetooth,
al igual que con LocalDevice
obteníamos información
sobre el dispositivo local.
Una vez haya terminado la búsqueda de dispositivos se invocará
el método inquiryCompleted
. En este método podremos
introducir código para que, en el caso de haberse completado la búsqueda
con éxito, nuestra aplicación pase a realizar la siguiente tarea
pendiente, que normalmente será la búsqueda de servicios que nos
ofrecen los dispositivos descubiertos.
Cuando hayamos creado el listener, podremos comenzar la búsqueda con
startInquiry
especificando el modo de búsqueda (GIAC o LIAC)
y el listener al que se notificarán los dispositivos encontrados:
da.startInquiry(DiscoveryAgent.GIAC, miListener);
Una vez terminada la búsqueda de dispositivos, necesitaremos buscar los servicios que nos ofrecen, para comprobar si está disponible el servicio que buscamos (el que tiene nuestro UUID).
Para cada dispositivo, podremos buscar los servicios identificados mediante una determinada UUID de la siguiente forma:
da.searchServices(null, new UUID[]{new UUID(UUID,false)},
(RemoteDevice)remoteDevices.elementAt(i),miListener);
Con esto comenzará la búsqueda de servicios del dispositivo especificado.
Cada vez que se encuentre uno o varios servicios nuevos, será invocado
el método servicesDiscovered
con una lista de servicios
descubiertos. Para cada servicio remoto encontrado tendremos un objeto ServiceRecord
.
Podemos añadir los servicios encontrados en una lista, igual que en el
caso de los dispositivos:
public void servicesDiscovered(int transID, ServiceRecord[] servicios) { for(int i=0;i<servicios.length;i++) { remoteServices.addElement(servicios[i]); } }
Cuando haya finalizado la búsqueda de servicios, se invocará
el método serviceSearchComplete
.
Como último paso, tendremos que establecer una conexión con alguno
de los servicios que hayamos localizado. Para ello utilizaremos el objeto ServiceRecord
obtenido correspondiente a dicho servicio.
ServiceRecord rs = (ServiceRecord)remoteServices.elementAt(0);
A partir de este objeto podremos obtener la URL necesaria para conectarnos al servicio:
String url = rs.getConnectionURL(
ServiceRecord.NOAUTHENTICATE_NOENCRYPT, true);
Con esta URL podremos crear una conexión de tipo flujo y abrir los correspondiente flujos de entrada salida para intercambiar datos con el servidor:
StreamConnection sc = (StreamConnection)Connector.open(url);
InputStream is = sc.openInputStream(); OutputStream os = sc.openOutputStream();
// Enviar y recibir datos según el protocolo que establezcamos os.flush();
os.close();
is.close(); sc.close();
En el caso de utilizar directamente el protocolo de bajo nivel L2CAP, utilizaremos una URL como la siguiente para crear la conexión:
String url = "btl2cap://localhost:" + UUID;
Cuando abramos la conexión con Connector.open
obtendremos
un objeto de tipo L2CAPConnectionNotifier
, y mediante el método
acceptAndOpen
de este objeto podremos aceptar conexiones L2CAP
de clientes. Cuando aceptemos una conexión de un cliente obtendremos
un objeto L2CAPConnection
con el que podremos realizar la comunicación.
Este objeto L2CAPConnection
tiene dos métodos send
y receive
con los que podremos enviar y recibir respectivamente
paquetes de datos L2CAP.
Como este protocolo no proporciona control de flujo, este control lo deberemos hacer nosotros si queremos asegurarnos de que los paquetes enviados no se han perdido.
Utilizaremos este protocolo cuando necesitemos una comunicación rápida o cuando la pérdida de paquetes no sea crítica para nuestra aplicación.