Conexión entre aplicaciones Android y servicios web .NET

Conexión entre aplicaciones Android y servicios web .NET
13/10/11


Introducción

Hoy en día es casi imprescindible el uso de Internet o de bases de datos alojadas en la red por parte de nuestas aplicaciones Android. Uno de los métodos más fáciles y comunes para realizar una comunicación hacia dichos servicios y bases de datos se realiza mediante el consumo de servicios web, los cuales en la mayoría de los casos actuan como una capa intermedia entre nuestra aplicación e Internet.Hoy explicaremos como enlazar nuestra aplicación con nuestros servicios web.

Nota:Si no sabeis como crear un servicio web bajo .NET os recomiendo que echeis un ojo a éste artículo en el que explico como crearlo.

Obtención e importación de la librería ksoap2

Lo primero de todo es descargar la librería que nos permitirá la conexión hacia el servicio web. Se trata de ksoap2 y desde aquí podemos descargar el .jar .Una vez descargado y creado un proyecto Android en Eclipse, en la carpeta /res del proyecto crearemos una carpeta llamada lib en la que guardaremos el .jar (para saber siempre donde buscarlo a la hora de añadirlo a nuestro proyecto).

Ahora procederemos a añadirlo como librería a nuestro proyecto. Suponiendo que utilizamos Eclipse, hacemos click derecho sobre el proyecto y vamos a Propiedades, en la sección Java Build Path nos movemos hasta la pestaña Libraries, damos a Add JARs y procedemos a seleccionar el jar descargado (Lo acabamos de poner dentro de la carpeta lib del proyecto).

Una vez que ya tenemos nuestro librería añadida estamos listos para usarla. Para ello deberemos importarla añadiendo esto a la lista de import de la clase que vaya a hacer uso de la librería:

import org.ksoap2.SoapEnvelope;
import org.ksoap2.serialization.PropertyInfo;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.HttpTransportSE;

Importada la librería vamos a ver como se utiliza. Los pasos para realizar una conexión son por regla general los siguientes:

  • Preparación de los datos necesarios para la conexión del servicio web (dirección del servicio web, nombre del método).
  • Preparación de los datos a enviar al servicio web (en el caso que hubiera).
  • Apertura de la conexión con los datos necesarios.
  • LLamada al método y obtención de los datos provenientes del servicio werb (en el caso que hubiera).
  • Tratamiento de dichos datos devueltos.

Nota: el último punto aunque no parezca importante si que hay que indicarlo para explicar mas tarde el procesamiento de datos complejos provenientes del servicio web.

Preparación de los datos para la conexión

Para llamar al servicio web necesitaremos cuantro cadenas de texto (String) que usaremos siempre para realizar las llamadas a los métidos del servicio web.

El primero es el denominado “namespace” cuyo valor nos indica el propio servicio web al crearlo. El namespace viene indicado en la cabecera del servicio web:

[WebService(Namespace = "http://ip:puerto/NombreDelServicio/")]

Por lo que la cadena que define el namespace sería:

private static String NAMESPACE = "http://ip:puerto/NombreDelServicio/";

El segundo es la URL del servicio web, que viene a ser la adición del nombre del archivo .asmx a la cadena que define el NAMESPACE:

private static String URL = NAMESPACE+"Service1.asmx";

El tercer dato que necesitamos es el nombre de método que guardaremos en la variable METHOD:

private static String METHOD;

El cuaro dato será el SOAPACTION, que será una combinación del NAMESPACE y del método al que llamemos:

private static String SOAPACTION = null;

Apertura de la conexión y adición de los datos

Definidos los datos iniciales veamos la preparación de datos en caso de que queramos enviar datos al servicio web.Para ello haremos uso de la clase SoapObject, que es un tipo de datos de encapsulación para poder enviar y recibir datos del servicio web (actua como un parseador de xml que es lo que se acaba enviando o recibiendo de un servicio web), y de la clase PropertyInfo que es una clase que nos permite añadir información al objeto SoapObject. Veamos un ejemplo.

METHOD = "method";
SoapObject request = new SoapObject(NAMESPACE, METHOD);
PropertyInfo pi1 = new PropertyInfo();
pi1.setName("variable1");
pi1.setValue(“a”);
request.addProperty(pi1);

Hay que tener mucho cuidado al añadir las variables, ya que el nombre de éstas debe coincidir con el nombre de las varibles del método al que llamamos en el servicio web. Como se ve lo que hacemos es crear un objeto PropertyInfo al que añadiremos el nombre y el valor de la variable que deseamos enviar.

Una vez que tenemos los datos a enviar, pasaremos a abrir la conexión. Para ello utilizaremos la clase SoapSerializationEnvelope y la clase HttpTransportSE:

SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(
SoapEnvelope.VER12);
envelope.dotNet = true; //indicamos que utilizaremos servicios .NET
envelope.setOutputSoapObject(request); //añadimos a la conexión el objeto SoapObject anteriormente creado
HttpTransportSE androidHttpTransport = new HttpTransportSE(URL);
androidHttpTransport.debug = true; //nos aseguramos así de que funcione siempre

LLamada al método y obtención de los datos provenientes del servicio web

Ya que tenemos abierta la conexión no queda mas que definir la variable SOAPACTION y realizar la llamada.

SOAPACTION = NAMESPACE + METHOD;
try {
	androidHttpTransport.call(SOAPACTION, envelope);
	SoapObject response = envelope.getResponse();
	//tratamiento de la respuesta
} catch (Exception e) {
	Log.d("error", e.getMessage().toString());
	return null;
}

De ésta manera llamamos al método del servicio web. Si el metodo del servicio web devuelve algún dato tendremos que tratarlo. En el caso de que nos encontremos con algún tipo complejo de datos (como una lista o de alguna clase que hayamos creado para tal propósito) deberemos tratarlo para recuperar la información. Para ello utilizaremos la clase SoapObject que encapsula los datos recibidos sean cual sean su naturaleza y nos proporciona una serie de métidos para poder extraer la información tal y como se devolvió desde el servicio web.

Tratamiento de datos complejos provenientes de un servicio web

Pongamos que el método del servicio web al que llamamos devuelve un List, el tratamiento de datos sería algo así:

SOAPACTION = NAMESPACE + METHOD;
List l = new ArrayList();
try {
	androidHttpTransport.call(SOAPACTION, envelope);
	SoapObject response = envelope.getResponse();
	//tratamiento de la respuesta
	if (response != null) {//comprobamos que la respuesta no esté vacía
                //recorremos el objeto
		for (int i = 0; i < response.getPropertyCount(); i++) {
                           //obtenemos el elemento i de la lista (sabemos que es un String)
                           l.add(response.getProperty(i).toString());
                           Log.d("elmento"+i+"devuelto",response.getProperty(i).toString());
		}
		return l;
	} else {
		return null;
	}
} catch (Exception e) {
	Log.d("error", e.getMessage().toString());
	return null;
}

Explicaré mejor el código de arriba. La variable response del tipo SoapObject obtiene el List que se devolvío por parte del servicio web y mediante un bucle utilizando la variable getPropertyCount() que nos devuelve el número de elementos que posee, recorremos el objeto como si recorrieramos el List. Cada elemento obtenido mediante el bucle es del tipo SoapObject, al cual simplemente haremos un toString() ya que sabemos que es un String. Hay que tener mucho cuidado a la hora del procesamiento de los datos devueltos ya que hay que estar totalmente seguro de que tipo de datos devuelve el método invocado.

Si los datos fueran mas complejo aún (imaginemos un List<List>) deberíamos extraer cada SoapObject del objeto devuelto por parte del servicio web (que a su vez sería un List) para, mediante otro bucle anidado, recorrer la segunda lista obteniendo ya si los valores de las cadenas de texto que contienet. Sería algo así:

