Android : Stocker des données

16 novembre 2012 rdorigny 0 commentaires

Il existe plusieurs solutions pour enregistrer des données: les shared preferences, le stockage interne ou externe, la base de données SQLite, les données réseaux, les services web...

Nous allons étudier les solutions simples qui peuvent être rapidement mises en oeuvre, les méthodes plus complexes feront l'objet d'un chapitre dédié.


1) Les préférences partagées (Shared Preferences)

Cette méthodologie permet de sauvegarder des informations dans un fichier via le framework Android. Ces informations sont accessibles aux différents processus de l'application. Ce sont des données primitives (entier, booléen, ...) qui sont stockées par paire clé-donnée. On les utilise beaucoup pour sauvegarder des données de sessions ou de configuration.

Ces informations sont stockées sous /data/data/package_name/shared_prefs. Par défaut, root et l'application sont les seuls autorisés à accéder à ces informations.

1.1)Lecture de préférences

Il existe deux méthodes pour créer une préférence:
  • getSharedPreferences(String,int): renvoit une instance des prĂ©fĂ©rences de la classe SharedPreferences. Le string correspond au nom de l'ensemble de prĂ©fĂ©rence,
  • getPreferences(int): Dans la plupart des cas, et par convention, le nom de l'ensemble des prĂ©fĂ©rences est le nom de l'activitĂ© courante, et donc il est inutile de prĂ©ciser le string. Un seul ensemble est gĂ©nĂ©ralement suffisant.

  • L'entier passĂ© en paramètre prĂ©cise le mode d'accès aux prĂ©fĂ©rences. On distingue:
  • MODE_PRIVATE: l'ensemble n'est accessible que par l'application,
  • MODE_WORLD_READABLE: les autres applications peuvent lire l'ensemble,
  • MODE_WORLD_WRITEABLE: les autres applications peuvent modifier l'ensemble,
  • MODE_MULTI_PROCESS: plusieurs processus peuvent accĂ©der Ă  l'ensemble.

  • DĂ©s que nous disposons d'une instance de l'ensemble de prĂ©fĂ©rences, on utilisera des mĂ©thodes pour accĂ©der aux informations pour chaque type basique :
  • getString(variable,valeur): Cette mĂ©thode renvoit le contenu de la variable demandĂ©, si elle n'existe pas , elle renverra la valeur passĂ©e en second paramètre,
  • getInt(variable,valeur): Idem pour un entier,
  • getFloat(variable,valeur): Idem pour un rĂ©el,
  • getLong(variable,valeur): Idem pour un entier long,
  • getBoolean(variable,valeur): Idem pour un boolĂ©en,
  • getAll(variable,valeur): Renvoit une collection Map(String,?).
  • 1.2)Ecriture de prĂ©fĂ©rences

    L'interface Editor de la classe SharedPreferences dispose de toutes les méthodes pour écrire: putInt, putString, putFloat, putBoolean et putLong. Les paramétres seront la clé puis la valeur.

    Il ne faut pas oublier d'appliquer l'écriture par la méthode commit() de façon synchrone ou apply() (copie immédiate en mémoire mais asynchrone sur le disque).

    1.3)Exemple

    Pour activity_main.xml:
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Appuyez pour afficher la préférence" tools:context=".MainActivity" /> <Button android:id="@+id/bouton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="OK" /> </LinearLayout>

    Pour MainActivity.java:
    package com.example.preferenceshared; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.Toast; import android.app.Activity; import android.content.Context; import android.content.SharedPreferences; public class MainActivity extends Activity implements OnClickListener { private String texte="Ceci est un test"; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); SharedPreferences prefs=getPreferences(Context.MODE_PRIVATE); //Création de l'éditeur SharedPreferences.Editor editor=prefs.edit(); editor.putString("S1", texte); editor.commit(); Button bt =(Button) findViewById(R.id.bouton); bt.setOnClickListener(this); } @Override public void onClick(View v) { SharedPreferences prefs=getPreferences(Context.MODE_PRIVATE); String test=prefs.getString("S1", null); Toast toast=Toast.makeText(this,test,Toast.LENGTH_LONG); toast.show(); } }


    Ce qui donnera:

    A noter qu'il existe une méthodologie pour réagir aux évènements sur les modifications des préférences. On enregistre par l'écouteur .registerOnSharedPeferenceChangeLitener() et en surchargeant la méthode onSharedPreferenceChanged .

    2)Utiliser des fichiers pour stocker des données

    2.1)Généralités

    Il est possible d'utiliser la classe java.io,néanmoins le framework Android propose des outils pour manipuler les fichiers.

    Les méthodes disponibles pour le traitement des fichiers:
  • openFileOutput() de la classe OutputStream ouvre le fichier en Ă©criture avec le nom du fichier et le mode d'ouverture du fichier,
  • openFileInput() de la classe InputStream ouvre le fichier en lecture,
  • utilisez la mĂ©thode read() pour lire les donnĂ©es,
  • write() pour remplir le buffer que la mĂ©thode openFileOutput() nous a fourni,
  • close() qui permet de fermer le fichier en s'assurant que tout ce qui a Ă©tĂ© Ă©crit est bien sauvegardĂ©.

  • Les modes d'ouvertures sont:
  • MODE_PRIVATE: pour crĂ©er un fichier privĂ© Ă  votre application.
  • MODE_APPEND: possède le mĂŞme principe que MODE_PRIVATE mais possible d'Ă©crire Ă  la fin du fichier plutĂ´t que de l'Ă©craser,
  • MODE_WORLD_READABLE: permet de lire ce fichier,
  • MODE_WORLD_WRITEABLE: permet de lire ce fichier.
  • 2.2)Stockage statique

    Android propose de stocker des fichiers dans le fichier *.apk du package de l'application. Il suffit de copier vos fichiers sous res/raw/monfic.* .

    Le fichier sera intégré comme une ressource par le framework (en lecture). Et par la méthode getRessources() associé à openRawRessource(), on obtient un InputStream sur notre fichier et donc on ne pourra modifier ce fichier. Il proposera des données statiques.

    Dans l'exemple très simple qui suit, nous affichons la première ligne d'un fichier texte.

    Le fichier text.txt:
    Je lis dans le fichier.

    Le layout:
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" > <TextView android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:text="OK"/> </RelativeLayout>

    Le fichier MainActivity.java:
    package fr.doritique.filedemo; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import android.os.Bundle; import android.app.Activity; import android.widget.TextView; import android.widget.Toast; public class MainActivity extends Activity { public TextView montextview; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); montextview=(TextView) findViewById(R.id.text); try { InputStream in=getResources().openRawResource(R.raw.test); //On créé un reader pour lire dedans InputStreamReader tmp=new InputStreamReader(in); BufferedReader reader = new BufferedReader(tmp); String str=reader.readLine(); montextview.setText(str); } catch (Exception e) { Toast.makeText(this, "Marche pas", Toast.LENGTH_LONG); } } }

    2.3)Stockage interne

    Il est possible de stocker des informations dans un fichier interne sur la mémoire du téléphone.
    package fr.doritique.filedemo; import java.io.BufferedReader; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.InputStreamReader; import android.os.Bundle; import android.app.Activity; import android.content.Context; import android.widget.TextView; import android.widget.Toast; public class MainActivity extends Activity { public TextView montextview; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); montextview=(TextView) findViewById(R.id.text); String FILE_NAME = "monfic"; String string = "hello world! It's me."; //Ecriture dans un fichier try { FileOutputStream fo = openFileOutput(FILE_NAME, Context.MODE_PRIVATE); fo.write(string.getBytes()); fo.close(); } catch (Exception e) { Toast.makeText(this, "Marche pas", Toast.LENGTH_LONG); } //Lecture de la premiére ligne try { FileInputStream fo = openFileInput(FILE_NAME); InputStreamReader tmp=new InputStreamReader(fo); BufferedReader reader = new BufferedReader(tmp); montextview.setText(reader.readLine()); fo.close(); } catch (Exception e) { Toast.makeText(this, "Marche pas", Toast.LENGTH_LONG); } } }



    Le fichier sera stocké sur la mémoire interne du mobile sous /data/app/data/nom_package/files . Il est possible d'explorer les fichiers avec l'outil de debug DDMS (Dalvik Debug Monitor Server). Sous Eclipse, faire par le menu Windows -> Open Perspectives -> Others... Sélectionner DDMS puis OK. Ensuite choisir l'onglet File explorer.

    A noter qu'il est possible d'utiliser les boutons de menus pour récupérer le fichier et vérifier son contenu.

    2.4)Stockage externe

    Il s'agit de stocker un fichier dans une mémoire de masse externe à l'appareil comme par exemple avec une carte mémoire. Rappelons que le système Android est basé sur Linux, et donc il est possible d'accéder à la SDCARD par /mnt/sdcard .

    Le framework Android propose des méthodes pour tester si le stockage est disponible, ainsi que de connaitre son état (lecture & écriture). Environment.getExternalStorageState() renvoit le chemin du stockage externe, soit généralement /mnt/sdcard.
    String etat=Environment.getExternalStorageState(); //Toast.makeText(this, etat, Toast.LENGTH_LONG).show(); if (Environment.MEDIA_MOUNTED.equals(etat)){ montextview.setText("Le stockage est accessible en lecture Ă©criture."); } else { if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(etat)){ montextview.setText("Le stockage est accessible uniquement en Ă©criture."); } else montextview.setText("Le stockage n'est pas accessible."); }

    Pour autoriser l'écriture sur le stockage, il est nécessaire d'ajouter la ligne suivante au fichier manifest :
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

    Ensuite, il est possible d'Ă©crire sur la sdcard en utilisant le java classique.
    File directory=Environment.getExternalStorageDirectory(); //directory sera probablement /mnt/sdcard/ //montextview.setText(directory.toString()); File file=new File(directory+"/myfile.txt"); try { //Création du fichier if (!file.exists()){ file.createNewFile(); } //Ecriture dans le fichier FileWriter fw=new FileWriter(file); BufferedWriter writer = new BufferedWriter(fw); writer.newLine(); writer.write("Ca marche!!rnr"); writer.newLine(); writer.close(); fw.close(); // // //Lecture du fichier // FileReader fr=new FileReader(file); // BufferedReader reader = new BufferedReader(fr); // String str=reader.readLine(); // montextview.setText(str); // Toast.makeText(this, str, Toast.LENGTH_LONG).show(); // reader.close(); // fr.close(); // } catch (IOException e) { // TODO Auto-generated catch block Toast.makeText(this, "Impossible de créer le fichier.", Toast.LENGTH_LONG).show(); } }

    On trouvera le fichier sur la sdcard:

    Conclusion

    Nous avons vu dans ce chapitre les méthodes simples pour stocker des données. Nous verrons dans les prochains chapitre des solutions avancées comme l'utilisation de la base de données SQLite. A noter que le framework Android propose la facilité des menus préférences, qui facilitent la vie du développeur pour stocker les choix de configuration de l'utilisateur de l'application mobile.








    Pseudonyme (obligatoire) :
    Adresse mail (obligatoire) :
    Site web :




    © 2023 www.doritique.fr par Robert DORIGNY