Saltar a contenido

112. Cliente http y consumo de API REST con Retrofit

La librería retrofit proporciona un cliente en Java y Android para crear clientes HTTP/HTTPS.

Necesitamos conocer: * Corrutinas * Permisos app

Aprendemos:
* Consumir REST API * Uso de RETROFIT

112.1 Rest API

Con Retrofit podemos hacer peticiones a servidores REST API y procesar los datos de la respuesta que normalmente vendrán en formato JSON

112.2 Codelab Mars photo

Vamos a ver el funcionamiento de Retrofit para obtener datos de internet a trvés de este ejemplo: Codelab Mars photos Primera parte

y segunda parte presentar las fotos

La aplicación recupera y presenta fotos de Marte del servidor dedicado para este codelab.

En este primer codelab se accede directamene al recurso remoto sin usar un repository

112.2.1 Agregar dependencias

// Retrofit
    implementation("com.squareup.retrofit2:retrofit:2.9.0")
    implementation("com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:1.0.0")
    implementation("com.squareup.okhttp3:okhttp:4.11.0")
// Retrofit with Scalar Converter
    implementation("com.squareup.retrofit2:converter-scalars:2.9.0")
    implementation("com.squareup.retrofit2:converter-gson:2.9.0")

112.2.2 Conexión a Internet

Sigue aquí

Alt text

En esta tarea, agregarás una capa de datos a tu proyecto Mars Photos, que tu ViewModel usará para comunicarse con el servicio web. Implementarás la API del servicio de Retrofit con los siguientes pasos:

  1. Crea un objeto Retrofit con la URL base y la fábrica del conversor para convertir strings.
  2. Creea un data class que contenga los datos que se intercambian mediante JSON
  3. Crear una interfaz que explique cómo habla Retrofit con el servidor web y una clase que implemente el intefaz MarsApiService

112.2.3 Permisos acceso a internet

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

112.2.4 Objeto Retrofit

private val retrofit: Retrofit = Retrofit.Builder()
    .addConverterFactory(Json.asConverterFactory("application/json".toMediaType()))
    .baseUrl(BASE_URL)
    .build()

112.2.5 Data class

Es el objeto Kotlin equivalente al JSON trasmitido.

data class MarsPhoto(
    val url: String
)

112.2.6 Interfaz y clase MarsApiService

interface MarsApiService {

    @GET("photos")
   suspend fun getFotos(): List<MarsPhoto>
}

object MarsApi {
    val retrofitService : MarsApiService by lazy {
        retrofit.create(MarsApiService::class.java)
    }
}

En el interfaz se crean los métodos para hacer las llamadas al API que vamos a consumir.
Utilizamos las anotaciones para que Retrofit construya las llamadas adecuadas. GET(photos) y convierta la respuestda JSON en una lista de objeto MarsPhoto . El método se usara en corrutinas y se prefija con suspend

El objeto MarsApi : 1. Contiene el objeto retrofitService 2. Retrofit crea una clase (y el objeto) que implementación del interface de MarsApiService y se inicializa en el primer uso (by lay)

El mismo resultado se puede implementar con el patrón singleton

class MarsApi {
    companion object {
        // Inicializador Lazy para RetrofitService
        val retrofitService: MarsApiService by lazy {
            // Suponiendo que 'retrofit' ya está inicializado en algún lugar con la configuración necesaria
            retrofit.create(MarsApiService::class.java)
        }
    }
}

112.2.7 Descargar y mostrar fotos.

Utilizamos la libería Coil

Primero agregamos la dependencia Coil

implementation("io.coil-kt:coil-compose:2.4.0")

Para obtener las fotos usamos la función de Coil:

AsyncImage(
    model = ImageRequest.Builder(LocalContext.current)
        .data("https://example.com/image.jpg")
        .crossfade(true)
        .build(),
    placeholder = painterResource(R.drawable.placeholder),
    contentDescription = stringResource(R.string.description),
    contentScale = ContentScale.Crop,
    modifier = Modifier.clip(CircleShape)
)
AsyncImage admite los mismos argumentos que el elemento componible Image estándar. Además, admite la configuración de pintores placeholder/error/fallback y devoluciones de llamada onLoading/onSuccess/onError. El código de ejemplo anterior carga la imagen con un recorte circular y un encadenado, y establece un marcador de posición.

Advertencia si se usa http nos dara el error: CLEARTEXT communication to xxxx not permitted

Crear el archivo network_security_config.xml:

En el directorio res/xml, crea un archivo llamado network_security_config.xml (crea el directorio xml si no existe).

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <domain-config cleartextTrafficPermitted="true">
        <domain includeSubdomains="true">192.168.1.2</domain>
        <domain includeSubdomains="true">192.168.1.3</domain>
    </domain-config>
</network-security-config>
Modificar el AndroidManifest.xml:

En el archivo AndroidManifest.xml, referencia el archivo de configuración de seguridad de red en la etiqueta :

<application
    android:networkSecurityConfig="@xml/network_security_config"
    ... >
    ...
</application>

112.3 Depurado

Podemos observar las comunicaciones REST API

Dependencias:

  implementation("com.squareup.okhttp3:logging-interceptor:4.12.0")

Añadimos el interceptador:
logging
okHttoClient
.client

/**
 * Para depurar añadimos un interceptador que regitra en logcat las trasmisiones
 * y recepciones
 */
val logging = HttpLoggingInterceptor().apply {
    // Configura el nivel de registro. Level.BODY te permite ver el cuerpo de las peticiones y respuestas.
    level = HttpLoggingInterceptor.Level.BODY
}

// Construye el cliente OkHttp y añade el interceptor de registro.
val okHttpClient = OkHttpClient.Builder()
    .addInterceptor(logging)
    .build()


private val retrofit = Retrofit.Builder()
    // .addConverterFactory(Json.asConverterFactory("application/json".toMediaType() ))
    .addConverterFactory(GsonConverterFactory.create())
    .baseUrl(BASE_URL)
    .client(okHttpClient) // interceptador
    .build()

112.4 NOTAS PARA REDACTAR

Si utilizamos id("org.jetbrains.kotlin.plugin.serialization") version "1.8.10":

plugins {
    id("com.android.application")
    id("org.jetbrains.kotlin.android")
    id("org.jetbrains.kotlin.plugin.serialization") version "1.8.10"
}
Este plugin es un procesador para la serialización se puede eliminar Call y usar suspend fun con el plugin de serialización de Kotlin en tus proyectos Retrofit. Esto simplifica tu código, hace que el manejo de errores sea más intuitivo y te permite aprovechar las coroutines de Kotlin para operaciones asíncronas.

como en :

interface MarsApiService {

    @GET("photos")
   suspend fun getFotos(): List<MarsPhoto>
}

Y cuando no se usa el plugin :

interface MarsApiService {
        @GET("photos")
        fun getPhotos(): Call<String>
}

El metodo preferido es usar el plugin y suspend

112.5 Apendice

Enlaces:
* https://cursokotlin.com/tutorial-retrofit-2-en-kotlin-con-corrutinas-consumiendo-api-capitulo-20-v2/ * tutorial android compose retrofit * Herramienta online editor json * https://developer.android.com/courses/pathways/android-basics-compose-unit-5-pathway-1?hl=es-419 * Codelab Mars photos

Colecciones de API Públicos * https://github.com/public-apis/public-apis * Colección de apis para educacion * https://www.hyperlinkinfosystem.com/research/the-20-best-education-apis-in-2020 * https://medium.com/@tapesh.patel/free-api-for-any-project-need-2c4d45213036 * Nasa api

API Juegos online * Space Trader * Video presentacion space trader * https://deckofcardsapi.com/ *

Otros API * GEOCOD De direcciones postales a posición GPS * RAE (REVISAR: https://github.com/nachocho/pyrae)