Scroll to top

Spanish (Español) translation by Manuel (you can also view the original English article)

En este tutorial, aprenderás a consumir servicios web usando la popular librería kSOAP en una aplicación Android. kSOAP es una librería de renombre amada por los desarrolladores que tienen la necesidad de analizar mensajes WSDL (Web Service Definition Language) y SOAP (Simple Object Access Protocol).


Introducción

La biblioteca kSOAP es una biblioteca cliente SOAP elegante, ligera y eficiente. La biblioteca es de código abierto, fácil de usar, y puede ahorrarte la molestia de codificar un parser personalizado. Es una de las bibliotecas SOAP más fiables que existen actualmente y se actualiza con frecuencia, lo que es una buena señal para cualquier proyecto de código abierto.

A menudo es arriesgado integrar software de código abierto (OSS) en un proyecto, ya que puede causar problemas imprevistos en el futuro. Busca siempre los comentarios y críticas de otros desarrolladores que hayan utilizado la biblioteca. Si el proyecto no está en desarrollo activo, puede ser mejor buscar una solución alternativa.

El objetivo de este tutorial es que te familiarices con la librería kSOAP. Para la demostración, utilizaremos un servicio web sencillo de W3Schools. El servicio web es un convertidor de Fahrenheit a Celsius. El servicio web acepta un valor en grados Fahrenheit y responde con el valor equivalente en grados Celsius. Vamos a recorrer el ejemplo paso a paso. Al final de este tutorial, mostraremos el resultado en el dispositivo del usuario.


1. Inicio de la actividad

Paso 1: Configuración del proyecto

Comienza un nuevo proyecto Android y configúralo a tu gusto. Siéntete libre de usar tu IDE favorito, pero para este tutorial usaré IntelliJ IDEA.

En el archivo de manifiesto del proyecto, hay que especificar que la aplicación puede conectarse a Internet. También vamos a especificar la versión del SDK de destino, así como la versión mínima del SDK. Echa un vistazo al archivo de manifiesto que se muestra a continuación.

1
<uses-sdk android:minSdkVersion="7" android:targetSdkVersion="17"/>
2
<uses-permission android:name="android.permission.INTERNET"/>

Paso 2: Descarga de kSOAP

Intenta siempre utilizar la última versión estable de una biblioteca o actualiza la biblioteca que está utilizando en una aplicación después de que se haya publicado una actualización importante. Es una buena práctica mantener actualizadas las dependencias de un proyecto por diversas razones, como la seguridad y la corrección de errores. En este tutorial, utilizaremos la versión 3.1.1 de la biblioteca kSOAP, que puedes encontrar en la página de descargas del proyecto. Después de descargar la biblioteca kSOAP, añádela a la carpeta libs de tu proyecto.

Paso 3: Añadir kSOAP a tu proyecto

Para utilizar la biblioteca kSOAP en tu proyecto, tendrás que añadirla a tu proyecto. Te mostraré cómo añadirla usando IntelliJ IDEA. Los pasos pueden ser ligeramente diferentes si estás usando un IDE diferente, pero la idea es la misma. En IntelliJ IDEA, selecciona Estructura del proyecto... en el menú Archivo, abre el panel Módulos, haz clic en el botón más en la parte inferior del panel derecho y selecciona biblioteca. Navega hasta la carpeta libs y selecciona la librería kSOAP. Echa un vistazo a las dos imágenes de abajo para aclararlo.

La biblioteca kSOAP debería ser ahora visible como una dependencia de tu proyecto. Haz clic en la casilla junto a la biblioteca kSOAP para añadirla a tu proyecto. Ahora que hemos añadido la biblioteca a nuestro proyecto, es el momento de ponerla en práctica. Si estás usando IntelliJ IDEA, tu proyecto debería ser similar al que se muestra a continuación.


2. Servicio web de W3Schools

El uso de la biblioteca kSOAP para consumir un servicio web implica una serie de pasos. Sin embargo, antes de sumergirnos de lleno en el uso de la biblioteca kSOAP, es útil contar un poco más sobre el servicio web que vamos a utilizar.

