lunes, 7 de mayo de 2012

Consumiendo Web Service SOAP-JSON con Android


Ahora toca el turno al tema de “Consumir Web Services en Android”. En esta primer parte del tutorial vamos a repasar algunos términos importantes sobre el tema de los web services, así como sus ventajas. También vamos hablar un poco de algunas librerías de terceros, las cuales utilizaremos en el desarrollo de nuestra practica para facilitar el manejo de algunas de las tecnologías a utilizar . Así que sin mas vamos a comenzar…
¿Que es un web service (ws) y para que nos sirve?
La mayoría de los sitios webs grandes (Google, Bancos, Facebook, Microsoft, etc.) usan aplicaciones que utilizan servicios webs (web services).  Un web service  es un conjunto de protocolos y estándares que sirven para intercambiar datos entre aplicaciones. Así que distintas aplicaciones de software desarrolladas en lenguajes de programación diferentes, y ejecutadas sobre cualquier plataforma, pueden utilizar los servicios web para intercambiar datos en redes de ordenadores como Internet, esto significa que los ws aportan interoperabilidad.
La interoperabildiad se consigue mediante la adopción de estándares abiertos. El servicio web que nosotros utilizaremos esta basado en un estandar abierto llamado SOAP (Simple Object Access Protocol) o XML-RPC (XML Remote Procedure Call).
SOAP define cómo dos objetos en diferentes procesos pueden comunicarse por medio de intercambio de datos XML (mensajes).
De manera mas clara, un ws es un conjunto de métodos que se pueden invocar por alguna aplicación para realizar una tarea compleja. La siguiente imagen representa un escenario de una aplicación cliente, que puede estar desarrollada en cualquier lenguaje y corriendo sobre diferentes plataformas. En ella se muestra como la aplicación esta consumiendo un servicio de una agencia de viajes y esta a su vez consume servicios de otros proveedores (Banco, Hotel, Linea area) para que la aplicación desarrollada pueda realizar muchas actividades con tan solo consumir los servicios y si es necesarios enviar solo algunos parámetros para ejecutar operaciones complejas.
 Ahora ya sabemos que al invocar un ws se están comunicando dos aplicaciones, y esto es posible, por el protocolo SOAP que realiza un intercambio de mensajes con estándar XML. Entre mas datos se estén intercambiando entre las aplicaciones, los mensajes crecerán mas y el tiempo de entrega se ira incrementando. Esto situación ha hecho que haya surgido una nuevo formato para el intercambio de datos con  el fin de hacer mas ligeros los mensajes de intercambio. Este nuevo formato es JSON.
JSON (JavaScript Object Notation) es un formato ligero para el intercambio de datos.  JSON es un subconjunto de la notación literal de objetos de JavaScript que no requiere el uso de XML. La simplicidad de JSON ha dado lugar a la generalización de su uso, especialmente como alternativa a XML. También es frecuente el uso de JSON y XML en la misma aplicación.
Con estos términos ya definidos y repasados, para los que no recordaban, ahora podemos comenzar a hablar de la aplicación que desarrollaremos en este tuto. Así que para comenzar iniciaremos descargando 2 librerías de terceros que nos ayudaran a simplificar el código necesario para consumir un web service SOAP con formato JSON:
  • Gson es una biblioteca Java que se puede utilizar para convertir objetos Java en su representación JSON. También se puede utilizar para convertir una cadena JSON a un equivalente de objetos Java. Descarga.
  • ksoap2-android es una biblioteca ligera y eficiente para web services basados en el protocolo SOAP. Descarga.
Ya descargando estos recursos estaríamos culminando la primera parte de este post, ahora nos estaremos metiendo de lleno tirar lineas de código para finalizar nuestra aplicación.

El web service (ws) que vamos a consumir fue realizado con tecnologias de ASP.NET con el objetivo de mostrar que los ws permiten la interoperabilidad con diferentes tecnologías de desarrollo y plataformas.
Para no involucrarnos en el desarrollo de ws  agregaremos al final del tutorial el código, y solo bastara publicarlo como una aplicación web dentro de nuestro servidor web, en este caso IIS ya que el servicio esta desarrollado con tecnologías de Microsoft.
Y por ultimo, les explico que realizará la apliación. Por medio de un botón invocaremos un web service (utilizando la librería ksoap2 android). El web service nos retornará una cadena en formato JSON la cual representa una lista de las versiones del Android OS. Ya retornada la cadena JSON, utilizaremos la librería Gson que nos ayudará a deserealizar esta cadena y pasarla a un objeto ArrayList para después mostrar la lista  en  un control ListView. Sin mas vamos a comenzar.
1) Creamos un proyecto de Android nombrado “ConsumirWS”.
2) Agregar y referenciar las librerias que nos pida
 3) Creamos nuestra UI.
