Vous êtes sur la page 1sur 32

Persistance des données

Chap. 5

• Mr. Pierre Christophe B. FAYE


Persistance des données

Ce chapitre présente les mécanismes de stockage persistant d’Android


(préférences, fichier, SQLite). Nous parlerons plus de SQLite. Cette API
offre une bibliothèque de bases de données SQL puissante, qui fournit une
couche de persistance robuste et entièrement contrôlable.
Persistance des données
Android fournit plusieurs méthodes pour faire persister les
données applicatives:
la persistance des activités (pouvoir conserver l’état de l’interface
utilisateur)
un mécanisme de sauvegarde clé/valeur, utilisé par les fichiers de
préférences(appelé préférences partagées)
des entrées sorties de type fichier
une base de données basée sur SQLite
Persistance des données
La persistance des données des activités est gérée par l'objet Bundle qui
permet de restaurer les View possèdant un id. S'il est nécessaire de
réaliser une sauvegarde plus personnalisée, il suffit de réimplémenter les
méthodes onSaveInstanceState et onCreate et d'utiliser les méthodes qui
permettent de lire/écrire des données sur l'objet Bundle.

NB: Android fournit aussi automatiquement, la persistance du chemin de


navigation de l'utilisateur, ce qui le renvoie à la bonne activité lorsqu'il
appuie sur la touche Retour.
Préférences Partagées
Les préférences partagées peuvent stocker des données de types boolean,
int, long,float et String.

La classe SharedPreferences permet de gérer des paires de clé/valeurs


associées à une activité. On récupère un tel objet par l'appel à
getPreferences:

SharedPreferences mapref = getPreferences(Context.MODE_PRIVATE);

