Communication HTTPS dans l'app. Kotlin pour Android

Ce tutoriel va te donner les clés pour faire une requête HTTPS GET au format JSON, en Android, avec la bibliothèque Retrofit V2, sous le langage Kotlin.

Concrètement, nous allons demander une liste de pays à un serveur web, REST Countries APIs, en suivant les étapes suivantes :

  • Importer Retrofit et Moshi dans le projet Android
  • Créer la classe Kotlin représentant les données (à récupérer du serveur)
  • Créer l’interface Kotlin représentant l’API du serveur
  • Créer l’instance du client Retrofit (en version 2)
  • Créer l’instance du service d’API
  • Créer la requête GET
  • Exécuter la requête GET
  • Récupérer le résultat de la requête

Importer Retrofit et Moshi dans le projet Android

Tout d’abord, il faut au préalable importer, dans le projet Android, la dépendance Retrofit 2, ainsi qu’un convertisseur de requête :

    implementation "com.squareup.retrofit2:retrofit:$retrofit_version"
    implementation "com.squareup.retrofit2:converter-moshi:$moshi_version"

avec :

        ext.retrofit_version = '2.9.0'
        ext.moshi_version = '2.9.0'

Il s’agit aussi d’ajouter la permission internet, dans le fichier Manifest :

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

Note : la bibliothèque OkHttp est utilisé pour écrire et lire les sockets par Retrofit V2.

Pour plus de détail, consultez l’article Configurer un projet Android pour utiliser Retrofit.

Dans la suite, nous nous intéressons à réaliser une requête HTTPS GET et à récupérer une liste d’objets au format JSON depuis un serveur distant.

Créer la classe Kotlin représentant les données

Il s’agit de créer la classe Kotlin représentant l’objet à récupérer du serveur.

Par exemple, nous souhaitons récupérer une liste des pays, depuis le serveur Countries APIs. La requête permettant d’obtenir la liste de pays est https://restcountries.com/v3.1/all.  En utilisant Postman, il est possible d’analyser le résultat JSON de cette requête :

[
{
    "name": {
        "common": "Barbados",
        "official": "Barbados",
        "nativeName": {
            "eng": {
                "official": "Barbados",
                "common": "Barbados"
            }
        }
    },
    "tld": [
        ".bb"
    ],
    "cca2": "BB",
    "ccn3": "052",
    "cca3": "BRB",
    "cioc": "BAR",
    "independent": true,
    "status": "officially-assigned",
    "unMember": true,
    "currencies": {
        "BBD": {
            "name": "Barbadian dollar",
            "symbol": "$"
        }
    },
    "idd": {
        "root": "+1",
        "suffixes": [
            "246"
        ]
    },
    "capital": [
        "Bridgetown"
    ],
    "altSpellings": [
        "BB"
    ],
    "region": "Americas",
    "subregion": "Caribbean",
    "languages": {
        "eng": "English"
    },
    "translations": {
        "ara": {
            "official": "باربادوس",
            "common": "باربادوس"
        },
        "bre": {
            "official": "Barbados",
            "common": "Barbados"
        },
        "ces": {}
      }
    }
  ]

Ainsi le serveur, renvoie une liste de pays, contenant :

  • un objet (name) lui même contenant
  • un nom (common)

Afin de modéliser un tel objet, soit Country, il faut créer les classes Kotlin correspondant à la réponse du serveur. Par exemple, la classe Country représente un pays et CountryDetail les détails du pays, selon les données du serveur :

data class Country(val name: CountryDetail)
data class CountryDetail(val common: String)

Les attributs du constructeur doivent porter les mêmes noms que ceux du fichier JSON renvoyé par le serveur : name et common. Pour le moment, seulement ces deux attributs nous intéresse, c’est pourquoi les autres n’apparaissent pas dans la classe.

Créer l’interface Kotlin représentant l’API

Il s’agit de créer l’interface Kotlin contenant la déclaration des requêtes disponibles sur Countries APIs. Pour le moment, nous avons une seule requête GET, ne prenant aucun paramètre et renvoyant une liste de pays. Par exemple, l’interface CountriesService représente l’API du serveur de cours :

interface CountriesService {
    @GET("/v3.1/all")
    fun listCountries(): Call<List<Country>>
}

Avec les importations suivants :

import retrofit2.Call
import retrofit2.http.GET

L’annotation @GET de Retrofit 2 indique la déclaration d’une requête GET. Ensuite, en paramètre, il est placé le chemin de la requête /v3.1/all.