4) Importamos todo lo necesario para consumir nuestro ws y deserealizar la cadena JSON que nos regresa.

import java.io.IOException;
import java.lang.reflect.Type;
import java.util.ArrayList;
 
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
 
import org.ksoap2.SoapEnvelope;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapPrimitive;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.HttpTransportSE;
import org.xmlpull.v1.XmlPullParserException;
 
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
5) Declaración de variables a nivel de clase. El codigo se encuentra comentado.
public class ConsumirWSActivity extends Activity {
 //Constantes para la invocacion del web service
 private static final String NAMESPACE = "http://tempuri.org/";
 private static String URL="http://192.168.0.231/EjemploWS/Service.asmx";
 private static final String METHOD_NAME = "getAllAndroidOS";
 private static final String SOAP_ACTION ="http://tempuri.org/getAllAndroidOS";
 
 //Declaracion de variables para consuymir el web service
 private SoapObject request=null;
 private SoapSerializationEnvelope envelope=null;
 private SoapPrimitive  resultsRequestSOAP=null;
 
 //Declaracion de variables para serealziar y deserealizar
 //objetos y cadenas JSON
 Gson gson ;
 
 //Variables para manipular los controles de la UI
 Button btn;
 ListView lsvAndroidOS;
 
 /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }  
 
}
6) Se hace la referencia a los controles de la UI y se implementa el evento click del boton que invoca al ws. Tambien añadimos el codigo que se encarga de invocar al ws. El codigo se encuentra comentado.
/** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
 
        lsvAndroidOS = (ListView)findViewById(R.id.lst);
        btn = (Button)findViewById(R.id .btn);
        btn.setOnClickListener(new OnClickListener() {
 
   @Override
   public void onClick(View v) {
    // TODO Auto-generated method stub
 
//    Se crea un objeto SoapObject para poder realizar la peticion
//    para consumir el ws SOAP. El constructor recibe
//    el namespace. Por lo regular el namespace es el dominio
//    donde se encuentra el web service
    request = new SoapObject(NAMESPACE, METHOD_NAME);
 
//    Se crea un objeto SoapSerializationEnvelope para serealizar la
//    peticion SOAP y permitir viajar el mensaje por la nube
//    el constructor recibe la version de SOAP
    envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
    envelope.dotNet = true; //se asigna true para el caso de que el WS sea de dotNet
 
    //Se envuelve la peticion soap
    envelope.setOutputSoapObject(request);
 
    //Objeto que representa el modelo de transporte
    //Recibe la URL del ws
    HttpTransportSE transporte = new HttpTransportSE(URL);
 
    try {
     //Hace la llamada al ws
     transporte.call(SOAP_ACTION, envelope);
 
     //Se crea un objeto SoapPrimitive y se obtiene la respuesta
     //de la peticion
     resultsRequestSOAP = (SoapPrimitive)envelope.getResponse();
 
    } catch (IOException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
    } catch (XmlPullParserException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
    }
 
    //Almacenamos el resultado en un String ya que lo que represa
    //el ws es una cadena json, representando una lista AndroidOS
    //de objetos del tipo
    String  strJSON = resultsRequestSOAP.toString();
 
    crearLista(strJSON);
   }
  });
 
    }
7) Agregamos el metodo que se encarga de deserealizar la cadena JSON y mostrar el resultado en un control ListView. El codigo se encuentra comentado.
/**
     * Metodo que recibe una cadena JSON y la convierte en una lista
     * de objetos AndroidOS para despues cargarlos en la lista
     * @param strJson (String) Cadena JSON
     */
    private void crearLista(String strJson){
  //se crea el objeto que ayuda deserealizar la cadena JSON
  gson = new Gson();
 
  //Obtenemos el tipo de un ArrayList
  Type lstT = new TypeToken< ArrayList>(){}.getType();
 
  //Creamos una objeto ArrayList
  ArrayList arrListAOS = new ArrayList();
 
  //Deserealizamos la cadena JSON para que se convertida a un ArrayList
  arrListAOS = gson.fromJson(strJson, lstT);
 
  //Asignaos la ArrayList al controls ListView para mostrar
  //la lista de SO Android que se consumieron del web service
  lsvAndroidOS.setAdapter(new ArrayAdapter
  (getApplication(), android.R.layout.simple_list_item_1, arrListAOS));
 
 }