Visita la página web del servicio web de W3Schools que utilizaremos en este tutorial. Verás que hay dos operaciones, CelsiusToFahrenheit y FahrenheitToCelsius. El nombre de cada operación se explica por sí mismo. La URL del servicio web es la URL base que utilizaremos para conectarnos al servicio web.

Si seleccionas una operación en el sitio web de W3Schools, se te muestra un ejemplo de la solicitud que espera el servicio web, así como la respuesta del servicio web. Echa un vistazo al siguiente fragmento de código, que es un ejemplo de solicitud que espera el servicio web. Presta atención a la acción SOAPAction en el fragmento de código. Lo usaremos un poco más adelante en este tutorial.

1
POST /webservices/tempconvert.asmx HTTP/1.1
2
Host: www.w3schools.com
3
Content-Type: text/xml; charset=utf-8
4
Content-Length: length
5
SOAPAction: "http://www.w3schools.com/webservices/FahrenheitToCelsius"
6
<!--?xml version="1.0" encoding="utf-8"?-->
7
string

El siguiente fragmento de código muestra un ejemplo de respuesta del servicio web.

1
HTTP/1.1 200 OK
2
Content-Type: text/xml; charset=utf-8
3
Content-Length: length
4
<!--?xml version="1.0" encoding="utf-8"?-->
5
string

3. Uso de kSOAP

Paso 1: Crear un sobre

Lo primero que tenemos que hacer es crear un sobre SOAP utilizando la clase SoapSerializationEnvelope (org.ksoap2.serialization.SoapSerializationEnvelope), que tienes que importar de la biblioteca kSOAP. Mira el siguiente fragmento de código, en el que he inicializado una instancia de la clase SoapSerializationEnvelope.

1
SoapSerializationEnvelope envelope = getSoapSerializationEnvelope(request);

El método getSoapSerializationEnvelope no está definido en la biblioteca kSOAP. Es un método de ayuda que he creado para facilitar el trabajo con la biblioteca kSOAP. El método devuelve el sobre SOAP que necesitamos para el resto del ejemplo. Echa un vistazo a la implementación de getSoapSerializationEnvelope a continuación.

1
private final SoapSerializationEnvelope getSoapSerializationEnvelope(SoapObject request) {
2
    SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
3
    envelope.dotNet = true;
4
    envelope.implicitTypes = true;
5
    envelope.setAddAdornments(false);
6
    envelope.setOutputSoapObject(request);
7
8
    return envelope;
9
}

El método getSoapSerializationEnvelope acepta una instancia de SoapObject, que es la solicitud. Veremos cómo crear la petición en unos minutos. Cuando se crea una instancia de la clase SoapSerializationEnvelope, la versión de SoapEnvelope se establece pasando SoapEnvelope.VER11, que indica a la biblioteca kSOAP que usaremos SOAP 1.1. Establecemos la propiedad dotNet del sobre a true, ya que el servicio web que vamos a consumir se ejecuta en el marco .NET de Microsoft.

1
envelope.dotNet = true;

Paso 2: Configuración de la envolvente

Ahora es el momento de configurar el sobre SOAP estableciendo la información de la solicitud. Comienza importando la clase SoapObject (org.ksoap2.serialization.SoapObject) y echa un vistazo al fragmento de código que aparece a continuación para ver cómo configurar la envolvente. Comenzamos creando una instancia de la clase SoapObject, que requiere dos parámetros, un espacio de nombres y un nombre de método. Puedes añadir propiedades adicionales a la solicitud utilizando el método addProperty como se muestra a continuación. En nuestro ejemplo, utilizo addProperty para añadir el valor en grados Fahrenheit a la solicitud.

1
String methodname = "FahrenheitToCelsius";
2
SoapObject request = new SoapObject(NAMESPACE, methodname);
3
request.addProperty("Fahrenheit", fValue);

