Stockage de données sous Android
Introduction
- Android propose plusieurs moyens au application de persister des données
- Chaque moyen répond à des besoins spécifiques
- Configuration partagée : table de stockage clé-valeur
- Stockage interne : stockage sur la mémoire interne
- Stockage externe : stockage sur la mémoire externe
- Base de donnée : données structurées dans une base privée
- Connexion distante vers un serveur réseau avec les outils des packages java.net et android.net
- Les données d'une application peuvent être exposées aux autres applications via un fournisseur de contenu
Configuration partagée (1/2)
- La classe SharedPreferences permet de gérer le stockage de paires clé/valeur
- Seules les données primitives sont supportées (booléens, entiers, réels et chaînes de caractères)
- Les données sont persistées même si l'application est détruite
-
Utilisation
- getPreferences() si l'application utilise un seul fichier de configuration
- getSharedPreferences() si l'application utilise plusieurs fichiers de configuration
- Les méthodes retournes une instance SharedPreferences et sa méthode edit() retourne l'éditeur SharedPreferences.Editor
- Puis utiliser les méthodes "put*" de l'éditeur
public class Calc extends Activity {
public static final String PREFS_NAME = "MyPrefsFile";
@Override
protected void onCreate(Bundle state){
super.onCreate(state);
// . . .
// Restore preferences
SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
boolean silent = settings.getBoolean("silentMode", false);
setSilent(silent);
}
@Override
protected void onStop(){
super.onStop();
// We need an Editor object to make preference changes.
// All objects are from android.context.Context
SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
SharedPreferences.Editor editor = settings.edit();
editor.putBoolean("silentMode", mSilentMode);
// Commit the edits!
editor.commit();
}
}Configuration partagée (2/2)
Stockage interne (1/2)
- Sauvegarder des fichiers sur la mémoire interne de l'appareil
- Les fichiers sauvegardés par une application sont privées par défaut et supprimés à la désinstallation
-
Utilisation
-
Utiliser openFileOutput() avec le nom du fichier à ouvrir et le mode d'ouverture
- MODE_APPEND : ouvrir le fichier et placer le curseur à la fin du fichier
- MODE_PRIVATE : fichier accessible uniquement par l'application
- La méthode retourne une instance FileOutputStream
- Utiliser ses méthodes pour écrire dans le fichier
- N'oublier de fermer le fichier avec close()
- Utiliser openFileIntput() pour lire un fichier existant
-
Utiliser openFileOutput() avec le nom du fichier à ouvrir et le mode d'ouverture
Stockage interne (2/2)
-
Autres méthodes
- getCacheDir() permet de récupérer le chemin du répertoire de cache de l'application
- getFilesDir() retourne le chemin d'enregistrement des fichiers de l'application
- getDir() créer et retourne un répertoire
- deleteFile() supprime un fichier
- fileList() retourne les fichiers enregistrés par l'application
String FILENAME = "hello_file";
String string = "hello world!";
FileOutputStream fos = openFileOutput(FILENAME, Context.MODE_PRIVATE);
fos.write(string.getBytes());
fos.close();- Exemple
Stockage externe (1/2)
- Les fichiers sauvegardés sur la mémoire externe de l'appareil peuvent être supprimés par l'utilisateur
- Des permissions sont requises pour lire et écrire dans la mémoire externe
<manifest ...>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
...
</manifest>- La méthode de l'environnement getExternalStorageState() retourne l'état du stockage externe
// Checks if external storage is available for read and write
public boolean isExternalStorageWritable() {
String state = Environment.getExternalStorageState();
return Environment.MEDIA_MOUNTED.equals(state) ? true : false;
}
// Checks if external storage is available to at least read
public boolean isExternalStorageReadable() {
String state = Environment.getExternalStorageState();
return Environment.MEDIA_MOUNTED.equals(state) ||
Environment.MEDIA_MOUNTED_READ_ONLY.equals(state) ? true : false;
}Stockage externe (2/2)
- getExternalStoragePublicDirectory() : des répertoires publics sont prévus pour stocker des fichiers partagés
public File getAlbumStorageDir(String albumName) {
// Get the directory for the user's public pictures directory.
File file = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), albumName);
if (!file.mkdirs()) {
Log.e(LOG_TAG, "Directory not created");
}
return file;
}- getExternalFilesDir() : des répertoires privés sont prévus pour stocker des fichiers uniquement pour l'application
public static final String ALBUMS_DIRNAME = "albums";
public File getAlbumStorageDir(String albumName) {
File file = new File(getExternalFilesDir(ALBUMS_DIRNAME));
if (!file.mkdirs()) {
Log.e(LOG_TAG, "Directory not created");
}
return file;
}- getExternalCacheDir() : répertoire cache sur la mémoire externe de l'appareil
Base de données (1/2)
- Android supporte les bases de données SQLite
- Il est recommandé d'utiliser la classe SQLiteOpenHelper pour gérer une base de données
- La méthode onCreate() doit être implémentée pour créer le schéma de la base
- Les méthodes getReadableDatabase() et getWritableDatabase() retourne une instance de la base
- Utiliser query() pour exécuter des requêtes
- La classe SQLiteQueryBuilder permet de créer des requetes complexes
- Une requête SQL retourne une instance Cursor pour analyser le résultat
- Le SDK fournit l'outil sqlite3 pour déboguer les bases
- Démonstrations : Note Pad et Searchable Dictianary
Base de données (2/2)
public class MyDatabaseHelper extends SQLiteOpenHelper {
public static final String DB_NAME = "database.db";
public static final int DB_VERSION = 1;
public static final String TBL_ROOMS_NAME = "rooms";
public static final String TBL_ROOMS_COLUMN_ID = "id";
public static final String TBL_ROOMS_COLUMN_LABEL = "label";
public static final String TABLES_SCHEMA = "create table "
+ TBL_ROOMS_NAME + "(" + TBL_ROOMS_COLUMN_ID
+ " integer primary key autoincrement, " + TBL_ROOMS_COLUMN_LABEL
+ " text not null);";
protected final Context context;
protected SQLiteDatabase db;
public MyDatabaseHelper(Context pContext) {
super(pContext, DB_NAME, null, DB_VERSION);
context = pContext;
}
@Override
public void onCreate(SQLiteDatabase pDb) {
db = pDb;
db.execSQL(TABLES_SCHEMA);
initDb();
}
private void initDb() {
new Thread(new Runnable() { // Starts a thread to load the database tables
public void run() {
for (String s : new String[] { "A01", "A02" }) {
ContentValues v = new ContentValues();
v.put(TBL_ROOMS_COLUMN_LABEL, s);
db.insert(TBL_ROOMS_NAME, null, v);
}
}
}).start();
}
public final SQLiteDatabase open() {
db = getWritableDatabase();
return db;
}
public final void close() {
db.close();
}
}Data Object Access (DAO)
// edu.android.db.BaseDAO.java
public abstract class BaseDAO<T>
extends MyDatabaseHelper {
public BaseDAO(Context pContext) {
super(pContext);
}
public SQLiteDatabase getDb() {
return db;
}
abstract public void create(T item);
abstract public T read(long id);
abstract public void update(T item);
abstract public void delete(long id);
abstract public List<T> list();
}
// edu.android.model.Room.java
public class Room {
private long id;
private String label;
public long getId() { return id; }
public void setId(long pId) { id = pId; }
public String getLabel() { return label; }
public void setLabel(String pLabel) { label = pLabel; }
@Override
public String toString() {
return String.format("(%d) %s", id, label);
}
}
// edu.android.db.RoomDAO.java
public class RoomDAO extends BaseDAO<Room> {
public void create(Room item) {
ContentValues value = new ContentValues();
value.put(MyDatabaseHelper.TBL_ROOMS_COLUMN_LABEL,
item.getLabel());
db.insert(MyDatabaseHelper.TBL_ROOMS_NAME, null, value);
}
public Room read(long id) {
Cursor c = db.rawQuery(
"select * from " + MyDatabaseHelper.TBL_ROOMS_NAME
+ " where " + MyDatabaseHelper.TBL_ROOMS_COLUMN_ID
+ " = ?", new String[]{String.valueOf(id)});
Room r = new Room();
// ... // ...
r.setId(c.getLong(0));
r.setLabel(c.getString(1));
c.close();
return r;
}
public void update(Room item) {
ContentValues value = new ContentValues();
value.put(MyDatabaseHelper.TBL_ROOMS_COLUMN_LABEL,
item.getLabel());
db.update(MyDatabaseHelper.TBL_ROOMS_NAME, value,
MyDatabaseHelper.TBL_ROOMS_COLUMN_ID
+ " = ?",
new String[] {String.valueOf(item.getId())}
);
}
public void remove(long id) {
db.delete(MyDatabaseHelper.TBL_ROOMS_NAME,
MyDatabaseHelper.TBL_ROOMS_COLUMN_ID
+ " = ?", new String[] {String.valueOf(id)}
);
}
@Override
public List<Room> list() {
List<Room> list = new ArrayList<Room>();
Cursor cursor = db.rawQuery("select * from "
+ TBL_ROOMS_NAME, null);
cursor.moveToFirst();
while (!cursor.isAfterLast()) {
list.add(cursorToRoom(cursor));
cursor.moveToNext();
}
cursor.close();
return list;
}
private Room cursorToRoom(Cursor cursor) {
Room room = new Room();
room.setId(cursor.getLong(0));
room.setLabel(cursor.getString(1));
return room;
}
}Stockage de données sous Android
By Steven Enten
Stockage de données sous Android
Présentation du stockage de données sous Android
- 1,547