📡 Gestion du réseau


Note 📝: Cette fiche vous permet de comprendre et d'avoir une rapide référence sur l'utilisation du réseau sur Android.

Accéder au réseau ⚡️

Votre application devra la plupart du temps accéder au réseau pour récupérer des données provenant d'une ou plusieurs API (web service). Il existe des centaines de manières de gérer cela sur Android.

Mais dans tous les cas vous devrez :

  • Gérer les permissions d'accès à internet
  • Lancer vos requêtes réseau sur un fil d'exécution (thread) différent
  • Comprendre le protocole HTTP

Mais avant d'accéder au réseau. Les PERMISSIONS 🥁

Les permissions

Sur un smartphone, il est possible de faire beaucoup de choses, il fut un temps au début des smartphones, et encore il y a peu, où globalement une app pouvait avoir accès à tout un tas de capteurs du mobile sans trop s'inquiéter.

Aujourd'hui c'est différent, notamment à cause d'abus de développeurs peu scrupuleux. Des abus d'accès à la vie privée de l'utilisateur (accès au micro, caméra, liste de contact etc.), mais aussi des abus d'utilisations de capteurs qui peuvent amoindrir la durée de vie de la batterie, abuser du réseau et provoquer des factures salées, envoyer des SMS malveillants depuis le smartphone de n'importe qui, etc.

Les systèmes Android et iOS ont mis en place les permissions, qui sont des gardes fous permettant à l'utilisateur de gérer ce qui se passe sur son mobile. Et aux développeur de ne pas abuser de l'appareil mobile.

Les permissions sur Android sont un point assez sensible, autant du point de vue utilisateur que du point de vue développeur. Ne négligez pas ce point, cela peut faire la différence entre une app qui a du succès à une app que tout le monde va désinstaller

Un peu de lecture : https://developer.android.com/guide/topics/permissions/overview

Et pour information : La loooooooongue liste des permissions

En tant qu'utilisateur 🧑

  • Vous voulez avoir le contrôle sur votre appareil, et sur les applications que vous installez dessus.
  • Vous voulez savoir quand une app utilise ou va utiliser un capteur particulier et pourquoi ? Est-ce que c'est pour une raison valable ou non ?
  • Vous ne voulez pas non plus être pris d'assaut par des dizaines de demande de permissions au démarrage d'une application.

