Android : la persistance des données
Présentation
Android propose plusieurs possibilités pour persister des données :
-
les bases de données,
-
les SharedPreferences (préférences partagées),
-
le stockage dans des fichiers internes,
-
le stockage dans des fichiers externes.
Tous ces points seront traités dans ce chapitre.
SharedPreferences
1. Présentation
L’API SharedPreferences permet d’enregistrer des informations sous forme de clé/valeur dans des fichiers XML de manière très simple. Les objets de type SharedPreferences permettent de stocker des informations dans des fichiers pouvant soit être lus uniquement par l’activité qui a créé le fichier soit être lus par plusieurs activités différentes.
2. Fonctionnement
Pour créer un tel fichier de préférences, il existe deux fonctions :
-
getSharedPreferences() : permet de créer un fichier de préférences pouvant être lu par plusieurs activités.
-
getPreferences() : permet de créer un fichier de préférences pouvant être lu uniquement par l’activité qui l’a créé.
Si le fichier n’existe pas, ces fonctions le créent et retournent un objet permettant de modifier le fichier et si le fichier existe déjà elles retournent un objet permettant de modifier le fichier.
Les étapes pour manipuler un fichier de préférences sont :
-
Récupérer un objet de type SharedPreferences pour manipuler le fichier.
-
Manipuler le fichier avec les fonctions putXX() et getXX().
-
Enregistrer les modifications à l’aide de la fonction commit().
3. Récupérer un objet de type SharedPreferences
a. Interactivité
Le code ci-dessous montre comment récupérer un objet de type SharedPreferences pour les fichiers manipulables depuis plusieurs activités :
Récupération d’un objet de type SharedPreferences
val objetSharedPreferences =
activite?.getSharedPreferences("fichier_de_preferences"...
Fichier interne
1. Présentation
Les appareils Android peuvent enregistrer des données sur l’espace interne du téléphone. Par défaut, les fichiers enregistrés sont privés, les autres applications ne peuvent y accéder. Android fournit un répertoire privé sur le système de fichiers pour chaque application où il est possible d’organiser les fichiers dont l’application a besoin.
2. Écrire dans un fichier interne
Voici les instructions permettant d’écrire dans un fichier interne.
Exemple d’écriture dans un fichier interne
File(this.filesDir, "unFichier.txt").outputStream().use {
it.write("Bonjour !!!".toByteArray())
}
3. Lire dans un fichier interne
Voici les instructions permettant de lire dans un fichier interne.
Exemple de lecture d’un fichier interne
val recuperation = File(this.filesDir,
"unFichier.txt").bufferedReader().readText();
4. Mettre en cache un fichier interne
Il est possible de stocker des données de manière temporaire, plutôt que de les stocker de manière persistante. Il existe un répertoire de cache spécifique à cet usage pour chaque application. Lorsque l’espace de stockage interne de l’appareil est insuffisant, Android peut supprimer ces fichiers de cache pour récupérer de l’espace.
Exemple d’enregistrement de données de manière temporaire
File.createTempFile("test"...
Fichier externe
1. Présentation
Les appareils Android peuvent enregistrer des données sur des espaces de stockage externes. Ces espaces de stockages sont appelés ainsi car ils sont amovibles et peuvent parfois être inaccessibles.
Les étapes pour accéder à un espace de stockage externe sont les suivantes :
-
Avoir la permission de lecture ou/et d’écriture sur un espace de stockage externe.
-
Vérifier la disponibilité de l’espace de stockage.
-
Vérifier que le fichier/dossier sur lequel il y a un accès soit disponible.
Le système fournit des répertoires publics pour que certains fichiers tels que des photos, sonneries, musiques et autres soient disponibles pour toutes les applications.
Il est également possible d’enregistrer des fichiers sur un espace de stockage externe dans un répertoire spécifique à l’application que le système supprimera lorsque l’utilisateur désinstallera l’application. Cela permet d’avoir un plus grand espace de stockage.
Lorsque l’on parle d’espace de stockage externe on parle généralement de carte SD.
2. Permissions
Écriture
Voici la balise de permission nécessaire pour écrire sur un espace de stockage externe :
AndroidManifest.xml
<manifest ...>
<uses-permission android:name="android.
permission.WRITE_EXTERNAL_STORAGE" />
...
</manifest>
Le droit d’écriture donne implicitement le droit de lecture.
Lecture
Voici la balise de permission nécessaire pour lire sur un espace de stockage externe :
AndroidManifest.xml
<manifest ...>
<uses-permission android:name="android.
permission.READ_EXTERNAL_STORAGE" />
...
</manifest>
3. Vérifier la disponibilité d’un espace de stockage
Lecture/Écriture
Le code ci-dessous permet de tester si l’espace de stockage externe est disponible en lecture et écriture :
fun isExternalStorageWritable(): Boolean {
return Environment.getExternalStorageState() ==
Environment.MEDIA_MOUNTED
}
Lecture
Le code ci-dessous permet de tester si l’espace de stockage externe est disponible en lecture :
fun isExternalStorageReadable():...
Base de données avec SQLiteOpenHelper
1. Présentation
Il existe plusieurs méthodes pour accéder à une base de données. La méthode présentée ci-dessous utilise les fonctionnalités du package android.database.sqlite, c’est la manière historique, elle est fastidieuse, elle peut être simplifiée grâce à ANKO (cf. chapitre Android : quelques librairies incontournables - Anko). Le site Android Developer préconise d’utiliser l’ORM Room pour accéder aux données de vos applications. Malgré ces recommandations il a été choisi de présenter cette manière de faire, car elle propose des fonctionnalités bas niveau et peut s’avérer puissante pour certains cas d’utilisations. De plus, les développeurs Java pourront être curieux de voir comment cette façon de faire est mise en œuvre avec Kotlin.
2. Procédure
Pour mettre en place une base de données :
-
Créer une classe modèle pour chaque table de la bdd.
-
Créer une classe de type Contract pour chaque table de la bdd.
-
Créer une classe BddHelper héritant de SQLiteOpenHelper, cette classe va permettre de créer et mettre à jour la structure de la base de données et va aussi permettre de fournir des objets représentant la base de données.
-
Créer une DAO pour chaque table.
3. Mise en place
a. Schéma de la base de données
Pour présenter la mise en place d’une base de données, nous allons travailler sur une base de données nommée "BddExemple" contenant une table personnes avec un identifiant de type INTEGER et un nom et un prénom de type TEXT.
b. Modèle
Le code ci-dessous contient une classe objet représentant une personne :
Personne.kt
package fr.acos.sqliteopenhelperwithkotlin.bo
data class Personne constructor(val id:Int?,val nom:String, val
prenom:String)
c. Contract
Le code ci-dessous contient une classe avec les valeurs utiles pour construire et manipuler la table personnes en SQL :
Contracts.kt
package fr.acos.sqliteopenhelperwithkotlin.contracts
import android.provider.BaseColumns
object Contracts {
...