MINISTÈRE DE LA TRANSITION NUMÉRIQUE ET DE LA
DIGITALISATION
RÉPUBLIQUE DE CÔTE D’IVOIRE — Union • Discipline • Travail
ECOLE SUPERIEURE AFRICAINE DES TIC (ESATIC)
Séance 3 : Gestion des données locales
Cours magistral (CM) — Durée : 2h30
Android — Stockage local : SharedPreferences, Fichiers,
SQLite, Room
Version du 23 septembre 2025
Séance 3 — Gestion des données locales (Android) Cours magistral — 2h30
Note
Résumé de la séance. Vous apprendrez à identifier les différentes options de stockage
local sur Android, à persister des données simples (SharedPreferences), à lire/écrire des
fichiers (mémoire interne/externe), à manipuler une base locale (SQLite, Room) et à
choisir la méthode adaptée selon le cas d’usage.
Table des matières
1 Objectifs pédagogiques 2
2 Prérequis et mise en place 2
3 Introduction au stockage local 2
4 SharedPreferences 3
4.1 Principe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
4.2 Exemple (Java) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
5 Stockage de fichiers 3
5.1 Interne vs externe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
5.2 Exemple — fichier interne (Java) . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
6 SQLite — Base de données locale 4
6.1 Principe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
6.2 Helper minimal (Java) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
6.3 Insertion Lecture (Java) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
6.4 Variantes utiles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
7 Room — approche moderne 6
7.1 Avantages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
7.2 Entity DAO Database (Kotlin) . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
7.3 Repository ViewModel (Kotlin) . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
8 Choisir la bonne méthode de stockage 7
9 Exercice pratique — StudentManager 8
10 Bonnes pratiques, sécurité et performance 8
11 FAQ et pièges fréquents 9
12 Références 9
A Annexe — Checklist de révision 9
1
Séance 3 — Gestion des données locales (Android) Cours magistral — 2h30
1 Objectifs pédagogiques
— Identifier les options de stockage local sur Android.
— Utiliser SharedPreferences pour des données simples.
— Lire et écrire des fichiers internes et externes.
— Manipuler SQLite via SQLiteOpenHelper et Room.
— Décider de la méthode de stockage selon le cas d’usage.
2 Prérequis et mise en place
— Android Studio à jour, SDK 24+.
— Projet Kotlin ou Java (les exemples incluent les deux).
— Pour Room, ajouter (Gradle, module app) :
Listing 1 – Dépendances Room ([Link])
1 dependencies {
2 def room_version = "2.6.1"
3 implementation "[Link]:room-runtime:$room_version"
4 kapt "[Link]:room-compiler:$room_version" // ou ksp si configur
5 implementation "[Link]:room-ktx:$room_version"
6 }
Bonnes pratiques
Pensez à activer kapt ou ksp selon votre configuration pour la génération de code Room.
3 Introduction au stockage local
Pourquoi persister des données ?
— Préférences utilisateur : thème sombre, langue, dernier onglet.
— Données métier : notes, contacts, tâches, messages.
— Ressources multimédias : images, sons, vidéos.
Panorama des mécanismes
— SharedPreferences (clé/valeur) — SQLite (relationnel)
— Fichiers (interne/externe) — Room (ORM moderne)
2
Séance 3 — Gestion des données locales (Android) Cours magistral — 2h30
Exemple
Exemples réels :
— WhatsApp → messages en base SQLite.
— Application météo → dernière ville via SharedPreferences.
— Application photo → images en mémoire externe.
4 SharedPreferences
4.1 Principe
Système clé/valeur persistant (fichier XML interne), idéal pour de petites préférences et
drapeaux.
4.2 Exemple (Java)
Listing 2 – Sauvegarde et lecture avec SharedPreferences
1 // Sauvegarde
2 SharedPreferences prefs = getSharedPreferences("MyPrefs", MODE_PRIVATE);
3 [Link] editor = [Link]();
4 [Link]("username", "Andra");
5 [Link]("isLogged", true);
6 [Link](); // criture asynchrone
7
8 // Lecture
9 String user = [Link]("username", "Andra");
10 boolean logged = [Link]("isLogged", false);
Bonnes pratiques
Bonnes pratiques
— Préfixer les clés (ex. : [Link], [Link]).
— Pour des secrets, préférer EncryptedSharedPreferences.
— Utiliser apply() pour des écritures non bloquantes.
5 Stockage de fichiers
5.1 Interne vs externe
— Interne : privé à l’application, supprimé lors de la désinstallation.
— Externe : partagé (galerie, téléchargements), soumis aux permissions et au Scoped Storage.
3
Séance 3 — Gestion des données locales (Android) Cours magistral — 2h30
5.2 Exemple — fichier interne (Java)
Listing 3 – Écriture/Lecture fichier interne
1 String filename = "[Link]";
2 // criture
3 try (FileOutputStream fos = openFileOutput(filename, MODE_PRIVATE)) {
4 [Link]("Cours Android".getBytes());
5 } catch (IOException e) { [Link](); }
6
7 // Lecture
8 try (FileInputStream fis = openFileInput(filename)) {
9 int c; StringBuilder sb = new StringBuilder();
10 while ((c = [Link]()) != -1) [Link]((char)c);
11 Log.d("FileContent", [Link]());
12 } catch (IOException e) { [Link](); }
Attention
Sur le stockage externe, utilisez les APIs modernes (MediaStore,
ACTION_CREATE_DOCUMENT) et déclarez les permissions nécessaires (lorsque requis).
6 SQLite — Base de données locale
6.1 Principe
Base relationnelle embarquée ; schéma, SQL, transactions. Accès classique via SQLiteOpenHelper.
6.2 Helper minimal (Java)
Listing 4 – SQLiteOpenHelper : création et migration simple
1 public class MyDBHelper extends SQLiteOpenHelper {
2 public MyDBHelper(Context c) { super(c, "[Link]", null, 1); }
3
4 @Override
5 public void onCreate(SQLiteDatabase db) {
6 [Link]("CREATE TABLE Student (id INTEGER PRIMARY KEY, name TEXT, grade REAL
)");
7 }
8
9 @Override
10 public void onUpgrade(SQLiteDatabase db, int oldV, int newV) {
11 [Link]("DROP TABLE IF EXISTS Student");
12 onCreate(db);
13 }
14 }
4
Séance 3 — Gestion des données locales (Android) Cours magistral — 2h30
6.3 Insertion Lecture (Java)
Listing 5 – Operations CRUD simples
1 SQLiteDatabase db = [Link]();
2 ContentValues values = new ContentValues();
3 [Link]("name", "Alice");
4 [Link]("grade", 15.5);
5 [Link]("Student", null, values);
6
7 Cursor cursor = [Link]("Student", null, null, null, null, null, null);
8 while ([Link]()) {
9 String name = [Link](1);
10 double grade = [Link](2);
11 Log.d("Student", name + " - " + grade);
12 }
13 [Link]();
Note
Pourquoi autant de null dans [Link](...) ? La surcharge la plus utilisée est :
1 Cursor query(String table, String[] columns, String selection,
2 String[] selectionArgs, String groupBy,
3 String having, String orderBy)
Ici : columns=null (toutes les colonnes), selection=null (pas de filtre), etc. Cela signifie
« renvoie toutes les lignes/colonnes sans tri ».
6.4 Variantes utiles
Listing 6 – Projections, filtres, agrégations
1 // Projection cible et tri
2 [Link]("Student", new String[]{"id","name"}, null, null, null, null, "name ASC");
3
4 // Filtrer en scurit (prvenir l’injection SQL)
5 [Link]("Student", null, "grade >= ? AND grade <= ?",
6 new String[]{"10", "20"}, null, null, "grade DESC");
7
8 // Group By / Having
9 [Link]("Student", new String[]{"ROUND(grade) AS g", "COUNT(*) AS n"},
10 null, null, "ROUND(grade)", "COUNT(*) >= 3", "g DESC");
5
Séance 3 — Gestion des données locales (Android) Cours magistral — 2h30
7 Room — approche moderne
7.1 Avantages
Surcouche officielle à SQLite : moins de code « plomberie », sécurité des requêtes (vérifiées
à la compilation), intégration avec Flow/LiveData, migrations versionnées.
7.2 Entity DAO Database (Kotlin)
Listing 7 – Modèle Room en Kotlin
1 import [Link].*
2
3 @Entity(tableName = "Student", indices = [Index(value=["name"]), Index(value=["grade"
])])
4 data class Student(
5 @PrimaryKey(autoGenerate = true) val id: Int = 0,
6 @ColumnInfo(name = "name") val name: String,
7 @ColumnInfo(name = "grade") val grade: Double
8 )
9
10 @Dao
11 interface StudentDao {
12 @Insert suspend fun insert(s: Student): Long
13 @Update suspend fun update(s: Student): Int
14 @Delete suspend fun delete(s: Student): Int
15
16 @Query("SELECT * FROM Student WHERE id = :id")
17 suspend fun findById(id: Int): Student?
18
19 @Query("SELECT * FROM Student ORDER BY name ASC")
20 fun observeAllByNameAsc(): [Link]<List<Student>>
21
22 @Query("SELECT * FROM Student WHERE grade BETWEEN :min AND :max ORDER BY grade DESC"
)
23 fun observeByGradeRange(min: Double, max: Double): [Link]<List
<Student>>
24 }
25
26 @Database(entities = [Student::class], version = 1, exportSchema = true)
27 abstract class AppDb : RoomDatabase() {
28 abstract fun studentDao(): StudentDao
29 companion object {
30 fun build(ctx: [Link]) = [Link](ctx, AppDb::class.
java, "[Link]")
31 .fallbackToDestructiveMigration() // Remplacer par de vraies migrations en prod
32 .build()
33 }
34 }
6
Séance 3 — Gestion des données locales (Android) Cours magistral — 2h30
7.3 Repository ViewModel (Kotlin)
Listing 8 – Couche accès données + VM
1 class StudentRepo(db: AppDb) {
2 private val dao = [Link]()
3 fun streamAll() = [Link]()
4 suspend fun add(name: String, grade: Double) =
5 [Link](Student(name = [Link](), grade = grade))
6 }
7
8 class StudentVM(app: [Link]) : [Link](
app) {
9 private val repo = StudentRepo([Link](app))
10 val students = [Link]()
11 fun add(name: String, grade: Double) = [Link] {
12 [Link](name, grade)
13 }
14 }
Bonnes pratiques
Choisir entre SQLite et Room : privilégiez Room pour de nouveaux projets ; SQLite
« pur » reste utile pour du contrôle fin ou des contraintes spécifiques.
8 Choisir la bonne méthode de stockage
Besoin Solution conseillée
Petites préférences (thème, SharedPreferences (ou EncryptedSharedPrefe-
nom utilisateur) rences)
Petits fichiers (notes, photos Fichiers (interne/externe selon partage)
locales)
Données relationnelles SQLite ou Room (recommandé)
(contacts, tâches)
Données synchronisées (cloud, Services distants (API REST, Firebase)
multi-appareils)
Mini schéma de décision
7
Séance 3 — Gestion des données locales (Android) Cours magistral — 2h30
Donnée à persister ?
Préférences simples ?
clés/valeurs
Oui Non
SharedPreferences Relationnel ?
Oui Non
Room/SQLite Fichiers (media
9 Exercice pratique — StudentManager
Exercice pratique
Énoncé. Créez une app StudentManager qui enregistre le nom et la note d’un étudiant
et affiche la liste dans un RecyclerView.
Corrigé (SQLiteOpenHelper, Java)
1 MyDBHelper dbHelper = new MyDBHelper(this);
2 SQLiteDatabase db = [Link]();
3 ContentValues values = new ContentValues();
4 [Link]("name", "Bob");
5 [Link]("grade", 12.5);
6 [Link]("Student", null, values);
7 Cursor cursor = [Link]("Student", null, null, null, null, null, null);
8 while ([Link]()) {
9 Log.d("Student", [Link](1) + " - " + [Link](2));
10 }
10 Bonnes pratiques, sécurité et performance
Bonnes pratiques
— Sécurité : chiffrer les données sensibles (EncryptedSharedPreferences, chiffrement
fichiers). Ne pas stocker de secrets en clair.
— Intégrité : utiliser selectionArgs pour les paramètres SQL (prévenir l’injection).
— Migrations : versionner le schéma (Room) et écrire des migrations.
— Threading : effectuer les I/O en arrière-plan (coroutines, executors). Ne pas blo-
8
Séance 3 — Gestion des données locales (Android) Cours magistral — 2h30
quer le main thread.
— Sauvegarde/restore : vérifier le comportement avec le système de sauvegarde et
la désinstallation.
— Scoped Storage : respecter les règles Android récentes pour l’accès aux médias.
11 FAQ et pièges fréquents
— Pourquoi mes préférences ne s’écrivent pas ? Vérifiez que vous appelez apply() ou commit().
— Je vois un CursorWindow trop petit. Réduisez la projection (colonnes) et paginez vos ré-
sultats.
— Room plante à la compilation. Assurez-vous que la version Room est cohérente et que
KAPT/KSP est activé.
12 Références
— Picard, G. & Jamont, J.-P. Programmation sous Android. ENSM, 2012.
— Griffiths, D. & Griffiths, D. Head First Android Development. O’Reilly, 2021.
— Meier, R. Professional Android. Wrox, 2022.
— Google Developers. Android Data Storage (2024).
— Diapositives du cours Android.
A Annexe — Checklist de révision
# Point de contrôle
1 Clés SharedPreferences nommées proprement et centralisées.
2 Fichiers stockés au bon emplacement (interne/externe) avec permissions.
3 Requêtes SQL paramétrées (selectionArgs).
4 Migrations Room écrites et testées.
5 I/O non bloquants (coroutines/executors).
6 Données sensibles chiffrées.
7 Respect du Scoped Storage pour médias.