En tant que développeur 🧑‍💻

  • Vous devez en tant que développeur faire en sorte que les permissions d'accès soient justifiées auprès de l'utilisateur. (Ceux qui ont lu ce point, bah on vous remercie, parce que c'est super long à écrire un cours alors ca fait plaisir que vous soyez attentif. 🍬)
  • Vous devez faire en sorte que si l'utilisateur refuse certaines permissions, votre application continue de fonctionner le plus possible.
  • Vous devez gérer exhaustivement les différents cas possibles liés à l'accord des permissions.
Note 📝 Par exemple, si l'utilisateur vous donne accès au micro mais pas à la caméra, ou qu'il décide de désactiver la permission de localisation entre deux démarrages de votre application. Cela ne doit pas créer de bug ou de comportement inattendu.


Ca c'est les cas simples

Sur Android

Les permissions peuvent être implicites ou explicites. C'est Google et plus généralement Android qui défini comment les permissions doivent être appliquées selon leur types.

Permissions Explicites

Les permissions de localisations sont explicites. On demande à l'utilisateur de confirmer via une popup in-app s'il veut bien partager sa position actuelle.

Question 1 👉 : Décrivez le code à utiliser pour afficher une demande explicite de permission à l'utilisateur. Créez une application simple qui demande l'accès explicitement aux fichiers de l'appareil. Faites valider par l'enseignant
Permissions implicites

Les permissions d'accès à internet sont implicites, l'utilisateur les a d'office acceptées quand il a décidé d'installer votre application. Il existe d'autres permissions qui sont implicites.

Retour au réseau

Pour accéder au réseau, vous avez de la chance c'est une permission implicite. C'est à dire qu'elle ne donne pas lieu à une demande visuelle bloquante à l'utilisateur.
Elle est acceptée automatiquement à partir du moment où l'utilisateur installe l'application sur son mobile.

Pour ajouter la permission d'accès au réseau vous devez modifier le fichier AndroidManifest.xml de votre projet.

<!-- AndroidManifest.xml -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.example.snazzyapp">

    <uses-permission android:name="android.permission.INTERNET"/>
    <!-- other permissions go here -->

    <application ...>
        ...
    </application>
</manifest>

Par contre sur les dernières versions d'Android, il n'est plus possible par défaut d'appeler des services web non sécurisés (en http), Google recommande de toujours passer par des services https où la communication est encrypté.

Il faudra également rajouter dans le manifeste que vous souhaitez appeler des URL non sécurisées explicitement (à des fins de développement uniquement par exemple :wink: :wink:)

<!-- AndroidManifest.xml -->
    ...
    <application
        ...
        android:usesCleartextTraffic="true"
        ...
    />

Faire une requête vers un web service

Nous allons utiliser l'API Rick&Morty une simple API sans authentification pour les prochains exemples.

Et nous allons utiliser une biliothèque facilitant la création et l'exécution de requête réseau : OkHtttp. Il en existe beaucoup, mais c'est une des plus connues et utilisées, elle est également recommandée par Google.

  1. Commencez par créer un projet Android simple (API >= 22) avec une activity type Empty.
  2. Ajoutez dans vos dépendances Gradle la bibliothèque OkHttp (je vous laisse chercher)
  3. En suivant la documentation de OkHttp & de l'API, lancez une requête depuis l'Activity principale permettant de récuperer la liste des personnages de la série
Question 2 👉 Une erreur a du survenir, faites valider votre appel de requête par l'enseignant. Ou si vous avez compris l'erreur, corrigez la et faites valider. Expliquez pourquoi cette erreur est survenue ?
Question 3 👉 Lancez maintenant une requête pour récuperer un personnage en particulier. Faites valider.

👉 Meh, c'est relou ces histoires de threads ! 👈

Asynchronicité et Threads

Pourquoi ces erreurs ?

Sur mobile, vous travaillez avec des appareils ayant une puissance moindre, malgré ce qu'on vous vend avec les publicités des constructeurs, un smartphone risque d'avoir du mal à tenir constamment les 60 images par seconde lors de l'affichage, du chargement ou du traitement de données complexes.

Aussi l'expérience utilisateur sur mobile est primordial et il faut en tant que développeur, tout faire pour conserver les 60 IPS.

Il est possible de déléguer le traitement non lié à l'interface sur des fils d'exécutions  secondaires. Permettant de conserver une fluidité maximum en exploitant les différents cœurs physiques et logiques du processeur.

Généralement on appelle cela du threading, où l'on va chercher à exploiter le plus efficacement possible le processeur.

Sur Android

Sur Android et sur la JVM en général, il y a plusieurs manières de faire cela, soit en utilisant des structures spécifiques créées par le framework ou la bibliothèque que vous utilisez.

  • Sur Android il existe les AsyncTask qui sont très simples à comprendre mais plutôt lourdes à écrire. Voir ce guide sur les AsyncTask pour en apprendre plus.
  • Vous pouvez aussi avec Kotlin utiliser les coroutines qui  vont devenir la norme très rapidement. La syntaxe y est plus courte à écrire et les coroutines sont très efficaces.
  • Idem, pour en apprendre plus la doc de Kotlin est assez claire et vous permet d'expérimenter rapidement le concept.
  • Sur okHttp il existe l'interface Call qui est la manière dont les créateurs d'okHttp ont décidé de vous laisser gérer les appels sur des thread background.

Faire une requête, c'est cool, utiliser les données c'est mieux.

Les données de l'API vous sont retournées dans le format JSON, jusqu'à présent vous avez simplement récupérer les données sous forme de chaine de caractères sans pouvoir les exploiter.

L'idéal serait même d'avoir le retour de l'API sous forme d'un objet Kotlin utilisable dans votre application. Pour cela nous allons effectuer une désérialisation de la donnée reçue vers un objet Kotlin.

Des objets Kotlin

L'outil qui va nous permettre de faire ces opérations est appelé un content negociator, il en existe beaucoup, ici nous choisirons celui recommandé par OkHttp.

Question 4 👉 Lancez une requête pour récuperer un personnage, et le parser dans une instance de data class Character. Faites valider par l'enseignant. Quel Content negociator avez vous utilisé ?
Indice 📝: La bibilothèque OkHttp respectant les principes SOLID, ne fait qu'une chose : faire des requêtes HTTP, c'est un Client HTTP. Il nous faut une autre bibliothèque permettant de déserialiser les données. Lisez les Recipes de la doc OkHttp 🎓
Question 5 👉 Faites une requête pour récuperer une liste de personnages, et désérialiser le tout dans des objets Kotlin. Faites valider.
Outils 🛠: Utilisez QuickType pour facilement générer des data class Kotlin depuis une structure JSON

Fiou !

Bien joué, pour le moment vous avez simplement "lu" des informations envoyées par un web service. Mais dans le futur vous aurez à également "envoyer" des informations via HTTP ou d'autres protocoles (Socket, Web Socket, etc.).

okHttp est que le début de l'aventure, en effet pour utiliser des API conséquentes, créer soit même chaque requête est une mauvaise idée. C'est générateur d'erreurs, cela devient rapidement illisible et peu maintenable.

Maintenant pensez à combiner : ViewModel + LiveData + Données du réseau, pour avoir une architecture toujours plus propre.

🔗 Continuer le cours principal ➡️