Android: Cómo consumir una API y procesar respuestas JSON 🎯 Retrofit

En este tutorial aprenderás a consumir una API (servicios web) y procesar la respuesta JSON obtenida.

¿API? ¿Servicios web?

Por azares del destino es posible que aun no conozcas muy bien el significado de estos términos, o la diferencia que existe entre ambos conceptos.

Pero no te preocupes.

Puedes ver el siguiente video y aclarar tus dudas:

Este tutorial está centrado en cómo consumir una API o servicios web desde una aplicación Android.

Si por ejemplo tienes una base de datos, pero no tienes una API creada. Entonces primero deberías definir una API.

Una API es un intermediario entre una base de datos y una aplicación móvil (sea Android, iOS u otra tecnología).

Si deseas aprender a desarrollar una aplicación Android de Diagnóstico Médico, por favor haz clic aquí.

En esta serie aprenderás a desarrollar una API usando Laravel, y a programar una aplicación Android que consuma esta API.

Cómo añadir Retrofit a nuestro proyecto

Existen varias formas de añadir dependencias a nuestro proyecto.

En este caso usaremos el método más común y recomendado: añadiremos Retrofit vía Gradle.

Eso significa que debemos ir a nuestro archivo build.gradle y añadir las siguientes líneas:

implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.6.4'
implementation 'com.squareup.okhttp3:logging-interceptor:4.9.3'
Espera, ¿dónde dices?

Debes añadir la dependencia en el archivo build.gradle a nivel de módulo.

En el lado izquierdo de Android Studio encontrarás dentro de Gradle Scripts 2 opciones con el mismo nombre. Asegúrate de seleccionar la opción adecuada:

Añadir dependencias Android usando Gradle

Dentro del archivo debes agregar 2 dependencias. Una para Retrofit y otra para GSON.

La tercera dependencia, la del logging interceptor, es opcional. Pero te recomiendo añadirla para poder debuggear las peticiones.

Añadir Retrofit y GSON a nuestro proyecto Android

Genial, ya lo tengo. ¿Pero qué es GSON? ¿No era JSON lo que queríamos obtener?

JSON es un formato de respuesta que usan las API. Eso es lo que vamos a obtener y procesar.

Pero GSON es una dependencia adicional, que funciona en conjunto con Retrofit para "convertir las respuestas JSON obtenidas en objetos Java".

Retrofit los llama "converters", y existen varios de ellos. Incluso para "mapear" respuestas obtenidas en formato XML.

Entrando en acción

Una vez que tienes las dependencias cargadas en tu proyecto, lo siguiente es configurar Retrofit a través de un ApiAdapter y un ApiService.

¿No puedo hacer directamente la petición? Estoy algo apurado.

Puedes, pero en serio, te recomiendo crear estos 2 archivos.

Una vez que lo comprendas, luego te será súper sencillo hacer peticiones, y lo mejor de todo es que tu código estará ordenado y podrás replicarlo fácilmente a otros proyectos.

Primero lo primero: Internet

Antes de empezar a configurar Retrofit en nuestro proyecto, es importante que nuestra aplicación se pueda conectar a internet.

Para solicitar este permiso debemos añadir la siguiente línea a nuestro archivo manifest:

<uses-permission android:name="android.permission.INTERNET" />

Una clase y una interfaz

El ApiAdapter es una clase que se encargará de instanciar un objeto Retrofit (aplicando el patrón de diseño Singleton), y este objeto hará posible las peticiones.

Además, en esta clase se definirá la ruta base de la API que queremos consultar.

El ApiService en cambio es una interfaz. Aquí vamos a definir métodos abstractos.

Cada método abstracto va a representar una ruta específica de nuestra API.

Por ejemplo, podemos tener un método para realizar un inicio de sesión. Le pasamos un usuario y una contraseña y obtenemos un token como respuesta.

Otro ejemplo es que le pasamos los datos de un producto, para que la API lo registre en la base de datos. Y obtenemos como respuesta un arreglo de posibles errores en los datos, o bien un boolean indicándonos que el registro fue satisfactorio.

¿Tiene sentido verdad?

Para que se comprenda mejor, a continuación puedes ver códigos de ejemplo para ambos conceptos.

Ejemplo de ApiService

En el siguiente ejemplo de ApiService se han considerado 4 métodos abstractos.

