Chapitre 3: Stockage de données – partie 1 -
Objectifs:
• Stocker des données simples
• Lire et écrire un fichier texte sur le stockage interne
• Lire et écrire un fichier texte sur un stockage externe
Introduction
Étant donné que la plupart des applications, grandes ou petites, nécessitent une sauvegarde des données. Android offre de nombreuses options. De l'enregistrement d'une simple valeur à la création de bases de données complètes à l'aide de SQLite, les options de stockage incluent les suivantes:
• Préférences partagées (shared preferences): paires nom/valeur simples
• Stockage interne: fichiers de données dans un stockage privé
• Stockage externe: fichiers de données dans un stockage privé ou public
• Base de données SQLite: données privées (peuvent être rendues publiques via un Content Provider)
• Stockage cloud: serveur privé ou fournisseur de services
Stocker des données simples
C'est une exigence courante de stocker des données simples, et Android le rend simple en utilisant l'API Préférences. Cela ne se limite pas non plus aux seules préférences de l'utilisateur; vous pouvez stocker n'importe quel type de données primitif à l'aide d'une paire nom/valeur.
Créez un nouveau projet Android avec une activité vide (Empty Activity) et appelez-le
"datastorage".
Nous utiliserons le TextView existant pour afficher un message de bienvenue et créer un nouveau EditText et un bouton pour enregistrer le nom de l'utilisateur. Commencez par ouvrir
activity_main.xml et remplacer le contenu du "layout" par le suivant:
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<EditText
android:id="@+id/editTextName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="10"
android:hint="Enter your name"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Save"
app:layout_constraintTop_toBottomOf="@+id/editTextName"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:onClick="saveName"/>
Ouvrez MainActivity.java et ajoutez les déclarations globales suivantes:
private final String NAME="NAME";
private EditText editTextName;
Ajoutez le code suivant à onCreate() pour enregistrer une référence à EditText et pour charger n'importe quel nom enregistré:
TextView textView = (TextView)findViewById(R.id.textView);
SharedPreferences sharedPreferences = getPreferences(MODE_PRIVATE);
String name = sharedPreferences.getString(NAME,null);
if (name==null) {
textView.setText("Bonjour");
} else {
textView.setText("Bon retour " + name + "!");
}
editTextName = findViewById(R.id.editTextName);
Assurez-vous d'importer les classes nécessaires.
Nous allons maintenant créer la méthode saveName pour enregistrer le nom dans EditText dans les préférences partagées.
public void saveName(View view) {
SharedPreferences.Editor editor = getPreferences(MODE_PRIVATE).edit();
editor.putString(NAME, editTextName.getText().toString());
editor.commit();
}
Pour charger le nom, nous obtenons d'abord une référence à SharedPreference et appelons la méthode getString(). Nous passons la clé de notre couple nom/valeur (nous avons créé une constante appelée NAME) et la valeur par défaut à retourner si la clé n'est pas trouvée.
Pour enregistrer la préférence, nous devons d'abord obtenir une référence à l'éditeur de préférences (SharedPreferences.Editor). Nous utilisons putString() avec notre constante NAME et la suivons avec commit(). Sans commit(), la modification ne sera pas enregistrée.
Exécutez le programme sur un appareil ou un émulateur. Puisque nous montrons des données persistantes, il charge le nom pendant onCreate(), alors enregistrez un nom et redémarrez le programme pour le voir se charger.
Lire et écrire un fichier texte sur le stockage interne
Lorsque de simples paires nom/valeur ne suffisent pas, Android prend également en charge les opérations de fichier régulières, notamment le travail avec du texte et des données binaires.
L'exemple suivant montre comment lire et écrire un fichier dans un stockage interne ou privé.
Créez une nouvelle activité vide et nommez-la InternalStorageActivity:
Assurez-vous de définir l'activité nouvellement créée en tant qu'activité LAUNCHER en modifiant le fichier AndroidManifest.xml.
Pour démontrer à la fois la lecture et l'écriture de texte, nous aurons besoin d'une mise en page avec un EditText et deux boutons. Commencez par ouvrir activity_internal_storage.xml (vous pouvez avoir un nom différent) et remplacez le contenu du layout par ce qui suit:
<EditText
android:id="@+id/editText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:inputType="textMultiLine"
android:ems="10"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@+id/buttonRead"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" />
<Button
android:id="@+id/buttonRead"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Read"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toTopOf="@+id/buttonWrite"
android:onClick="readFile"/>
<Button
android:id="@+id/buttonWrite"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Write"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:onClick="writeFile"/>
Maintenant, ouvrez InternalStorageActivity.java et ajoutez les variables globales suivantes:
private final String FILENAME="testfile_chap3_p1.txt";
EditText editTextFile;
Ajoutez ce qui suit à la méthode onCreate(), après setContentView():
editTextFile = (EditText)findViewById(R.id.editText);
Ajoutez la méthode writeFile() suivante:
public void writeFile(View view) { try {
FileOutputStream fileOutputStream = openFileOutput(FILENAME, Context.MODE_PRIVATE);
((FileOutputStream) fileOutputStream).write(editTextFile.getText().toString().getBytes());
fileOutputStream.close();
} catch (java.io.IOException e) { e.printStackTrace();
} }
Assurez-vous d'importer les classes nécessaires.
Maintenant, ajoutez la méthode readFile():
public void readFile(View view) {
StringBuilder stringBuilder = new StringBuilder();
try {
InputStream inputStream = openFileInput(FILENAME);
if ( inputStream != null ) {
InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String newLine = null;
while ((newLine = bufferedReader.readLine()) != null ) { stringBuilder.append(newLine+"\n");
}
inputStream.close();
}
} catch (java.io.IOException e) { e.printStackTrace();
}
editTextFile.setText(stringBuilder);
}
Nous utilisons les classes InputStream et FileOutputStream pour lire et écrire, respectivement. Écrire dans le fichier est aussi simple que d'obtenir le texte d'EditText et d'appeler la méthode write().
La relecture du contenu est un peu plus compliquée. Nous pourrions utiliser la classe FileInputStream pour la lecture, mais lorsque vous travaillez avec du texte, les classes “helper” facilitent les choses.
Dans notre exemple, nous ouvrons le fichier avec openFileInput(), qui renvoie un objet InputStream. Nous utilisons ensuite
InputStream pour obtenir un BufferedReader, qui propose la méthode ReadLine(). Nous parcourons chaque ligne du fichier et l'ajoutons à notre StringBuilder. Lorsque nous avons fini de lire le fichier, nous attribuons le texte à EditText.
Exécuter le programme sur un appareil ou un émulateur. Ajoutez du texte au EditText, puis appuyez sur le bouton "write". Fermez
l'application et rouvrez-la puis appuyez sur le bouton "read". Le texte enregistré doit maintenant apparaître dans le EditText.
Lire et écrire un fichier texte sur un stockage externe
Le processus de lecture et d'écriture de fichiers sur le stockage externe est fondamentalement le même que l'utilisation du stockage interne. La différence réside dans l'obtention d'une référence à l'emplacement de stockage. Notez que le stockage externe peut ne pas être disponible, il est donc préférable de vérifier la disponibilité avant d'essayer d'y accéder.
Cet exemple va lire et écrire un fichier texte, comme nous l'avons fait dans l'exemple précédent.
Nous montrerons également comment vérifier l'état du stockage externe avant d'y accéder.
Créez une nouvelle activité vide (Empty Activity) et nommez-la "ExternalStorageActivity".
Assurez-vous de définir l'activité nouvellement créée en tant qu'activité LAUNCHER en modifiant le fichier AndroidManifest.xml.
Nous utiliserons la même mise en page de l'exemple précédent. Ouvrez
activity_external_storage.xml (vous pouvez avoir un nom différent) et remplacez le contenu du layout par ce qui suit:
<EditText
android:id="@+id/editTextEXT"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:inputType="textMultiLine"
android:ems="10"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@+id/buttonReadEXT"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" />
<Button
android:id="@+id/buttonReadEXT"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Read"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toTopOf="@+id/buttonWriteEXT"
android:onClick="readFile"/>
<Button
android:id="@+id/buttonWriteEXT"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Write"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:onClick="writeFile"/>
Nous devons ajouter l'autorisation d'accéder à l'écriture sur le stockage externe. Ouvrez AndroidManifest.xml et ajoutez l'autorisation suivante:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Ensuite, ouvrez ExternalStorageActivity.java et ajoutez les variables globales suivantes:
private final String FILENAME = "testfile_chap3_p1.txt";
private final String[] PERMISSIONS_STORAGE = {
Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE };
EditText mEditText;
Ajoutez ce qui suit à la méthode onCreate(), après setContentView():
mEditText = (EditText)findViewById(R.id.editTextEXT);
Ajoutez les deux méthodes suivantes pour vérifier l'état du stockage:
public boolean isExternalStorageWritable() {
if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) { return true;
}
return false;
}
public boolean isExternalStorageReadable() {
if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()) ||
Environment.MEDIA_MOUNTED_READ_ONLY.equals(Environment.getExternalStorageState())) { return true;
}
return false;
}
Ajoutez la méthode suivante pour vérifier que l'application est autorisée à accéder au stockage externe:
public void checkStoragePermission() {
int permission = ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (permission != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, PERMISSIONS_STORAGE,101);
} }
Ajoutez la méthode writeFile() suivante:
public void writeFile(View view) { if (isExternalStorageWritable()) { checkStoragePermission();
try {
Log.i("ExternalStorageActivity",getApplicationContext().getExternalFilesDir(null).toString());
File textFile = new File(getApplicationContext().getExternalFilesDir(null), FILENAME);
FileOutputStream fileOutputStream = new FileOutputStream(textFile);
fileOutputStream.write(mEditText.getText().toString().getBytes());
fileOutputStream.close();
} catch (java.io.IOException e) { e.printStackTrace();
Toast.makeText(this, "Erreur d'écriture du fichier", Toast.LENGTH_LONG).show();
} } else {
Toast.makeText(this, "Impossible d'écrire sur le stockage externe", Toast.LENGTH_LONG).show();
} }
Ajoutez la méthode readFile() suivante:
public void readFile(View view) { if (isExternalStorageReadable()) { checkStoragePermission();
StringBuilder stringBuilder = new StringBuilder();
try {
File textFile = new File(getApplicationContext().getExternalFilesDir(null), FILENAME);
FileInputStream fileInputStream = new FileInputStream(textFile);
if (fileInputStream != null) {
InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String newLine = null;
while ((newLine = bufferedReader.readLine()) != null) { stringBuilder.append(newLine + "\n");
}
fileInputStream.close();
}
mEditText.setText(stringBuilder);
} catch (java.io.IOException e) { e.printStackTrace();
Toast.makeText(this, "Erreur de lecture du fichier", Toast.LENGTH_LONG).show();
} } else {
Toast.makeText(this, "Impossible de lire le stockage externe", Toast.LENGTH_LONG).show();
} }
Exécutez le programme sur un appareil ou un émulateur avec stockage externe.