Te estarás preguntando de dónde viene NAMESPACE. Es una cadena estática privada que se define en otra parte de la aplicación como puedes ver a continuación.

1
private static final String NAMESPACE = "http://www.w3schools.com/webservices/";

Paso 3: Creación de la solicitud

Para enviar la solicitud al servicio web, necesitamos crear una solicitud de transporte HTTP. Para ello utilizaremos la clase HttpTransportSE (org.ksoap2.transport.HttpTransportSE). Echa un vistazo al siguiente ejemplo.

1
HttpTransportSE ht = getHttpTransportSE();

Como habrás adivinado, getHttpTransportSE es otro método de ayuda y te permite crear rápidamente un objeto de transporte HTTP. Hace que sea menos tedioso crear un objeto de transporte HTTP cada vez que se hace una llamada al servicio web. Echa un vistazo a su implementación a continuación. Para crear una instancia de HttpTransportSE, solo necesitamos la URL base del servicio web, que es otra cadena estática privada como puedes ver a continuación.

1
private final HttpTransportSE getHttpTransportSE() {
2
    HttpTransportSE ht = new HttpTransportSE(Proxy.NO_PROXY,MAIN_REQUEST_URL,60000);
3
    ht.debug = true;
4
    ht.setXmlVersionTag("<!--?xml version=\"1.0\" encoding= \"UTF-8\" ?-->");
5
    return ht;
6
}
1
private static final String MAIN_REQUEST_URL = "http://www.w3schools.com/webservices/tempconvert.asmx";

En getHttpTransportSE, también configuramos el objeto HttpTransportSE. Al pasar Proxy.NO_PROXY como primer argumento del constructor, especificamos que no se utiliza ningún proxy para la petición. El tercer argumento del constructor establece el tiempo de espera de la sesión en milisegundos. Para facilitar la depuración, también establecemos la propiedad debug del objeto en true. Cualquier problema que surja se registrará en LogCat.

Paso 4: Envío de la solicitud

Es el momento de enviar la petición SOAP al servicio web. Lo hacemos a través de HTTP utilizando los objetos de transporte y envolvente que creamos anteriormente. El objeto de transporte HTTP tiene un método de call, que se utiliza para añadir la acción SOAP y el sobre que hemos creado anteriormente.

1
ht.call(SOAP_ACTION, envelope);

SOAP_ACTION es otra cadena estática privada como puedes ver a continuación.

1
private static final String SOAP_ACTION = "http://www.w3schools.com/webservices/FahrenheitToCelsius";

Paso 5: Procesamiento de la respuesta

Cuando el servicio web envíe una respuesta, necesitaremos procesarla y manejar cualquier error que pueda haber sido lanzado. A continuación, podemos mostrar los datos al usuario. Observa el siguiente fragmento de código en el que extraemos la respuesta del sobre de respuesta utilizando el método getResponse.

1
SoapPrimitive resultsString = (SoapPrimitive)envelope.getResponse();

Estoy usando un tipo SoapPrimitive, pero también puedes usar una instancia de SoapObject si la respuesta del servicio web es XML. A continuación, puedes utilizar la instancia de SoapObject para obtener los valores de la respuesta y almacenarlos en una matriz. Llama a toString en el objeto SoapPrimitive para convertir la respuesta en una simple cadena para usarla en tu aplicación.

Mira el siguiente fragmento de código en el que he implementado un método getCelsiusConversion. El método acepta una variable de cadena como único argumento. La variable se añade como una propiedad a la petición SOAP como vimos anteriormente en este tutorial. La variable que consume el método es el valor en grados Fahrenheit. Este valor es enviado y procesado por el servicio web y obtenemos de vuelta una respuesta en grados Celsius.

