Tutoriel Android : apprendre à gérer les fichiers

Android2ee

Mathias Seguy

Ce tutoriel s'intéresse à comprendre comment bien gérer les fichiers sous Android. Il fait partie du livre "Android a complete course" dont les chapitres sont listés ci-dessous :

- Chapitre 0 : Installation et préparation de l'environnement de développement

- Chapitre 1 : Premiers pas avec Android

- Chapitre 1.1 : Cycle de vie de l'activité

- Chapitre 2.1 : Les éléments graphiques fondamentaux

- Chapitre 2.2 : Composants graphiques complexes

- Chapitre 3.3 : Intent et IntentFilters

- Chapitre 4.1 : Les Ressources

- Chapitre 4.2 : SharedPreferences et PreferenceActivity

- Chapitre 4.3 : Base de données SQLite

- Chapitre 4.4 : Gestion des fichiers

- Chapitre 5 : Content Provider

Pour réagir à ce tutoriel, un espace de dialogue vous est proposé sur le forum : Commentez

- Titre : Tutoriel Android : apprendre à gérer les fichiers

- Auteur : Mathias Seguy

- Parution : 15 février 2016

- Licence : Copyright ® 2016 MathiasSeguy. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- I. Le cœur du système

- I-A. Les fichiers

- I-A-1. Fichiers internes à l'application

- I-A-2. Fichiers externes à l'application propre à votre activité

- I-A-3. Fichiers partagés externes à l'application

- II. Conclusion et remerciements

I - Le cœur du système

I-A - Les fichiers

Les fichiers se scindent en deux groupes : ceux qui sont fournis par l'application (et sont donc read only) et ceux qui sont créés sur le terminal.

I-A-1 - Fichiers internes à l'application

Ces fichiers sont déposés par convention dans le dossier res\raw\ et on y accède dans le code de la manière usuelle par R.RAW.MonFichier :

1. InputStream inputStream = getResources().openRawResource(R.raw.internal_file);

Vous pouvez alors le lire en toute simplicité :

1. /***************************************************************************************/

2. /** Simple File reader *****************************************************************/

3. /***************************************************************************************/

4. // First implement the textView

5. TextView textViewSelected = (TextView) findViewById(R.id.TextViewSeletedFile);

6. textViewSelected.setText(fileName);

8. // First implement the textView

9. TextView textViewFile = (TextView) findViewById(R.id.TextViewFileReader);

11. // Read the file :open a InputStream on it

12. InputStream inputStream = getResources().openRawResource(R.raw.internal_file);

13. try {

14. if (inputStream != null) {

15. // open a reader on the inputStream

16. BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));

18. // String used to store the lines

19. String str;

20. StringBuilder buf = new StringBuilder();

22. // Read the file

23. while ((str = reader.readLine()) != null) {

24. buf.append(str + "\r\n");

25. }

26. // Close streams

27. reader.close();

28. inputStream.close();

29. textViewFile.setText(buf.toString());

30. }

31. } catch (java.io.FileNotFoundException e) {

32. Toast.makeText(this, "FileNotFoundException", Toast.LENGTH_LONG);

33. } catch (IOException e) {

34. Toast.makeText(this, "FileNotFoundException", Toast.LENGTH_LONG);

35. }

Si votre fichier est un fichier XML, l'exemple suivant permet de comprendre comment le manipuler :

1. /************************************************************************************/

2. /** Xml File reader *****************************************************************/

3. /************************************************************************************/

5. // First implement the textView

6. TextView textViewXmlSelected = (TextView) findViewById(R.id.TextViewSeletedXmlFile);

7. textViewXmlSelected.setText(xmlFileName);

9. // First implement the textView

10. TextView textViewXmlFile = (TextView) findViewById(R.id.TextViewXmlFileReader);

12. // Read the file

13. inputStream = getResources().openRawResource(R.raw.internal_xml_file);