String nom = mapref.getString(« Le nom", null);

Long taille = pref.getFloat("taille", 0.0f);


Préférences Partagées
La méthode getPreferences(int) appelle la méthode getPreferences(String,
int) à partir du nom de la classe de l'activité courante.

Le mode MODE_PRIVATE restreint l'accès au fichier créé à l'application.

Les modes d'accès MODE_WORLD_READABLE et MODE_WORLD_WRITABLE


permettent aux autres applications de lire/écrire ce fichier.
Préférences Partagées
exemple
// Sauvegarde des paramètres
SharedPreferences settings = getSharedPreferences(
« var_prefs", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = settings.edit();
editor.putString("valeur", getTxtValeur());
editor.commit();

// Récupération des anciens paramètres


SharedPreferences settings = getSharedPreferences(
« var_prefs", Context.MODE_PRIVATE);
settings.getString("valeur", "")
Les Fichiers
Android fournit aussi un accès classique au système de fichier pour tous
les cas qui ne sont pas couverts par les préférences ou la persistance des
activités.

Pour la gestion des permissions on retrouve les mêmes fonction comme


pour les préférences.

MODE_PRIVATE et MODE_WORLD_READABLE/WRITABLE

on peut ajouter la méthode MODE_APPEND pour ajouter des données.


Les Fichiers
try {
FileOutputStream out = openFileOutputStream("fichier", MODE_PRIVATE);
...
} catch (FileNotFoundException e) { ... }

Les ressources permettent aussi de récupérer un fichier embarqué dans l'application


Resources res = getResources();
InputStream is = res.openRawResource(R.raw.fichier);

NB: les fichiers sont à éviter. Mieux vaut alléger l'application au maximum et
prévoir le téléchargement de ressources nécessaires et l'utilisation de
fournisseurs de contenu.
Stockage Externe
Architecture avec une Base de Données Externe
D’un coté application Android, d'un autre, notre base de données

Objectif: faire communiquer ces deux entités, est d'utiliser un Middleware qui va
organiser, adapter et traiter les échanges entre l'application et la BDD.
Ces échanges sont possibles grâce à des Web Services, avec des langages d'échanges
adaptés tels que JSON, ou XML.
Stockage Externe
La communication
Stockage Externe
Technologie permettant de gérer les échanges

• Android (Application) - JSON (format d'échange)/REST (requêtes GET / POST) -


PHP (Middleware) - MySQL, PostgreSQL, ... (BDD)

• Android (Application) - JSON (format d'échange)/REST (requêtes GET / POST) -


JavaEE (Middleware) & JDBC - MySQL, PostgreSQL, ... (BDD)

• Android (Application) - XML (format d'échange)/SOAP - JavaEE (Middleware) &


JDBC - MySQL, PostgreSQL, ... (BDD)
BDD SQLite
Android dispose d'une base de données relationnelle basée sur SQLite. Il a
été implémenté sous la forme d’une bibliothèque C compacte incluse dans
Android.

De manière générale, les bases de données sont stockées dans les


répertoires de la forme /data/data/<package>/databases.

SQLite a une réputation de grande fiabilité et il est le SGBDR choisi par de


nombreux appareils électroniques
BDD SQLite
• Le moteur SQLite accepte les types suivants de données

Type Définition
NULL Valeur vide
INTEGER Entier signé
REAL Nombre réel
TEXT Champ texte
BLOB Champ binaire

Le type booléen n’est qu’un entier ayant pour valeur 0 et 1


BDD SQLite
Pour les dates il y a plusieurs manières de procéder

• Dans un champ TEXT : Format YYYY-MM-DD HH:MM:SS.SSS

• Dans un champ REAL : Nombre de jour depuis Greenwich le 24 Novembre


4714 avant J.C

• Dans un champ INTEGER : Nombre de seconde depuis le 01/01/1970 soit


la date au format UNIX Ne vous inquiétez pas SQLite possède des
fonctions pour manipuler les dates.
BDD SQLite
• Toutes les classes qui permettent de travailler avec les bases de données se
trouvent dans le packageandroid.database. Celles qui facilitent le travail avec
SQLite, sont placées dansandroid.database.sqlite.

• SQLiteOpenHelper : il s'agit d'une classe qui aide à créer et à gérer les versions
de la base de données. Voici les méthodes qui facilitent ces opérations :
- onCreate() : crée la structure de la base (tables, données par défaut) si elle
n'existe pas.
- onUpgrade() : actualise la structure de la base si c'est nécessaire.
- onOpen() : ouvre la base si c'est possible.
BDD SQLite
• SQLiteDatabase : les instances de cette classe sont utilisées pour gérer les
données de la base. Elles gérent les transactions, ajouts, suppressions,
actualisations ainsi que la lecture des données.

• Cursor : c'est le résultat des méthodes query(), queryWithFactory(),


rawQuery() et rawQueryWithFactory() de la classe SQLiteDatabase.
L'implémentation de cette interface Cursor fournit l'accès lecture-écriture
à des résultats retournés par les fonctions mentionnées. Si Cursor est
utilisé par plusieurs threads, il nécessite sa propre synchronisation.

• ContentValues : la classe qui stocke les données qui peuvent être traitées
par unContentResolver.
BDD SQLite
class MaBaseOpenHelper extends SQLiteOpenHelper {
public MaBaseOpenHelper(Context context, String nom, CursorFactory cursorfactory, int
version)
{
super(context, nom, cursorfactory, version);
}
@Override
public void onCreate(SQLiteDatabase db) {
// TODO Ajoutez votre code de création ici ...
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// TODO Ajoutez votre code de mise à jour ici ...
}
}
BDD SQLite
public class DictionaryOpenHelper extends SQLiteOpenHelper {
private static final int DATABASE_VERSION = 2;
private static final String DICTIONARY_TABLE_NAME = "dictionary";
private static final String DICTIONARY_TABLE_CREATE =
"CREATE TABLE " + DICTIONARY_TABLE_NAME + " (" +KEY_WORD + " TEXT, " +
KEY_DEFINITION + " TEXT);";

DictionaryOpenHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}

@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(DICTIONARY_TABLE_CREATE);
}
}
Pour faciliter la lecture de votre code il est recommandé d’utiliser des constantes pour définir les
objets liés à vos entités dans la base de données.
BDD SQLite
Lecture / Ecriture dans la BDD
Pour réaliser des écritures ou lectures, on utilise les méthodes getWritableDatabase() et
getReadableDatabase() qui renvoient une instance de SQLiteDatabase. Sur cet objet,
une requête peut être exécutée via la méthode query():
public Cursor query (boolean distinct, String table, String[] columns,
String selection, String[] selectionArgs,
String groupBy, String having, String orderBy,
String limit)
Toutes les requêtes de sélection SQLite s’effectuent via la méthode query() d’une
instance de SQLiteDatabase.
BDD SQLite
Curseurs et Content Values
Les Content Values servent à insérer de nouvelles lignes dans des tables.
Chaque objet ContentValues représente une ligne de la table sous la
forme d’une association des noms de colonnes vers les valeurs.

Sous Android, le résultat des requêtes est renvoyé sous la forme d’objets
Cursor. La classe Cursor inclut de nombreuses fonctions de déplacement:
BDD SQLite
L'objet de type Cursor permet de traiter la réponse (en lecture ou écriture)

• getCount(): nombre de lignes de la réponse


• moveToFirst(): déplace le curseur de réponse à la première ligne
• getInt(int columnIndex): retourne la valeur (int) de la colonne passée en
paramètre
• getString(int columnIndex): retourne la valeur (String) de la colonne
passée en paramètre
• moveToNext(): avance à la ligne suivante
• getColumnName(int): donne le nom de la colonne désignée par l'index
BDD SQLite
Cursor result = db.rawQuery("select id, name, position from planete",null);
result.moveToFirst();
while(!result.isAfterLast()){
int id = result.getInt(0);
String name = result.getString(result.getColumnIndex("name"));
String inventory = result.getString(2);
result.moveToNext();
}
result.close();
BDD SQLite
Insérer des données

Insérer ou mettre à jour des données dans une base SQLite repose sur
l’utilisation de la méthode insert de la classe SQLiteDatabase. Pour
spécifier les valeurs de la ligne à insérer, la méthode accepte un objet de
type ContentValues. Cet objet stocke les valeurs de chaque colonne de la
ligne à insérer sous la forme d’une collection d’associations entre le nom
de la colonne et la valeur.
BDD SQLite
public long insertPlanete(Planete planete) {
ContentValues valeurs = new ContentValues();
valeurs.put(COLONNE_NOM, planete.getNom());
valeurs.put(COLONNE_RAYON, planete.getRayon());
return maBaseDonnees.insert(TABLE_PLANETES, null, valeurs);
}

public long insertPlanete(ContentValues valeurs) {


return maBaseDonnees.insert(TABLE_PLANETES, null, valeurs);
}
BDD SQLite
Mettre à jour des données
Pour mettre à jour des données dans SQLite, utilisez la méthode update() de la
classe SQLiteDatabase en spécifiant un objet ContentValues contenant les
nouvelles valeurs et la valeur de la clause de condition WHERE.
public int updatePlanete(int id, Planete planeteToUpdate) {
ContentValues valeurs = new ContentValues();
valeurs.put(COLONNE_NOM, planeteToUpdate.getNom());
valeurs.put(COLONNE_RAYON, planeteToUpdate.getRayon());
return maBaseDonnees.update(TABLE_PLANETES, valeurs, COLONNE_ID + " = "
+ id, null);
}
public int updatePlanete(ContentValues valeurs, String where,
String[] whereArgs) {
return maBaseDonnees.update(TABLE_PLANETES, valeurs, where, whereArgs);
}
Le dernier paramètre de la méthode update est la condition – clause identique au
paramètre de la clause standard SQL UPDATE – permettant de spécifier les
éléments à mettre à jour. Seuls les éléments répondant à cette condition seront
modifiés.
BDD SQLite
Supprimer des données
Pour supprimer des données d’une table, utilisez la méthode delete() de
la classe SQLiteDatabase en spécifiant le nom de la table ciblée et le
critère permettant à la base d’identifier les éléments à supprimer.

public int removePlanete(String nom) {


return maBaseDonnees.delete(TABLE_PLANETES, COLONNE_NOM + " LIKE "
+ nom, null);
}
public int removePlanete(int id) {
return maBaseDonnees.delete(TABLE_PLANETES, COLONNE_ID + " = " + id,
null);
}
public int removePlanete(String where, String[] whereArgs) {
return maBaseDonnees.delete(TABLE_PLANETES, where, whereArgs);
}
BDD SQLite
Transactions
• Multiple opérations sont par défaut considérés comme des multiples transactions
• Chaque transaction peut être lourde
• Il est possible de regrouper ces opérations dans une transaction
try{
db.beginTransaction();
for(ContentValues valeurs:values){
db.insert("table", "", valeurs);
}
db.setTransactionSuccessful();
}
catch(SQLException e){e.printStackTrace();}
Finally{db.endTransaction();}
XML

Android fournit plusieurs parsers XML (Pull parser, Document parser, Push
parser). SAX et DOM sont disponibles. L'API de streaming (StAX) n'est pas
disponible. Cependant, une librairie équivalente est disponible:
XmlPullParser.
XML
String s = new String("<plop><blup attr=\"45\">XML Test</blup></plop>");
InputStream f = new ByteArrayInputStream(s.getBytes());
XmlPullParser parser = Xml.newPullParser();
try {
// auto-detect the encoding from the stream
parser.setInput(f, null);
parser.next();
Toast.makeText(this, parser.getName(), Toast.LENGTH_LONG).show();
parser.next();
Toast.makeText(this, parser.getName(), Toast.LENGTH_LONG).show();
Toast.makeText(this, parser.getAttributeValue(null, "attr"),
Toast.LENGTH_LONG).show();
parser.nextText();
Toast.makeText(this, parser.getText(),
Toast.LENGTH_LONG).show();
}
Conclusion

Il existe différentes façons de stocker, de manipuler et d’accéder à des


données depuis vos applications : préférences, fichiers et bases de
données. Mais c’est suivant portée de l’accès aux données, structuration
ou non des données, la rapidité en lecture et enfin, la nécessité ou non de
devoir effectuer des requêtes sur ces données que vous allez décider de
quelle technique de stockage utiliser.

Lien documentation:
http://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html
FIN

Vous aimerez peut-être aussi