1
public String getCelsiusConversion(String fValue) {
2
        String data = null;
3
        String methodname = "FahrenheitToCelsius";
4
5
        SoapObject request = new SoapObject(NAMESPACE, methodname);
6
        request.addProperty("Fahrenheit", fValue);
7
8
        SoapSerializationEnvelope envelope = getSoapSerializationEnvelope(request);
9
10
        HttpTransportSE ht = getHttpTransportSE();
11
        try {
12
            ht.call(SOAP_ACTION, envelope);
13
            testHttpResponse(ht);
14
            SoapPrimitive resultsString = (SoapPrimitive)envelope.getResponse();
15
16
            List COOKIE_HEADER = (List)      ht.getServiceConnection().getResponseProperties();
17
18
            for (int i = 0; i < COOKIE_HEADER.size(); i++) {
19
                String key = COOKIE_HEADER.get(i).getKey();
20
                String value = COOKIE_HEADER.get(i).getValue();
21
22
                if (key != null && key.equalsIgnoreCase("set-cookie")) {
23
                    SoapRequests.SESSION_ID = value.trim();
24
                    Log.v("SOAP RETURN", "Cookie :" + SoapRequests.SESSION_ID);
25
                    break;
26
                }
27
            }
28
            data = resultsString.toString();
29
30
        } catch (SocketTimeoutException t) {
31
            t.printStackTrace();
32
        } catch (IOException i) {
33
            i.printStackTrace();
34
        } catch (Exception q) {
35
            q.printStackTrace();
36
        }
37
   return data;
38
}

Utilizo dos cadenas en getCelsiusConversion, data y methodname. La variable data será devuelta por el método después de que el servicio web envíe una respuesta, mientras que methodname almacena el nombre de la operación del servicio web al que nos dirigiremos y se utiliza en la instancia SoapObject.

Puede que hayas notado el bucle for en getCelsiusConversion, que no forma parte de los pasos que hemos discutido antes. Cuando se trabaja con servicios web más complejos, es importante hacer un seguimiento de la sesión actual. En el siguiente fragmento, almaceno la sesión y hago un seguimiento de ella cada vez que hago una llamada al servicio web.

1
for (int i = 0; i < COOKIE_HEADER.size(); i++) {
2
    String key = COOKIE_HEADER.get(i).getKey();
3
    String value = COOKIE_HEADER.get(i).getValue();
4
    if (key != null && key.equalsIgnoreCase("set-cookie")) {
5
        SoapRequests.SESSION_ID = value.trim();
6
        Log.v("SOAP RETURN", "Cookie :" + SoapRequests.SESSION_ID);
7
        break;
8
    }
9
}

4. Creación de la interfaz de usuario

Ahora que el trabajo duro ha quedado atrás, es el momento de hacer uso de lo que acabamos de crear. Para concluir este tutorial, te mostraré cómo crear una sencilla interfaz de usuario para convertir un valor en grados Fahrenheit a un valor en grados Celsius y mostrar el resultado en el dispositivo del usuario.

Paso 1: Crear el diseño

Primero, necesitamos crear un archivo XML en la carpeta de diseño del proyecto. Echa un vistazo al fragmento de código siguiente. Es una simple ilustración de una interfaz de usuario creada en XML.

1
<?xml version="1.0" encoding="utf-8"?>
2
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3
 android:orientation="vertical"
4
 android:layout_width="fill_parent"
5
 android:layout_height="fill_parent" />
6
<EditText
7
 android:layout_width="200dp"
8
 android:layout_height="wrap_content"
9
 android:layout_gravity="center_horizontal"
10
 android:hint="Fahrenheit"
11
 android:inputType="number"
12
 android:id="@+id/value_to_convert" />
13
14
<Button
15
 android:layout_width="200dp"
16
 android:layout_height="wrap_content"
17
 android:layout_gravity="center_horizontal"
18
 android:text="Convert to Celsius"
19
 android:id="@+id/convert" />
20
21
<TextView
22
 android:layout_width="fill_parent"
23
 android:layout_height="wrap_content"
24
 android:gravity="center_horizontal"
25
 android:textSize="30dp"
26
 android:id="@+id/answer" />
27
</LinearLayout>

