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¶
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:
- Crea un objeto
Retrofit
con la URL base y la fábrica del conversor para convertir strings. - Creea un data class que contenga los datos que se intercambian mediante JSON
- 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)
)
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>
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"
}
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)