8) Por ultimo en nuestro archivo Manifest hay que agregar el permiso de internet a la aplicación.
9) Con esto finalizariamos el desarrollo de la aplicación solo falta depurar y probar. Es muy importante que el ws se encuentre publicado en el servidor IIS y que la pc donde se este desarrollando tenga internet.
Con esto finalizamos el tema de Consumir Web Service SOAP.  

13 comentarios:

  1. Mínimo hubieras respetado la autoria del post, es de uno de mis editores, no me enoja ya que quiere decir que nuestro trabajo te gustó pero reitero, a ver si agregas el link de la fuente de este post que copiaste y cual. saludos.

    ResponderEliminar
  2. Uh! si, tienes toda la razon y te pido disculpas. Es un error mio y muy mala practica, la de no poner las autorias de las fuentes. Sin duda que tengo que implementar poner la autoria o un link a la fuente. Quiero que sepas, que pido perdon y es algo que voy a reparar. Mi respeto a su trabajo, de verdad, porque es muy bueno. Saludos cordiales.

    ResponderEliminar
  3. Excelente bloq, PERO PORQUE no publico una imagen de la ejecucion de la Aplicacion? para asi poder saber el resultado final?

    ResponderEliminar
    Respuestas
    1. Gracias Juan por la visita. El articulo y el codigo fue tomado de Condesa Androideity. Te recomiendo fuertemente que visites androideity.com , es uno de los sitios de referencia mia, que utilizo para aprender algunos temas y reflejarlos aquì como un "backup mio". Saludos

      Eliminar
  4. Hola amigo gracias por el post me ha servido mucho... ahora bien de casualidad no sabes como hacer consumo de webservices desde blackberry esque lo necesito para un proyecto universitario pero aun no encuentro nada. solo se que el unico q soporta es javascript y me sale facil hacerlo con soap y json pero quisiera algun ejemplo.. Saludos

    ResponderEliminar
  5. Como puedo enviar una imagen por servicio web.

    ResponderEliminar
    Respuestas
    1. Sencillo, tienes que serializar la imagen, por ejemplo usa base64, tomas la imagen en el web service lado servidor la codificas a base64 y luego del lado cliente la decodificas para obtener nuevamente la imagen, alguna vez hizo yo eso.

      Eliminar
  6. Hola buen día,

    Por casualidad sabes como consumir un werbservice que retorna un objeto, por ejemplo:
    Objeto Persona
    Atributos:
    long id;
    String nombre.

    Estoy intentándolo pero siempre me tira un error al consumir el web y ejecutar esta parte:

    resultsRequestSOAP = (SoapPrimitive)envelope.getResponse();

    Gracias de antemano

    ResponderEliminar
  7. Mi estimado podrías por favor actualizar el link de las fuentes, este tema que has posteado referente a Android me interesa bastante... Muchas gracias, saludos.

    ResponderEliminar
  8. hola
    relice paos a paso y me vota un error en esta line de codigo

    Type lstT = new TypeToken<ArrayList>(){}.getType();

    TypeToken cannot be resolved to a variable

    que tengo que hacer crear una variable porfa ayudame para ver si me sale ..

    ResponderEliminar
  9. hola hermanaso tu tuto esta genial te tengo una pregunta puesto q soy novato en cosas de java yo quiero hacer lo siguiente se generaran numeros aleatorios y quiero q cada vez q el numero sea superior a 120 este inserte una serie de datos sin necesidad de ejecutar un boton o algo no se si me explico quiero hacer inserciones a la base de datos sin necesidad de usar un boton para ejecutar la accion si no cuando se genere un numero superior a 120 no se si tengas algun ejemplos de esto realmente me interesa si tienes te dejo mi correo jose_xp_799@hotmail.com lo q quiero son ejemplos de insercion sin necesidad de usar un boton :D

    ResponderEliminar
  10. Hola, primero que nada excelente tuto, tengo algunas dudas ya he hecho este tipo de conexion en una aplicacion, cuando lo hice tenia una base de datos MySQL y mediante un webservice (php) me conectaba y jalaba los datos a un ListView que tenia en mi aplicacion.. el problema es que cuando lo emulaba en mi celular 2.3.6 funcionaba correctamente pero en un android 4.1.1 no se conecta y me cacha la excepcion de la conexion!! tienes alguna idea de como puedo solucionar este problema

    ResponderEliminar
  11. hola
    relice paso a paso y me vota un error en esta line de codigo

    Type lstT = new TypeToken(){}.getType();

    TypeToken cannot be resolved to a variable

    que tengo que hacer crear una variable contestame porfavor

    ResponderEliminar