14. try {

15. DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();

16. Document doc = builder.parse(inputStream, null);

17. NodeList nodes = doc.getElementsByTagName("string");

18. StringBuilder buf = new StringBuilder();

19. Element element;

20. for (int i = 0; i < nodes.getLength(); i++) {

21. element = (Element) nodes.item(i);

22. buf.append("Node name:"+element.getNodeName());

23. buf.append("\r\n\t Node Attribute name :"+element.getAttribute("name"));

24. buf.append("\r\n\t Node Text Content:"+element.getTextContent());

25. buf.append("\r\n\t node type:"+element.getNodeType());

26. buf.append("\r\n");

27. }

28. inputStream.close();

29. textViewXmlFile.setText(buf.toString());

30. } catch (java.io.FileNotFoundException e) {

31. Toast.makeText(this, "FileNotFoundException", Toast.LENGTH_LONG);

32. } catch (IOException e) {

33. Toast.makeText(this, "FileNotFoundException", Toast.LENGTH_LONG);

34. } catch (ParserConfigurationException e) {

35. e.printStackTrace();

36. } catch (SAXException e) {

37. e.printStackTrace();

38. }

Où le fichier XML est de ce type (et se nomme internal_xml_file.xml) :

1. <resources>

2. <!--Simple string-->

3. <string name="hello">Hello World, ResourcesTuto!</string>

4. <string name="app_name">ResourcesTuto</string>

5. <string name="simpleString">Good Morning My name is Bond, James Bond</string>

6. <!--String with parameters ($s for string, $d for decimal (any decimal:integer, double, float...)-->

7. <string name="param_message">Hello, i love %1$s, i hate %2$s, i am %3$d years old</string>

8. <string name="spinner">Do you like: </string>

9. <!--String array-->

10. <string-array name="i_like_array">

11. <item>chocolate</item>

12. <item>television</item>

13. <item>internet</item>

14. <item>nicotine</item>

15. <item>hug</item>

16. <item>Santa Claus</item>

17. </string-array>

18. <!--Plurals String-->

19. <plurals name="singleOrPlural">

20. <item quantity="one">I am alone on moon</item>

21. <item quantity="other">I am 6 900 000 000 on earth</item>

22. </plurals>

23. <string name="button">An image on the button</string>

24. </resources>

I-A-2 - Fichiers externes à l'application propre à votre activité

Ces fichiers sont privés à votre activité. Vous pouvez les ouvrir en lecture ou en écriture (mais pas les deux) via les méthodes openFileInput(String filename) ou openFileOutput(String fileName). Comme ces fichiers sont propres à votre activité, Android gère leur emplacement, il est donc interdit d'utiliser des chemins pour le fileName et leur extension. Il faut juste mettre le nom du fichier toto et pas .\DossierToto\toto.txt.

Quand les fichiers ont fini d'être utilisés, il faut les fermer, dans la méthode onPause de votre activité. Celle dont on est sûr qu'elle sera appelée avant la destruction de votre activité.

Pour parcourir la liste des fichiers de votre application, la méthode String[] fileList() est à votre disposition. Pour supprimer un fichier, utilisez la méthode deleteFile(FileName). Ces méthodes peuvent être utiles pour nettoyer vos fichiers dans les cas où votre application se termine de manière inopinée (i.e. potentiellement tout le temps).

Un dernier détail d'importance : deux modes d'ouverture sont disponibles pour l'ouverture en écriture des fichiers, le mode Private qui écrase le contenu existant du fichier et le mode Append qui concatène vos données à la fin du fichier :

openFileOutput(NOTES, Context.MODE_PRIVATE)

openFileOutput(NOTES, Context.MODE_APPEND)

Ainsi nous obtenons le code suivant

pour la lecture :

1. // First instanciate and fill the spinner with existing files

2. spinner = (Spinner) findViewById(R.id.SpinnerFiles);

3. ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, fileList());

4. adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);

5. spinner.setAdapter(adapter);

7. // Instanciate the first element

8. String fileName = (String) spinner.getSelectedItem();

10. // if there is a selected file, then read it

11. if (fileName != null) {

12. try {

13. //open the file and retrieve the inputStream

14. InputStream inputStream = openFileInput(fileName);

15. if (inputStream != null) {

16. // open a reader on the inputStream

17. BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));

19. // String to use to store read lines

20. String str;

21. StringBuilder buf = new StringBuilder();

23. // Read the file

24. while ((str = reader.readLine()) != null) {

25. buf.append(str + "\r\n");

26. }

27. // Close the reader

28. reader.close();

29. // Close the inputStream

30. inputStream.close();

31. // Affect the text to the textView

32. textViewFile.setText(buf.toString());

33. }

34. } catch (java.io.FileNotFoundException e) {

35. Toast.makeText(this, "FileNotFoundException", Toast.LENGTH_LONG);

36. } catch (IOException e) {

37. Toast.makeText(this, "FileNotFoundException", Toast.LENGTH_LONG);

38. }

39. }

pour l'écriture :

1. String fileNameStr="MyFileName";

2. String fileContentStr="The content of the file …";

3. try {

5. // To open you can choose the mode MODE_PRIVATE, MODE_APPEND,

6. // MODE_WORLD_READABLE, MODE_WORLD_WRITEABLE

7. // This is the creation mode (Private, World Readable et World Writable),

8. // Append is used to open the file and write at its end

9. FileOutputStream fos= openFileOutput(fileNameStr, Context.MODE_PRIVATE);

10. // Open the writer

11. OutputStreamWriter outputStreamWriter=new OutputStreamWriter(fos);

12. // Write

13. outputStreamWriter.write(fileContentStr);

14. // Close streams

15. outputStreamWriter.close();

16. fos.close();

17. } catch (FileNotFoundException e) {

18. e.printStackTrace();

19. } catch (IOException e) {

20. e.printStackTrace();

21. }

I-A-3 - Fichiers partagés externes à l'application

L'accès aux fichiers externes de votre application s'effectue au moyen d'un Content Provider qui encapsule cet accès.

L'exemple ci-dessous montre l'utilisation du MediaStore pour récupérer la liste des chansons du lecteur externe :

1. // Define the URI for the external audio files

2. Uri media = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;

4. // Define the data you want to gather

5. String[] projection = { MediaStore.Audio.Media._ID,         // 0

6. MediaStore.Audio.Media.ARTIST,      // 1

7. MediaStore.Audio.Media.TITLE,       // 2

8. MediaStore.Audio.Media.ALBUM};      // 3

10. // Define the where clause (which audio files do you want)

11. String selection = MediaStore.Audio.Media.IS_MUSIC + " != 0";

13. // Make the query

14. Cursor cursor = getContentResolver().query(media,projection,selection,null,null);

15. StringBuilder strbuilder= new StringBuilder();

17. // Browse the result of the query and do something with it:

18. while(cursor.moveToNext()) {

19. strbuilder.append("A new song from ");

20. strbuilder.append(cursor.getString(1));

21. strbuilder.append(" called ");

22. strbuilder.append(cursor.getString(2));

23. strbuilder.append(" in the Album ");

24. strbuilder.append(cursor.getString(3));

25. strbuilder.append("\r\n");

26. }

28. // Display that list

29. AlertDialog.Builder alertDialog=new AlertDialog.Builder(this);

30. alertDialog.setMessage(strbuilder.toString());

31. alertDialog.setPositiveButton("Close", new Dialog.OnClickListener() {

32. @Override

33. public void onClick(DialogInterface dialog, int which) {

34. }

35. });

36. alertDialog.show();

II - Conclusion et remerciements

Ce tutoriel s'est intéressé à expliquer comment accéder aux fichiers internes et externes à votre application.

Nous tenons à remercier Claude Leloup pour la relecture orthographique, puis Malick SECK pour la mise au gabarit.