Consumir Web Services Soap en Android (parte 2)
En esta segunda parte vamos a consumir el Servicio Web que hicimos en .Net en la parte 1. Utilizaremos soap para poder establecer la comunicación con el servicio y poder realizar las transacciones.
Antes de empezar con la segunda parte veamos de que se compone un objeto soap:
Requisitos para realizar este tutorial:
1. Importar las librerias ksoap2 que se descargaron de la siguiente manera:
2. Crear un proyecto nuevo en eclipse con nombre "VisitasConexionWebService", agregar 2 layouts con nombres activity_main.xml y consultar_registros.xml
Nota: No se explica como diseñar los layouts porque es irrelevante para este tutorial, el código fuente de los xml se dará al final en un enlace de descarga.
Básicamente activity_main.xml tiene 4 spinners (comboBox), 2 EditText y 2 botones.
consultar_registros.xml tiene 2 EditText, 2 botones y 1 ListView.
Soap para consultar
3. Crear una clase "Vendedor.java"
- Eclipse ADT Bundle
- Librerías ksoap2, descargar la ultima versión de aquí
- Un Servicio Web publicado (ver parte 1)
Empezamos:
1. Importar las librerias ksoap2 que se descargaron de la siguiente manera:
- Click derecho sobre el proyecto, escoger Build Path/Configure buld path/Libreries/Add externals Jars y escoger el archivo .jar que contiene la libreria ksoap2.
- Luego ir a Order and Export, dar check a la libreria ksoap y finalmente click en OK.
2. Crear un proyecto nuevo en eclipse con nombre "VisitasConexionWebService", agregar 2 layouts con nombres activity_main.xml y consultar_registros.xml
activity_main.xml |
consultar_registros.xml |
Nota: No se explica como diseñar los layouts porque es irrelevante para este tutorial, el código fuente de los xml se dará al final en un enlace de descarga.
Básicamente activity_main.xml tiene 4 spinners (comboBox), 2 EditText y 2 botones.
consultar_registros.xml tiene 2 EditText, 2 botones y 1 ListView.
Soap para consultar
3. Crear una clase "Vendedor.java"
package com.example.visitasconexionwebservice; import java.util.ArrayList; import org.ksoap2.SoapEnvelope; import org.ksoap2.serialization.SoapObject; import org.ksoap2.serialization.SoapSerializationEnvelope; import org.ksoap2.transport.HttpTransportSE; public class Vendedor { //Propiedades y constructores public Integer IdVendedor; public String Nombres; public Vendedor(Integer idvendedor, String nombres) { this.IdVendedor=idvendedor; this.Nombres=nombres; } public Vendedor(){} /*Metodos*/ //El spinner muestra lo que retorne este método public String toString(){ return Nombres; } //getId captura el id del item seleccionado en el spinner public int getId() { return IdVendedor; } //Devuelve lista que se usa para llenar el spinner vendedor public ArrayListConsultarVendedores() { ArrayList lista = new ArrayList (); //Estos datos los proporciona el webService final String NAMESPACE = "http://tempuri.org/"; final String URL="http://10.0.2.2/Visitas/WebServiceVisitas.asmx"; //para pruebas en el AVD //final String URL="http://192.168.1.11/Visitas/WebServiceVisitas.asmx"; //para llevar la apk a produccion final String METHOD_NAME = "ConsultarVendedores"; final String SOAP_ACTION = "http://tempuri.org/ConsultarVendedores"; //Se instancia un objeto soap pasandole el namespace y el metodo del webservice a consumir SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME); //Se instancia un objeto envelope y se define que version de soap se usará (10,11,12) SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11); envelope.dotNet = true; //indica si el web service fue desarrollado en .NET envelope.setOutputSoapObject(request); //establece la comunicacion por http //recordar habilitar permisos de internet HttpTransportSE transporte = new HttpTransportSE(URL); try { transporte.call(SOAP_ACTION, envelope); //ejecuta la llamada SoapObject resSoap =(SoapObject)envelope.getResponse(); //obtiene respuesta //lo siguiente es para recorrer, leer y guardar la respuesta en una lista int nPropiedades = resSoap.getPropertyCount(); for (int i = 0; i < nPropiedades; i++) { SoapObject ic = (SoapObject)resSoap.getProperty(i); lista.add(new Vendedor( Integer.parseInt(ic.getProperty("IdVendedor").toString()), ic.getProperty("Nombres").toString())); } } catch (Exception e) { e.printStackTrace(); } return lista; } }
Destacar lo siguiente:
final String NAMESPACE = "http://tempuri.org/"; final String URL="http://10.0.2.2/Visitas/WebServiceVisitas.asmx"; //final String URL="http://192.168.1.11/Visitas/WebServiceVisitas.asmx"; final String METHOD_NAME = "ConsultarVendedores"; final String SOAP_ACTION = "http://tempuri.org/ConsultarVendedores";
Los datos de esas variables las proporciona el webservice, se puede observar de donde tomarlos en la siguiente imagen:
Nota 1: Para probar con el Android Virtual Device, se debe setear la URL apuntando a la ip 10.0.2.2 ya que no reconoce con localhost ni con 127.0.0.1 como se suele hacer. Cuando se pruebe la apk en un mobil android, se debe poner la dirección ip del servidor que contiene el webservice.
Nota 2: Si el método del servicio requiere pasarle una propiedad como parámentro, se debe agregar una propiedad al objeto soap de nombre "request":
request.addProperty("IdVendedor", IdVendedor.toString());
Soap para grabar
4. Crear una clase "Visita.java" e implementar la interfaz KvmSerializable, se implementan los métodos:
- getproperty()
- getPropertyCount()
- getPropertyInfo()
- setProperty()
@Override public Object getProperty(int arg0) { switch(arg0) { case 0: return this.IdVisita; case 1: return this.IdVendedor; case 2: return this.IdRuta; case 3: return this.IdCliente; case 4: return this.IdTipoVisita; case 5: return this.Resultado; case 6: return this.Comentario; } return null; } @Override public int getPropertyCount() { return 7; } @Override public void getPropertyInfo(int indice, Hashtable arg1, PropertyInfo info) { switch(indice) { case 0: info.type = PropertyInfo.INTEGER_CLASS; info.name = "IdVisita"; break; case 1: info.type = PropertyInfo.INTEGER_CLASS; info.name = "IdVendedor"; break; case 2: info.type = PropertyInfo.INTEGER_CLASS; info.name = "IdRuta"; break; case 3: info.type = PropertyInfo.INTEGER_CLASS; info.name = "IdCliente"; break; case 4: info.type = PropertyInfo.INTEGER_CLASS; info.name = "IdTipoVisita"; break; case 5: info.type = PropertyInfo.STRING_CLASS; info.name = "Resultado"; break; case 6: info.type = PropertyInfo.STRING_CLASS; info.name = "Comentario"; break; default:break; } } @Override public void setProperty(int indice, Object val) { switch(indice) { case 0: IdVisita = Integer.parseInt(val.toString()); break; case 1: IdVendedor = Integer.parseInt(val.toString()); break; case 2: IdRuta = Integer.parseInt(val.toString()); break; case 3: IdCliente = Integer.parseInt(val.toString()); break; case 4: IdTipoVisita = Integer.parseInt(val.toString()); break; case 5: Resultado = val.toString(); break; case 6: Comentario = val.toString(); break; default: break; } }
5. Definir el método grabar de la siguiente manera:
public boolean Grabar(boolean esNuevo) { boolean resul = true; final String NAMESPACE = "http://tempuri.org/"; final String URL="http://10.0.2.2/Visitas/WebServiceVisitas.asmx"; //final String URL="http://192.168.1.11/Visitas/WebServiceVisitas.asmx"; final String METHOD_NAME = "GrabarVisita"; final String SOAP_ACTION = "http://tempuri.org/GrabarVisita"; SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME); //para cuando se va a pasar un objeto no primitivo PropertyInfo pi = new PropertyInfo(); pi.setName("Visita"); //nombre del objeto a pasar pi.setValue(this); //pasar los valores pi.setType(this.getClass());//pasar el tipo del objeto request.addProperty("EsNuevo", esNuevo); //agregar propiedad 1 request.addProperty(pi); //agrega propiedad 2 de tipo Visita SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11); envelope.dotNet = true; envelope.setOutputSoapObject(request); //mapea o hace matching entre el objeto Visita de java y //el objeto VisitaInfo de Visual Basic.Net envelope.addMapping(NAMESPACE, "VisitaInfo", this.getClass()); HttpTransportSE transporte = new HttpTransportSE(URL); try { transporte.call(SOAP_ACTION, envelope); SoapPrimitive resultado_xml =(SoapPrimitive)envelope.getResponse(); String res = resultado_xml.toString(); //verifica si se grabó correctamente if(!res.equals("true")) resul = false; } catch (Exception e) { resul = false; } return resul; }
Nota 1: lo nuevo en el método grabar es que al request se le agrega un una propiedad de tipo Visita, y luego hay que hacer un matching entre nuestro objeto java Visita y el objeto VB.Net VisitaInfo.
Nota 2: El matching no puede realizarse si la clase no tiene implementada la interfaz Kmserializable y las propiedades de los objetos deben encajar en ambos lenguajes así como sus tipos independientemente.
6. Consideraciones en MainActivity.java:
Hay que crear cierta programación para que todo funcione bien, ya que da error porque no se puede ejecutar operaciones de larga duración en el hilo principal (transacciones con webservice) por políticas estrictas, para solucionar esto, hay que cambiar la política:
//Necesario para que no salga error en operaciones de larga duracion en el hilo principal if (android.os.Build.VERSION.SDK_INT > 9) { StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build(); StrictMode.setThreadPolicy(policy); }
Ese código se debe escribir dentro del método onCreate. Caso contrario hay que orientar el código a operaciones en hilos de ejecución (Threads) en un posterior tutorial se dará una explicación.
A este punto ya se ha explicado el funcionamiento de soap y como usarlo. los demás métodos del resto de clases son similares, se deja a mano de la persona que sigue este tutorial la tarea de terminar la aplicación, de igual manera el código fuente completo se pondrá en un enlace al final.
7. Corrrer la aplicación, debe quedar algo como esto:
Pantalla Principal |
Pantalla de consulta |
Descargar Fuentes de los proyectos .Net, Android java y base de datos: a través de este link
Estimado estaba mirando tu ejemplo y no puedo levantar la base de datos por me marca que tiene errores el bak.
ResponderEliminarHola, puede ser la versión del SSMS, acabo de actualizar el skydrive y ahora también incluyo un archivo de script para que lo ejecutes, te crea la base de datos, estructuras, y registros.
EliminarHola puedees pasarme el link ? ya no esta disponible el que esta publicado =/
ResponderEliminarClaro, aquí está: https://1drv.ms/u/s!AlmTdpYG-a-ahHPGFbY2tVuXGpO2
Eliminargracias por el aviso, voy a actualizar el link.
Amigo, muchas gracias por compartir, podrias indicarme como llenar un spinner desde un webservice
ResponderEliminar