Android - Llamadas a una API

Apr 1, 2014 2:22:00 PM / by gerard.canadas

 

 

En la publicación de hoy, os traemos un pequeño tutorial en el que os mostraremos como llamar un servicio Web de una API, y obtener los datos que este nos retorna, para poder trabajar con ellos desde nuestra app.

 

Este proceso, aparentemente fácil (especialmente para aquellos que no sean principiantes en desarrollo Android), puede complicarse, incluso para estos, a partir de las versiones 3 de Android. Esto es debido a que, a partir de la versión 3.0, se introdujo una nueva política de seguridad en el sistema, que bloquea todas las comunicaciones en el thread principal (Main Thread). Para establecer comunicación con el exterior desde nuestra aplicación, debemos hacerlo en un nuevo thread.

 

El motivo de este cambio es muy sencillo. Las comunicaciones con el exterior pueden llevar un tiempo demasiado largo, y si se realizan desde el Main Thread, toda la aplicación dejará de responder, haciendo que si, por el motivo que sea, la comunicación falla, la aplicación se cuelgue y tengamos que recurrir al temido "Forzar cierre". Si únicamente generamos el código que realiza la llamada al WebService (como veníamos haciendo en las anteriores versiones de Android), la aplicación nos retornará el error NetworkOnMainThreadException, y esto provocará el cierre de la misma.

 

Para solucionar esto, en el siguiente tutorial os vamos a mostrar como realizar estas comunicaciones desde un nuevo Thread. Para hacer totalmente efectiva esta nueva política, os vamos a enseñar como hacerlo desde una tarea asíncrona, que se ejecutará en background, haciendo que nuestra aplicación se continue ejecutando con normalidad, pase lo que pase con nuestras comunicaciones, y haciendo así más fácil el control de errores de estas comunicaciones, como timeout excedido, pérdida de conexión con la red, etc. 

 

Vamos a ilustrar esta explicación con un sencillo ejemplo, que consistirá en un simple sistema de Login para Android 4.0 o superior.

 

El primer paso será generar la llamada al WebService. Esto lo haremos tal y como lo veníamos haciendo en versiones anteriores. Haremos la llamada utilizando las clases nativas de comunicaciones Http, y expulsando el contenido que nos devuelva el WebService en un objeto JSON, también nativo de Android. Para seguir la estructura correcta de organización del proyecto, vamos a crear una clase llamada LogInRequest.

 

package com.IngensNetworks.APIRequest;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONStringer;
import android.util.Log;

public class LogInRequest {

public static String WSLogin(String URL, String User, String Password) throws JSONException, ClientProtocolException, IOException {
HttpGet request = new HttpGet(URL + "UserAut/" + User + "/" + Password);
request.setHeader("Content-type", "application/json");
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpResponse response = httpClient.execute(request);
HttpEntity responseEntity = response.getEntity();

InputStream inputStream = null;
String result = null;

inputStream = responseEntity.getContent();
// json is UTF-8 by default
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"), 8);
StringBuilder sb = new StringBuilder();

String line = null;
while ((line = reader.readLine()) != null)
{
sb.append(line + "\n");
}
result = sb.toString();

JSONObject jObject = new JSONObject(result);

return jObject.getString("response");

}

}

 

En la primera línea de la función, podemos ver como haremos la llamada a la URL proporcinada, donde se ubica la API a la que accedemos. Como en este caso, el protocolo utilizado es GET,luego le añadimos UserAut/ (WebService al que hacemos la petición) más los parámetros, en este caso, usuario y password.

 

Una vez hecho esto, vamos a encapsular esta llamada en una AsyncTask. Para obtener más información sobre esta clase y sus propiedades, podeis ver su apartado documentación oficial de Android, AsyncTask.

 

Debemos tener en cuenta, como hemos explicado anteriormente, que estas llamada debe ser realizada fuera de nuestro Thread principal.

 

private class AsyncTaskCallWS extends AsyncTask<String, Float, String>{

protected void onPreExecute() {
//showProgress(true);
}

protected String doInBackground(String... urls) {
String URLLogin = getResources().getString(R.string.URL_WebService);
String result = "";
try {
result = LogInRequest.WSLogin(URLLogin, mUser, mPassword);
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

return result;
}

 

En este código, a modo de ejemplo, no se ha implementado el control de errores en la tarea asíncrona.

 

Si lo miramos detenidamente, podemos ver como obtenemos la URL donde está ubicada la API (en nuestro caso, guardado en el archivo de Resources para utilizarlo genéricamente en toda la aplicación), y en la función doInBackground es donde ejecutamos la llamada y obtenemos el resultado.

 

Ahora solo nos falta indicar donde vamos a ejecutar esta acción. En nuestro caso, será en una función llamada Login, que se ejecutará cuando el usuario intente loguearse en la aplicación.  

 

public void login(View v) throws IOException, IOException, ParseException, JSONException {
// Store values at the time of the login attempt.
mUser = mUserView.getText().toString();
mPassword = mPasswordView.getText().toString();

String output = "";
try {
output = new AsyncTaskCallWS().execute().get();
if (output.equals("true"))
goToMain();
else {
setPswMistake(1);
showProgress(false);
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

 

Como podemos observar, únicamente obtenemos los valores de dos TextBox (mUserView, mPasswordView), que corresponden al usuario y contraseña introducidos, y realizamos la llamada a la API. En este caso, como hemos parseado previamente el JSON que nos va a retornar esta llamada, obtendremos una variable string, que contendrá "true" en caso de que el usuario se haya autenticado correctamente, y "false" si no lo ha hecho, y hacemos el tratamiento correspondiente en cada caso.

 

Y, con este ejemplo, termina el post de hoy. Esperamos que os sea de utilidad en vuestras aplicaciones!

Topics: Android, API, app, AsyncTask, Ingens Developments, WebService

gerard.canadas

Written by gerard.canadas

Lists by Topic

see all
Servicios gestionados

Categorías

Ver todas