Cada método define una ruta, y especifica qué clase se encargará de procesar la respuesta obtenida. Esto te lo explicaré con más detalle en un momento. Vamos de a pocos.

  • El primer método representa una petición GET a la ruta diseases. La respuesta será un listado de enfermedades. Y esta respuesta se va a procesar gracias a la clase DiseasesResponse.

  • El segundo método es una petición POST a la ruta upload/photo. Esta petición se hace enviando ciertos parámetros. Entre ellos, una variable String que representa una imagen codificada en base64. Se asume que la API está lista para subir la foto a través de esta ruta.

  • El tercer método permite iniciar sesión en una aplicación. Se asume que LoginResponse indica el formato para procesar la respuesta de esta ruta. Debería encargarse de parsear el posible token recibido, si el login fue exitoso.

  • El último método permite registrar un producto a través de una petición POST. Se asume que la respuesta devolverá un arreglo con mensajes de error, en caso de que el servidor así lo considere. Todo depende de la API. Aquí solo estamos viendo cómo consumirla.

public interface MyApiService {

    @GET("diseases")
    Call<DiseasesResponse> getDiseases();

    @FormUrlEncoded
    @POST("upload/photo")
    Call<SimpleResponse> postPhoto(
        @Field("image") String base64, 
        @Field("extension") String extension,
        @Field("user_id") String user_id
    );

    @GET("login")
    Call<LoginResponse> getLogin(
    	@Query("username") String username, 
    	@Query("password") String password
    );

    @FormUrlEncoded
    @POST("product")
    Call<SimpleResponse> postNewProduct(
            @Field("code") String code,
            @Field("name") String name,
            @Field("description") String description
    );

}

Ejemplo de ApiAdapter

public class MyApiAdapter {

    private static MyApiService API_SERVICE;

    /**
     * Localhost IP for AVD emulators: 10.0.2.2
     */
    private static final String BASE_URL = "http://10.0.2.2:8080/api/";

    public static MyApiService getApiService() {
        // Creamos un interceptor y le indicamos el log level a usar
        final HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
        logging.setLevel(HttpLoggingInterceptor.Level.BODY);

        // Asociamos el interceptor a las peticiones
        final OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
        httpClient.addInterceptor(logging);

        if (API_SERVICE == null) {
            Retrofit retrofit = new Retrofit.Builder()
                    .baseUrl(BASE_URL)
                    .addConverterFactory(GsonConverterFactory.create())
                    .client(httpClient.build()) // <-- set log level
                    .build();

            API_SERVICE = retrofit.create(MyApiService.class);
        }

        return API_SERVICE;
    }

}

Organizando nuestro código

Como ya lo has notado, necesitamos crear una clase y una interfaz.

Con el fin de tener nuestro proyecto organizado por carpetas, vamos a crear una carpeta io y a situar allí los 2 archivos antes mencionados.

El nombre de IO hace referencia a input/output.

Ten en cuenta que no he puesto los import en los ejemplos. Pero puedes importar las clases fácilmente en Android Studio.

Adicional a ello, necesitamos otro grupo de clases que nos permitirán "parsear" las respuestas JSON obtenidas. Estas clases las guardaremos en una carpeta model.

Por ejemplo, si tenemos una entidad Disease (con los datos de una enfermedad), entonces vamos a crear esta clase dentro de la carpeta model.

Esta carpeta contendrá todo nuestro modelo de datos. Es decir, existirá una clase por cada entidad que recibamos desde la API.

A estas alturas nuestro proyecto se verá de la siguiente forma:

Paquetes de nuestro proyecto Android

En la carpeta response, ubicada dentro del paquete io se encontrarán nuestras clases que sirven para determinar el formato a usar en el "parse" de la respuesta JSON a objetos.

Error CLEARTEXT communication not supported

Si obtienes como error el siguiente mensaje: CLEARTEXT communication not supported, significa que estás queriendo comunicarte con una URL base que usa http en vez de https.

Lo recomendable es usar https, sin embargo, mientras desarrollas es posible que quieras conectarte a una ip de desarrollo local con http.

Si este es tu caso, ve al archivo AndroidManifest.xml de tu proyecto y en la etiqueta application agrega el siguiente atributo: android:usesCleartextTraffic="true".

Con ello lo solucionarás.

¿Te has perdido?

No te preocupes, hay un video que puedes ver ahora mismo sobre cómo implementar todos estos pasos:

# android # retrofit

Logo de Programación y más

Comparte este post si te fue de ayuda 🙂.

Regístrate

Accede a todos los cursos, y resuelve todas tus dudas.

Cursos Recomendados

Imagen para el curso Laravel y Android

Laravel y Android

Curso intensivo. Incluye el desarrollo de una API, su consumo, y autenticación vía JWT. También vemos Kotlin desde 0.

Iniciar curso
Imagen para el curso Docker y Microservicios

Docker y Microservicios

Aprende por qué es importante y cómo funciona Docker, con este nuevo curso práctico!

Iniciar curso
Imagen para el curso Aprende Python

Aprende Python

Desarrolla tu primer Chatbot para Facebook Messenger sobre Google Cloud, y aprende Python en el camino!

Iniciar curso

Espera un momento ...

¿Te gustaría llevar mi curso de Laravel, gratis?

Sólo debes ingresar tus datos: