Skip to content
Ejemplo básico REST que consulta un servicio en Internet para hacer un saludo
Kotlin
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
.idea
app
gradle/wrapper
images
video
.gitignore
README.md
build.gradle
gradle.properties
gradlew
gradlew.bat
settings.gradle

README.md

Primer ejemplo básico REST desde Android

demo

Hasta el momento hemos construido aplicaciones que funcionan dentro del entorno de nuestro dispositivo. Ahora vamos a establecer una comunicación con un nodo remoto, que ofrece un servicio a través de la web.

El proyecto

Este proyecto está generado para

  • Android Studio 3.2.1 (Noviembre 2018)
  • con Gradle 3.2.1 (el que viene con Android Studio)
  • para una SDK 28 (Pie)

Un saludo REST

Vamos a acceder a un servicio REST que está en un Web Server externo:

http://rest-service.guides.spring.io/greeting

(extraído de este artículo). Esto nos devuelve un saludo, en formato JSON (Javascript Object Notation):

{
    "id": 40530,
    "content": "Hello, World!"
}

¿Qué características tiene un servicio REST? Pueden leerlo en esta página.

El cliente

Vista

La vista principal de nuestra aplicación Android es simple, cuenta con dos TextView que permiten visualizar id y contenido del saludo.

Definición de un service

Utilizaremos el framework Retrofit que nos va a facilitar la llamada al servicio externo. Generamos entonces una interfaz que dice cómo vamos a acceder al web service:

interface GreetingService {
    @GET("/greeting")
    fun getGreeting(): Observable<Greeting>

    companion object {
        fun create(): GreetingService {
            val BASE_URL = "http://rest-service.guides.spring.io"

            val retrofit = Retrofit.Builder()
                    .baseUrl(BASE_URL)
                    .addConverterFactory(GsonConverterFactory.create())
                    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                    .build()

            return retrofit.create(GreetingService::class.java)
        }
    }
}
  • la annotation @GET define que vamos a hacer el request mediante un método GET
  • creamos un companion object de Kotlin para la interfaz GreetingService, lo que en otros lenguajes implementábamos como well known objects o singletons, y en él definimos la URL base que será http://rest-service.guides.spring.io
  • también debemos definir el path al que vamos a acceder dentro del server: en nuestro caso es la URL relativa "/greeting", eso termina formando http://rest-service.guides.spring.io/greeting
  • en Retrofit 2.0 las llamadas pueden ser sincrónicas o asincrónicas, entonces el método getGreeting devuelve un Observable de un valor que representaremos con un objeto nuevo: Greeting, que tenemos que codificar
  • la buena noticia es que no tenemos que recibir el JSON y convertirlo a un Greeting, esto lo hace retrofit utilizando como convención las propiedades del JSON devuelto (es lo que resuelve GsonConverterFactory). Si el JSON devuelve un objeto con propiedades id y content, es obvia la implementación de Greeting:
class Greeting {

    var id: String = null
    var content: String = null
}

Llamada al service en la activity

La aplicación al iniciar construye un objeto Service, que se decora en base a la definición de nuestro GreetingService, y se instancia en forma lazy (la primera vez que se invoca), y necesita suscribirse al observer asincrónico pasándole

  • un callback cuando el resultado fue correcto
  • y otro callback para manejar los errores (código HTTP distinto de 200)
class MainActivity : AppCompatActivity() {

    val greetingService by lazy {
        GreetingService.create()
    }

    var disposable: Disposable? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        findViewById<Button>(R.id.btnGreet).setOnClickListener { armarSaludo() }
        armarSaludo()
    }

    private fun armarSaludo() {
        disposable =
                greetingService.getGreeting()
                        .subscribeOn(Schedulers.io())
                        .observeOn(AndroidSchedulers.mainThread())
                        .subscribe(
                                { saludo ->
                                    lblId.text = saludo.id
                                    lblContent.text = saludo.content
                                },
                                { error ->
                                    Toast.makeText(this@MainActivity.applicationContext, "Ocurrió un error al buscar el saludo. ", Toast.LENGTH_LONG).show()
                                    Log.e("BasicRestApp", error.message)
                                }
                        )

    }
}

Modificaciones en el Manifest

En el AndroidManifest debemos indicar que necesitamos el permiso del usuario para conectarnos a Internet:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="uqbar.org.basicrestapp">
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <application
        android:networkSecurityConfig="@xml/network_security_config"

Pero además debemos crear un archivo de configuración de red network_security_config.xml que encontrarán en el directorio res/xml:

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <domain-config cleartextTrafficPermitted="true">
        <domain includeSubdomains="true">rest-service.guides.spring.io</domain>
    </domain-config>
</network-security-config>

Aquí habilitamos el acceso al dominio en cuestión.

Arquitectura general

image

You can’t perform that action at this time.