Creamos tres componentes, una instancia EditText, una instancia Button y una instancia TextView. La instancia EditText se utiliza para introducir y capturar el valor que pretendemos enviar al servicio web. El botón se utiliza para ejecutar el hilo que invoca getCelsiusConversion y la vista de texto muestra la respuesta que obtenemos del servicio web.

Paso 2: Crear la actividad

El siguiente paso es crear una instancia de Activity para mostrar el diseño que acabamos de crear. Echa un vistazo al siguiente fragmento de código. Esto no debería ser demasiado sorprendente si has desarrollado aplicaciones Android antes.

1
package com.example.KsoapExample;
2
3
import android.app.Activity;
4
import android.os.Bundle;
5
6
public class MyActivity extends Activity {
7
    /**

8
    * Called when the activity is first created.

9
    */
10
    @Override
11
    public void onCreate(Bundle savedInstanceState) {
12
        super.onCreate(savedInstanceState);
13
        setContentView(R.layout.main);
14
    }
15
}

Ahora que nos hemos ocupado de la interfaz de usuario, podemos unir todo. Echa un vistazo al siguiente fragmento de código para ver cómo se hace esto.

1
package com.example.KsoapExample;
2
3
import android.app.Activity;
4
import android.os.Bundle;
5
6
public class MyActivity extends Activity {
7
    private TextView txt;
8
    private String celsius;
9
    /**

10
     * Called when the activity is first created.

11
     */
12
    @Override
13
    public void onCreate(Bundle savedInstanceState) {
14
        super.onCreate(savedInstanceState);
15
        setContentView(R.layout.main);
16
17
        final EditText edt = (EditText)findViewById(R.id.value_to_convert);
18
        Button btn = (Button)findViewById(R.id.convert);
19
        txt = (TextView)findViewById(R.id.answer);
20
21
        btn.setOnClickListener(new View.OnClickListener() {
22
            @Override
23
            public void onClick(View v) {
24
                if (edt.length() > 0) {
25
                    getCelsius(edt.getText().toString());
26
                } else {
27
                    txt.setText("Fahrenheit value can not be empty.");
28
                }
29
            }
30
        });
31
    }
32
}

En onCreate, establecemos un receptor en el botón, btn. También comprobamos que se ha introducido un valor en el campo de entrada antes de enviarlo al servicio web. En el receptor del botón, el valor pasado a getCelsius se convierte en una cadena ya que el servicio web espera un valor de cadena. La implementación de getCelsius no es difícil como puedes ver a continuación.

1
private final void getCelsius(final String toConvert) {
2
    new Thread(new Runnable() {
3
4
        @Override
5
        public void run() {
6
            SoapRequests ex = new SoapRequests();
7
            celsius = ex.getCelsiusConversion(toConvert);
8
            handler.sendEmptyMessage(0);
9
            }
10
    }).start();
11
}

En getCelsius, se crea un nuevo hilo que se ejecuta y crea una instancia de la clase que implementa getCelsiusConversion. Cuando recibimos una respuesta del servicio web, enviamos un mensaje a un manejador para actualizar la interfaz de usuario mostrando el valor en grados Celsius al usuario.

1
public Handler handler = new Handler(new Handler.Callback() {
2
3
    @Override
4
    public boolean handleMessage(Message msg) {
5
        switch (msg.what) {
6
7
            case 0:
8
                txt.setText(celsius);
9
                break;
10
        }
11
        return false;
12
    }
13
});

En el manejador, actualizamos la instancia TextView con el valor que recibimos del servicio web. Echa un vistazo al resultado final a continuación.


Conclusión:

Ahora deberías ser capaz de añadir la librería kSOAP a un proyecto y aprovecharla para hacer peticiones a un servicio web que utilice el protocolo SOAP. Trabajar con la librería kSOAP será más fácil con un poco de práctica y por ello te animo a que pruebes el servicio web de conversión de Celsius a Fahrenheit. Prueba la aplicación Android de ejemplo que forma parte del tutorial para obtener un poco de ayuda adicional.