Accede a todos los cursos 隆a un precio especial! 馃巺鉂勷煄

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: