25 janvier 2015 · 7 min de lecture
SQLite est un moteur de base de données relationnel gratuit. Il est facilement portable car le moteur et les données sont contenus dans un même fichier. C’est donc un excellent choix pour le stockage de données dans un smartphone.
Vous trouverez en bas de cet article toutes les informations utiles pour créer et gérer une base SQLite sur votre ordinateur.
Pour utiliser une base SQLite dans votre application Android, je vous propose d’étudier deux cas concrets :
Dans les deux cas, suivez les étapes suivantes.
Par exemple, vous avez une table “animal” avec les champs “id” et “nom”. On va donc créer la classe “Animal” comme suit :
public class Animal {
private int id_animal;
private String nom_animal;
// Constructeur
public Animal(int id,String nom) {
this.id_animal=id;
this.nom_animal=nom;
}
public int getId_animal() {
return id_animal;
}
public void setId_animal(int id) {
this.id_animal = id;
}
public String getNom_animal() {
return nom_animal;
}
public void setNom_animal(String nom) {
this.nom_animal = nom;
}
} // class Animal
On va utiliser une classe pour se connecter à la table “Animal” et pouvoir ainsi lire, écrire et supprimer des données :
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
public class AnimalManager {
private static final String TABLE_NAME = "animal";
public static final String KEY_ID_ANIMAL="id_animal";
public static final String KEY_NOM_ANIMAL="nom_animal";
public static final String CREATE_TABLE_ANIMAL = "CREATE TABLE "+TABLE_NAME+
" (" +
" "+KEY_ID_ANIMAL+" INTEGER primary key," +
" "+KEY_NOM_ANIMAL+" TEXT" +
");";
private MySQLite maBaseSQLite; // notre gestionnaire du fichier SQLite
private SQLiteDatabase db;
// Constructeur
public AnimalManager(Context context)
{
maBaseSQLite = MySQLite.getInstance(context);
}
public void open()
{
//on ouvre la table en lecture/écriture
db = maBaseSQLite.getWritableDatabase();
}
public void close()
{
//on ferme l'accès à la BDD
db.close();
}
public long addAnimal(Animal animal) {
// Ajout d'un enregistrement dans la table
ContentValues values = new ContentValues();
values.put(KEY_NOM_ANIMAL, animal.getNom_animal());
// insert() retourne l'id du nouvel enregistrement inséré, ou -1 en cas d'erreur
return db.insert(TABLE_NAME,null,values);
}
public int modAnimal(Animal animal) {
// modification d'un enregistrement
// valeur de retour : (int) nombre de lignes affectées par la requête
ContentValues values = new ContentValues();
values.put(KEY_NOM_ANIMAL, animal.getNom_animal());
String where = KEY_ID_ANIMAL+" = ?";
String[] whereArgs = {animal.getId_animal()+""};
return db.update(TABLE_NAME, values, where, whereArgs);
}
public int supAnimal(Animal animal) {
// suppression d'un enregistrement
// valeur de retour : (int) nombre de lignes affectées par la clause WHERE, 0 sinon
String where = KEY_ID_ANIMAL+" = ?";
String[] whereArgs = {animal.getId_animal()+""};
return db.delete(TABLE_NAME, where, whereArgs);
}
public Animal getAnimal(int id) {
// Retourne l'animal dont l'id est passé en paramètre
Animal a=new Animal(0,"");
Cursor c = db.rawQuery("SELECT * FROM "+TABLE_NAME+" WHERE "+KEY_ID_ANIMAL+"="+id, null);
if (c.moveToFirst()) {
a.setId_animal(c.getInt(c.getColumnIndex(KEY_ID_ANIMAL)));
a.setNom_animal(c.getString(c.getColumnIndex(KEY_NOM_ANIMAL)));
c.close();
}
return a;
}
public Cursor getAnimaux() {
// sélection de tous les enregistrements de la table
return db.rawQuery("SELECT * FROM "+TABLE_NAME, null);
}
} // class AnimalManager
Pour gérer le fichier SQLite, on va créer une classe qui hérite de SQLiteOpenHelper. Celle-ci inclut, entre autres, les méthodes suivantes :
On ajoute les constantes suivantes :
Revenons à nos 2 cas cités en introduction.
A) Vous créez une base vierge au premier lancement de l’application : utilisez la classe MySQLite() ci-dessous.
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
public class MySQLite extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "db.sqlite";
private static final int DATABASE_VERSION = 1;
private static MySQLite sInstance;
public static synchronized MySQLite getInstance(Context context) {
if (sInstance == null) { sInstance = new MySQLite(context); }
return sInstance;
}
private MySQLite(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
// Création de la base de données
// on exécute ici les requêtes de création des tables
sqLiteDatabase.execSQL(AnimalManager.CREATE_TABLE_ANIMAL); // création table "animal"
}
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i2) {
// Mise à jour de la base de données
// méthode appelée sur incrémentation de DATABASE_VERSION
// on peut faire ce qu'on veut ici, comme recréer la base :
onCreate(sqLiteDatabase);
}
} // class MySQLite
B) Vous utilisez une base existante.
app/src/main/assets
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.widget.Toast;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
class MySQLite extends SQLiteOpenHelper {
private final Context mycontext;
private static MySQLite sInstance;
private static final int DATABASE_VERSION = 1; // l'incrément appelle onUpgrade(), décrément => onDowngrade()
private String DATABASE_PATH; // chemin défini dans le constructeur
private static final String DATABASE_NAME = "db.sqlite";
public static synchronized MySQLite getInstance(Context context) {
if (sInstance == null) { sInstance = new MySQLite(context); }
return sInstance;
}
// Constructeur
private MySQLite(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
this.mycontext=context;
String filesDir = context.getFilesDir().getPath(); // /data/data/com.package.nom/files/
DATABASE_PATH = filesDir.substring(0, filesDir.lastIndexOf("/")) + "/databases/"; // /data/data/com.package.nom/databases/
// Si la bdd n'existe pas dans le dossier de l'app
if (!checkdatabase()) {
// copy db de 'assets' vers DATABASE_PATH
copydatabase();
}
}
private boolean checkdatabase() {
// retourne true/false si la bdd existe dans le dossier de l'app
File dbfile = new File(DATABASE_PATH + DATABASE_NAME);
return dbfile.exists();
}
// On copie la base de "assets" vers "/data/data/com.package.nom/databases"
// ceci est fait au premier lancement de l'application
private void copydatabase() {
final String outFileName = DATABASE_PATH + DATABASE_NAME;
InputStream myInput;
try {
// Ouvre la bdd de 'assets' en lecture
myInput = mycontext.getAssets().open(DATABASE_NAME);
// dossier de destination
File pathFile = new File(DATABASE_PATH);
if(!pathFile.exists()) {
if(!pathFile.mkdirs()) {
Toast.makeText(mycontext, "Erreur : copydatabase(), pathFile.mkdirs()", Toast.LENGTH_SHORT).show();
return;
}
}
// Ouverture en écriture du fichier bdd de destination
OutputStream myOutput = new FileOutputStream(outFileName);
// transfert de inputfile vers outputfile
byte[] buffer = new byte[1024];
int length;
while ((length = myInput.read(buffer)) > 0) {
myOutput.write(buffer, 0, length);
}
// Fermeture
myOutput.flush();
myOutput.close();
myInput.close();
}
catch (IOException e) {
e.printStackTrace();
Toast.makeText(mycontext, "Erreur : copydatabase()", Toast.LENGTH_SHORT).show();
}
// on greffe le numéro de version
try{
SQLiteDatabase checkdb = SQLiteDatabase.openDatabase(DATABASE_PATH + DATABASE_NAME, null, SQLiteDatabase.OPEN_READWRITE);
checkdb.setVersion(DATABASE_VERSION);
}
catch(SQLiteException e) {
// bdd n'existe pas
}
} // copydatabase()
@Override
public void onCreate(SQLiteDatabase db) {}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (oldVersion < newVersion){
//Log.d("debug", "onUpgrade() : oldVersion=" + oldVersion + ",newVersion=" + newVersion);
mycontext.deleteDatabase(DATABASE_NAME);
copydatabase();
}
} // onUpgrade
} // class MySQLite
Voici un schéma des classes Java que nous venons de créer :
Vous pouvez maintenant manipuler vos données comme ceci :
AnimalManager m = new AnimalManager(this); // gestionnaire de la table "animal"
m.open(); // ouverture de la table en lecture/écriture
// insertion. L'id sera attribué automatiquement par incrément
m.addAnimal(new Animal(0,"maya"));
// modification du nom de l'animal dont l'id est 1
Animal a=m.getAnimal(1);
a.setNom_animal("toto");
m.modAnimal(a);
// suppression
m.supAnimal(a);
// Listing des enregistrements de la table
Cursor c = m.getAnimaux();
if (c.moveToFirst())
{
do {
Log.d("test",
c.getInt(c.getColumnIndex(AnimalManager.KEY_ID_ANIMAL)) + "," +
c.getString(c.getColumnIndex(AnimalManager.KEY_NOM_ANIMAL))
);
}
while (c.moveToNext());
}
c.close(); // fermeture du curseur
// fermeture du gestionnaire
m.close();
Site officiel SQLite
https://sqlite.org
Logiciels gratuits de gestion d’une base SQLite
Créer une base SQLite en ligne de commande
sqlite3 nom_fichier
Alléger la taille d’un fichier SQLite
La commande SQL est VACUUM. Dans une console vous pouvez taper :
sqlite3 nom_fichier "VACUUM;"
Récupérer le fichier SQLite de l’émulateur Android
Pour copier le fichier SQLite depuis l’émulateur vers votre ordinateur, tapez la commande suivante dans une console, en remplaçant com.package.nom
par le nom du paquetage de votre application :
adb pull /data/data/com.package.nom/databases/db.sqlite
Chiffrer une base SQLite
sqlcipher