La signature de la fonction associé à la requête porte le nom listCountries (son nom n’a pas d’importance). Elle ne prend pas de paramètre puisque la requête n’en demande pas. Et elle renvoie un Call<...>, c’est la réponse du serveur, prenant entre chevron List<Country>, c’est-à-dire la liste de pays renvoyée par le serveur au format JSON.

Toutes fonctions associées à une requête, retourne un objet Call<>, ensuite le paramètre entre chevron varie selon ce que renvoie le serveur (une liste ou un objet) et ce que l’on souhaite récupérer. Par ailleurs, si la requête requiert un paramètre tel qu’un nom d’utilisateur alors il est spécifié en paramètre de la fonction.

Par exemple pour récupérer la liste des répertoires d’un utilisateur GitHub, selon leur API, il faudrait coder en Kotlin :

@GET("/users/{user}/repos")
listRepos(@Path("user") user: String): Call<List<Repo>>

Créer l’instance du client Retrofit

Depuis, une Activity ou bien un Fragment, nous allons créer une instance de client Retrofit. Par exemple, dans un Fragment NetworkFragment:

    val retrofit = Retrofit.Builder()
     .baseUrl(URL_COUNTRY_API)
     .addConverterFactory(MoshiConverterFactory.create())
     .build()

avec l’url :

companion object {
    const val URL_COUNTRY_API = "https://restcountries.com/"
}

les imports concernés sont celui de Retrofit 2 et de Moshi, le convertisseur de JSON :

    import retrofit2.Retrofit
    import retrofit2.converter.moshi.MoshiConverterFactory

Le client Retrofit est à configurer avec une url de serveur ainsi qu’un convertisseur de requête. Ici, il est choisi le convertisseur Moshi car il permet de convertir du JSON en objet Kotlin.

Créer l’instance du service

Après avoir créé l’instance du client Retrofit, à la suite dans NetworkFragment, il s’agit de créer l’instance du service comme suit :

    val service = retro.create(CountriesService::class.java)

et d’importer la classe CountriesService.

Ce service est créé à partir du client Retrofit, lequel contient l’url du serveur, et à partir du .class de l’interface, laquelle contient toutes les requêtes possibles avec le serveur.

Créer la requête GET

Toujours à la suite dans NetworkFragment, il s’agit de créer la requête GET :

    val countryRequest = service.listCountries()

Exécuter la requête GET

Enfin, il est possible d’exécuter la requête venant d’être créée via la fonction enqueue(object: Callback<…>) de Retrofit :

countryRequest.enqueue(object : Callback<List<Country>> {
        override fun onResponse(call: Call<List<Country>>, response: Response<List<Country>>) {
            val allCountry = response.body()
            for (c in allCountry!!)
                Log.v(
                    MainActivity::class.simpleName,
                    "NAME: ${c.name.common} \n "
                )
        }


        override fun onFailure(call: Call<List<Country>>, t: Throwable) {
            Log.i(MainActivity::class.simpleName, "RETRY AND GOOD LUCK.")
        }

    })

les importations associées sont les suivantes :

      import retrofit2.Call
      import retrofit2.Callback
      import retrofit2.Response

ainsi que l’import de la classe Country.

La fonction enqueue(object: Callback<…>) prend en paramètre l’objet Callback, cet objet intercepte la réponse du serveur. Cette dernière est traitée dans la sur-implémentation des fonctions onResponse(...) et onFailure(...). Les paramètres du Callback ainsi que des fonctions onResponse(...) et onFailure(...) dépendent directement du type de retour de la fonction représentant la requête. Dans notre cas, le type de retour de listCountries() est List<Country> (définit par ce que renvoie le serveur).

Récupérer le résultat de la requête

Enfin, la liste des pays en contenu dans response.body().

Le code correspondant peut être téléchargé dans le thème “Communication HTTPS” de l’application “Kotlin pour Android : Quiz”.

Communication HTTPS avec API de pays

Finalement, dans cet article nous avons vu comment :

  • Importer Retrofit et Moshi dans le projet Android
  • Créer la classe Kotlin représentant les données à récupérer du seveur
  • Créer l’interface Kotlin représentant l’API du serveur
  • Créer l’instance du client Retrofit en version 2
  • Créer l’instance du service d’API
  • Créer la requête GET
  • Exécuter la requête GET
  • Récupérer le fruit de la requête

Références

  1. Retrofit
  2. Okhttp
  3. Moshi
  4. Postman

Partagez ou réagissez sur Twitter.

Vous avez trouvé une erreur ou voulez améliorer cet article ? Editez le directement !

Comments