if (response != null) {//comprobamos que la respuesta no esté vacía
        //recorremos el objeto
	for (int i = 0; i &lt; response.getPropertyCount(); i++) {
        //obtenemos el elemento i del List&lt; List&lt; String &gt; &gt;;
        SoapObject element = response.getProperty(i);
       /*recorremos el List&lt; String &gt; i */
        for(int j=0;j&lt; element.getPropertyCount();j++){
	        String a = element.getProperty(i).toString();
	        //tratamos la cadena a
	}
}

Y con esto daríamos por concluída la lección sobre conexiones a servicios web .NET en Android usando ksoap2. Éstas conexiones nos vendrán muy bien por ejemplo para acceder a datos que están alojados en bases de datos en la red o simplemente para realizar operaciones fuera del alcance de nuestro dispositivo.

Escrito por Jesús Manzano Camino


Puedes dejar un comentario, o referenciar este post desde tu sitio web.

Hay 11 comentarios en este post.

 
kike Enero 19, 2012 Reply

Hola buenas, primero gracias por el tutorial, tengo un problema y es que cuando creo0 la carpeta y guardo el jar dentro, me da error al proyecto, es mas me da error a otros proyectos incluso habiendo creado la carperta lib en un proyecto distinto. No hay forma de recuperar datos de una web usando las librerias que vienen con el sdk de android??
Saludos!

 
jmc Enero 19, 2012 Reply

Veamos si puedo ayudarte. Te cuento como añadí el jar a mi directorio lib: desde el propio Eclipse creé el directorio lib (click derecho sobre la carpeta res y nueva carpeta). Una vez creado, copié el .jar de la librería y la pegué también desde Eclipse (botón derecho sobre lib y pegar). Luego simplemente la referencié desde el apartado propiedades del proyecto (Java Build Path/Add Jar y buscar en el directorio del proyecto).
También puedes añadirla sin crear la carpeta simplemente referenciándola desde el apartado propiedades del proyecto y añadiéndola usando Add External JAR. El problema es que si se borra el .jar de tu directorio de archivos el proyecto no podrá referenciar el .jar y fallará.
Con lo que yo se no existe otra manera de acceder a servicios web sin usar la librería ksoap2.

 
kike Enero 19, 2012 Reply

Muchas gracias por todo, la incorpore como external jar, pero eso al subir mi aplicacion al market no va a dar problemas??
Saludos!

 
jmc Enero 20, 2012 Reply

Échale un ojo a https://github.com/mosabua/ksoap2-android/blob/master/LICENSE.txt donde puedes encontrar la licencia en la que se encuentra librería. Si te refieres a si habrá problema al ejecutar tu aplicación por estar añadida la librería como external jar no hay problema, una vez generado el .apk de tu aplicación no importa donde esté la librería. Si que importa a la hora de desarrollarlo (como te conté en la anterior respuesta).

 
JLuis Febrero 3, 2012 Reply

Gran tutorial amigo, gracias por el, te tengo una pregunta, en caso de querer obtener datasets, aplicaria el método de datos complejos que aquí manejas? de antemano gracias!

 
Jesús Manzano Camino Febrero 4, 2012 Reply

La verdad es que he usado muy poco los DataSet y según veo es una estructura de datos en la que se rellena con datos provenientes de una consulta a una BBDD con ciertos adaptadores de BBDD. Si estoy en lo cierto y habiendo buscado un poco por la red comentan que no es una buena idea devolver DataSets, por lo que yo te aconsejaría que crearas una pequeña estructura de datos en la que guardaras los resultados del DataSet, devolviéndolos en dicha estructura hacia la aplicación Android.

 
JLuis Febrero 8, 2012 Reply

Muchas Gracias por tu pronta respuesta Jesús, averiguare al respecto, slds.

 
jlLuis. Febrero 8, 2012 Reply

Jesús, tienes una idea de como puedo leer este xml, http://wstest.comuf.com/, lo coloque allí solo para mostrartelo, ignora lo demás, ya tengo la conexión hecha y todo lo demás, es un web sevice que realiza un login, le he dado mil vueltas y no logro mostrarlo, solo lo logro mostrarlo como lo que es un xml, agradeceria tu ayuda, gracias de antemano, JLuis.

 
Jesús Manzano Camino Febrero 8, 2012 Reply

Lo primero es preguntarte si la estructura del xml es siempre la misma. Si es así, existen librerías para parsear xml en Android, por lo que seguramente usando alguna de ellas podrás leer los xml procedentes. Échale un ojo a ésta página en la que vienen distintas bibliotecas para parsear los xml. Espero haberte podido ayudar.

 
JLuis. Febrero 8, 2012 Reply

Mucha gracias por tu rápida respuesta, el xml es variable, te explico a grandes rasgos lo que pretendo conseguir, en el layout principal se realiza un login (el cual ya hice) que recibe el Soapobject el cual es básicamente resultado de la búsqueda de, en este caso, un “alumno”, el alumno toma varias lecciones y se muestra su progreso en las lecciones, lecciones terminadas, lecciones pendientes o que puede tomar, en el xml se reciben básicamente para no congestionar el primer objeto a recibir tres tablas importantes: Account, con dos valores internos de tipo string, Lectures, con 8 valores internos, de tipo string, datatime, boolean e int, y Courses con 10 valores internos, de tipo int, datatime, string, lo demás es información para mostrarse como strings sobre lecciones para tomar, de allí la idea es conectarme nuevamente al web service para usar otro métodos para tomar lecciones, voy solo en el login! e intentado y leído de todo pero no he logrado ver un solo ejemplo que detalle la estructura de como obtener estos datos, siempre obtengo el xml que te mostré, de antemano, gracias por tu ayuda!

 
Jesús Manzano Camino Marzo 1, 2012 Reply

Mas o menos he intentado entender lo que me has contado. Con lo que me has contado y viendo la estructura que hay en el enlace del comentario anterior, podrías hacer perfectamente un algoritmo con bucle que leyera los datos, ya que aunque los datos sean variables comparten una estructura. Con la librería ksoap y mirando lo que puse en el artículo en cuanto a leer datos complejos creo que podrías leer bien los datos que necesitas.

Responde