Les services système
Les appareils mobiles Android offrent aux applications beaucoup de fonctionnalité très spécialisée. Nous pouvons penser aux systèmes de localisation (GPS), Bluetooth, NFC, etc. L’utilisation de ces fonctionnalités peut varier, mais en général, on utilise la méthode de contexte « getSystemService » afin d’avoir accès aux différents gestionnaires de service. Cette méthode est accessible à partir de n’importe quelle activité puisque la classe « Activity » hérite de la classe « Context ». Voici les services accessibles à partir de la méthode « getSystemService »:
-
- Service de fenêtre (« WINDOW_SERVICE »)
- Permets de gérer soit même les fenêtres de son application.
- Service de « layout inflater » (« LAYOUT_INFLATER_SERVICE »)
- Retourne un « LayoutInfalter » qui peut être utilisé pour transformer un « layout » en objet « View ».
- Service d’activité (« ACTIVITY_SERVICE »)
- Permets la gestion d’une activité au niveau système
- Gestion d’arrière-plan (« WALLPAPER_SERVICE »)
- Permets la gestion (par exemple, modification) de l’arrière-plan de la page d’accueil et de la page de verrouillage de l’appareil.
- Nécessite la permission: « Manifest.permission.BIND_WALLPAPER »
- Service d’énergie (« POWER_SERVICE »)
- Permets d’avoir accès aux informations relatives à la gestion énergétique de l’appareil.
- Certaines fonctionnalités nécessitent des permissions spéciales:
- Le Wake_Lock nécessite « Manifest.permission.WAKE_LOCK »;
- Le redémarrage de l’appareil (reboot) nécessite « Manifest.permission.REBOOT »
- Service d’alarme(« ALARM_SERVICE »)
- Permets de créer des lancements planifiés de Intent;
- Permets également certaines gestions horaires de l’appareil;
- Certaines fonctionnalités nécessitent des permissions spéciales:
- Le « setTime » qui permet de modifier l’heure de l’appareil nécessite « Manifest.permission.SET_TIME »;
- Le « setTimeZone » qui permet de modifier le fuseau horaire de l’appareil nécessite « Manifest.permission.SET_TIME_ZONE »
- Service de notification (« NOTIFICATION_SERVICE »)
- Permets d’informer l’utilisateur d’action qui se déroule en arrière-plan.
- Service de désactivation du verrouillage de l’appareil (« KEYGUARD_SERVICE »)
- Permets de désactiver, temporairement et pour l’application en cours seulement, le verrouillage de l’appareil.
- Nécessite la permission « Manifest.permission.DISABLE_KEYGUARD »
- Service de localisation (« LOCATION_SERVICE »)
- Permets d’obtenir des informations à propos du positionnement de l’appareil.
- Nécessite une des permissions suivantes dans le fichier Manifest:
- « Manifest.permission.ACCESS_COARSE_LOCATION » : Permets l’obtention d’une approximation de la position
- « Manifest.permission.ACCESS_FINE_LOCATION » : Permets d’obtenir le positionnement précis de l’appareil
- Service de recherche de l’appareil (« SEARCH_SERVICE »)
- Permets d’utiliser la fonctionnalité de recherche de l’appareil
- Rarement utilisé puisqu’il y a une méthode plus facile dans activités (voir « startSearch ») pour accéder aux fonctionnalités de recherche et un « Intent » de type « ACTION_SEARCH » peut également être utilisé;
- Gestionnaire de vibration (« VIBRATOR_SERVICE »)
- Permets d’utiliser la fonctionnalité de vibration de l’appareil.
- Nécessite la permission « Manifest.permission.VIBRATE »;
- Gestionnaires de réseau: Il existe plusieurs gestionnaires qui servent à l’utilisation ou au diagnostic réseau.
- « CONNECTIVITY_SERVICE »: Valider la connexion réseau;
- « IPSEC_SERVICE »: Utiliser la fonctionnalité IPsec réseau;
- « WIFI_SERVICE »: Gestionnaire pour le WiFi;
- « WIFI_AWARE_SERVICE »: Permets d’utiliser et de localiser les appareils WiFi Aware;
- « WIFI_P2P_SERVICE »: Permets l’utilisation de la fonctionnalité de WiFi directe;
- « NETWORK_STATS_SERVICE »: Permets d’obtenir de l’information sur l’utilisation du réseau.
- À noter que plusieurs de ces fonctionnalités nécessitent des permissions pour pouvoir être utilisées. Voir la documentation pour plus de détails.
- Gestionnaire de méthodes d’entrée (« INPUT_METHOD_SERVICE »)
- Permets de gérer les méthodes d’entrées (types de clavier, reconnaissance vocale, etc.)
- Plusieurs fonctionnalités de ce gestionnaire nécessitent des permissions spéciales.
- Service de modes d’affichage (« UI_MODE_SERVICE »)
- Permets d’activer et de désactiver des modes d’affichage comme le mode nuit ou le mode voiture.
- Service de téléchargement (« DOWNLOAD_SERVICE »)
- Permets de lancer des téléchargements HTTP(S) en arrière-plan
- Nécessite la permission « Manifest.permission.INTERNET »
- Gestionnaire de batterie (« BATTERY_SERVICE »)
- Permets d’avoir de l’information à propos de la batterie de l’appareil
- Planificateur de tâche (« JOB_SCHEDULER_SERVICE »)
- Permets de planifier des tâches qui s’exécuteront dans l’application en cours
- Gestionnaire matériel (« HARDWARE_PROPERTIES_SERVICE »)
- Permets d’avoir accès aux informations sur le matériel de l’appareil.
- À noter que ce gestionnaire peut seulement être utilisé par les applications système
- Service de fenêtre (« WINDOW_SERVICE »)
Pour plus d’informations, voir la documentation de la méthode « getSystemService » ici.
À propos des permissions
Pour ajouter une permission dans le Manifest, on doit utiliser:
<uses-permission android:name="android.permission.NOM_DE_LA_PERMISSION" />
directement à la racine de la balise « <manifest> » du fichier « AndroidManifest.xml ».
Exemple
Voici un exemple où vous pouvez voir l’utilisation de 3 types de service: vibration, information sur la batterie et la désactivation de la veille de l’appareil. Pour cet exemple, vous aurez seulement besoin des fichiers de base d’un projet Android vide (MainActivity.java, activity_main.xml, etc.). Voici les fichiers qui devront être modifiés: Le fichier « ActivityMain.java »:
import androidx.appcompat.app.AppCompatActivity;
import android.os.BatteryManager;
import android.os.Build;
import android.os.Bundle;
import android.os.HardwarePropertiesManager;
import android.os.PowerManager;
import android.os.Vibrator;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initialiserWakeLock();
}
public void boutonVibrationClique(View aVue) {
Vibrator lVibreur = (Vibrator)getSystemService(VIBRATOR_SERVICE);
lVibreur.vibrate(1000);
}
public void boutonChargementClique(View aVue) {
BatteryManager lbatterie = (BatteryManager)getSystemService(BATTERY_SERVICE);
Toast lToast;
String lToastTexte;
if (Build.VERSION.SDK_INT >= 23) {
if (lbatterie.isCharging()) {
lToastTexte = getString(R.string.chargement_oui);
} else {
lToastTexte = getString(R.string.chargement_non);
}
} else {
lToastTexte = getString(R.string.chargement_indéfini);
}
lToast = Toast.makeText(this, lToastTexte , Toast.LENGTH_LONG);
}
PowerManager.WakeLock wakeLock;
public void initialiserWakeLock() {
PowerManager lPowerManager = (PowerManager)getSystemService(POWER_SERVICE);
wakeLock = lPowerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK,
this.getClass().getName());
}
public void boutonVeilleClique(View aVue) {
Button lBouton = findViewById(R.id.bouton_veille);
if (wakeLock.isHeld()) {
wakeLock.release();
lBouton.setText(R.string.bouton_veille_activer_texte);
} else {
wakeLock.acquire();
lBouton.setText(R.string.bouton_veille_deactiver_texte);
}
}
}
Le fichier « activity_main.xml »:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:orientation="vertical">
<Button
android:id="@+id/button_vibration"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:onClick="boutonVibrationClique"
android:text="@string/bouton_vibration_texte" />
<Button
android:id="@+id/bouton_chargement"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:onClick="boutonChargementClique"
android:text="@string/bouton_chargement_texte" />
<Button
android:id="@+id/bouton_veille"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:onClick="boutonVeilleClique"
android:text="@string/bouton_veille_activer_texte" />
</LinearLayout>
Le fichier « AndroidManifest.xml »:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="me.louismarchand.exempleservices">
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Le fichier « strings.xml »:
<resources>
<string name="app_name">Exemple Services</string>
<string name="bouton_vibration_texte">Vibration</string>
<string name="bouton_chargement_texte">Batterie en chargement</string>
<string name="bouton_temperature_texte">Température du processeur</string>
<string name="chargement_oui">La batterie est en chargement</string>
<string name="chargement_non">La batterie n\'est pas en chargement</string>
<string name="chargement_indéfini">La gestion de la batterie n\'est pas supportée</string>
<string name="bouton_veille_activer_texte">La veille est activé</string>
<string name="bouton_veille_deactiver_texte">La veille est désactivé</string>
</resources>
Activer les autorisation à partir du code
Dans les dernières version d’Android, ajouter la permission dans le fichier « AndroidManifest.xml » n’est plus suffisant pour permettre à l’application d’utiliser certains services. C’est le cas pour les permissions de:
- Informations d’entrainement (Senseur cardiaque, information sur les activités, etc.),
- Calendrier,
- Contacts,
- Utilisation du service téléphonique,
- SMS,
- Service de localisation (GPS)
- Utilisation des fichiers externes de l’application,
- Utilisation du microphone et de la caméra,
- Historique système.
Il est possible de laisser l’utilisateur activer manuellement l’autorisation dans les paramètres de l’application, mais il va de soi que cette manière de faire est quelque peu problématique puisque plusieurs utilisateurs d’appareils ne savent pas comment activer manuellement une autorisation dans le système. Ainsi, il y a également moyen de demander l’autorisation de l’utilisateur, directement à partir du code Java. Pour ce faire, il faut utiliser le code:
if (Build.VERSION.SDK_INT >= 23) {
requestPermissions(new String[]{Manifest.permission.LA_PERMISSION}, 1);
}
Il est à noter que ce système d’autorisation existe seulement depuis Android M (API 23). Donc, pour les systèmes avant Android M, seulement la permission dans le fichier « AndroidManifest.xml » était nécessaire. Notez également qu’il est possible ici de demander plusieurs autorisations en même temps. Sachez également que si vous voulez utiliser la fonctionnalité que vous demandez l’autorisation directement lorsque l’utilisateur l’accepte, vous ne devez pas exécuter le code du service directement après le code d’autorisation (ci-dessus). Il faut utiliser l’événement « onRequestPermissionsResult ». Il suffit de faire le redéfinir la méthode dans l’activité qui a effectué la demande d’autorisation:
@Override
public void onRequestPermissionsResult(int aCode,
String aPermission[],
int[] aAccepte) {
super.onRequestPermissionsResult(aCode, aPermission,
aAccepte);
// Exécuter le service
}
Il est d’ailleurs à noter que le « 1 » utiliser comme second argument de la méthode « requestPermissions » plus haut sert à identifier précisément la demande d’autorisation dans l’événement « onRequestPermissionsResult » (3è argument).
Finalement, puisque l’utilisateur peut refuser de donner l’autorisation, il est important d’exécuter le service à l’intérieur d’un « if » vérifiant que l’application possède l’autorisation d’utiliser le service. Voici le code permettant de valider cet autorisation:
if (Build.VERSION.SDK_INT < 23 ||
checkSelfPermission(Manifest.permission.LA_PERMISSION) ==
PackageManager.PERMISSION_GRANTED) {
// Le code du service
}
Par exemple, voici un code qui affiche le nom du premier contact de l’appareil:
private void afficherPremierContact(){
ContentResolver lContentResolver = getContentResolver();
Cursor lCurseur = lContentResolver.query(
ContactsContract.Contacts.CONTENT_URI,
null, null, null, null);
if (lCurseur != null){
if (lCurseur.getCount() > 0) {
lCurseur.moveToNext();
Log.i("Service Exemple", "Le premier contact: " +
lCurseur.getString(lCurseur.getColumnIndex(
ContactsContract.Contacts.DISPLAY_NAME)));
} else {
Log.i("Service Exemple", "L'appareil n'a aucun contacts.");
}
} else {
Log.e("Service Exemple", "Une erreur s'est produite");
}
}
Pour pouvoir utiliser ce code, il faut inscrire la permission « READ_CONTACTS » dans le « AndroidManifest.xml ». Comme ceci:
<uses-permission android:name = "android.permission.READ_CONTACTS" />
Par contre, si vous utilisez directement ce code, même avec la permission bien indiquée dans le « AndroidManifest.xml », vous obtiendrez une exception de permission. En effet, pour pouvoir utiliser ce service, l’utilisateur devra donner son autorisation. Il peut le faire manuellement dans les paramètres système de l’application:
->
Afin de faire en sorte que le code Java demande l’autorisation (sans que l’utilisateur ait à donner l’autorisation directement dans les paramètres), on peut faire le code suivant:
if (Build.VERSION.SDK_INT >= 23) {
requestPermissions(new String[]{Manifest.permission.READ_CONTACTS}, 1);
}
Ce code peut, par exemple, être utilisé dans le OnCreate, ou sur un bouton indiquant de demander l’autorisation. Si je voulais afficher le premier contact à l’instant où l’utilisateur a donné son autorisation, je pourrais faire la méthode:
@Override
public void onRequestPermissionsResult(int aCode,
String aPermission[],
int[] aAccepte) {
super.onRequestPermissionsResult(aCode, aPermission,
aAccepte);
afficherPremierContact();
}
Pour terminé, on doit modifier la méthode « afficherPremierContact » afin de s’assurer que l’application ne ferme pas lorsque l’utilisateur refuse l’autorisation d’utiliser le service de contacts:
private void afficherPremierContact(){
if (Build.VERSION.SDK_INT < 23 ||
checkSelfPermission(Manifest.permission.READ_CONTACTS) ==
PackageManager.PERMISSION_GRANTED) {
ContentResolver lContentResolver = getContentResolver();
Cursor lCurseur = lContentResolver.query(
ContactsContract.Contacts.CONTENT_URI,
null, null, null, null);
if (lCurseur != null){
if (lCurseur.getCount() > 0) {
lCurseur.moveToNext();
Log.i("Service Exemple", "Le premier contact: " +
lCurseur.getString(lCurseur.getColumnIndex(
ContactsContract.Contacts.DISPLAY_NAME)));
} else {
Log.i("Service Exemple", "L'appareil n'a aucun contacts.");
}
} else {
Log.e("Service Exemple", "Un erreur s'est produit");
}
}
}
Systèmes de fichiers
Android vous permet d’avoir accès à certaines informations concernant les systèmes de fichiers de l’appareil Android. Lorsque je parle de systèmes de fichiers, j’inclus l’emplacement des répertoires spéciaux (documents de l’utilisateur, répertoire de l’application, etc.) ou bien l’information sur l’utilisation d’une carte SD dans l’appareil. Pour avoir accès à ces informations, vous pouvez utiliser certaines méthodes de la classe « Context » (accessible à partir des activités) et certaines méthodes de la classe « Environment ». La documentation de la classe « Environment » est ici. Les méthodes de contexte permettant d’atteindre des répertoires système les plus utiles sont:
-
- getFilesDir()
- Permets d’avoir accès au répertoire de données interne de l’application
- Les fichiers sont détruits si l’application est désinstallée.
- Il n’est pas nécessaire de demander de permission pour utiliser ce répertoire.
- L’utilisateur n’a (généralement) pas accès à ce répertoire directement.
- Permets d’avoir accès au répertoire de données interne de l’application
- getCacheDir()
- Permets de stocker de l’information temporaire
- Il est de la responsabilité de l’application de supprimer les fichiers temporaires lorsque ceux-ci ne sont plus utiles.
- Les fichiers sont détruits si l’application est désinstallée.
- getExternalFilesDir(String type)
- Permets d’avoir accès aux répertoires de données de l’utilisateur (contenant les documents, téléchargements, etc.)
- Les fichiers sont détruits si l’application est désinstallée.
- L’utilisateur a accès à ces fichiers.
- Le « type » représente quel répertoire vous désirez ouvrir. Il faut utiliser les constantes « Fields » de la classe « Environment ».
- Par exemple: « DIRECTORY_DOCUMENTS », « DIRECTORY_DOWNLOADS », etc.
- Également, pour avoir accès à la racine, envoyer « null » au champ « type ».
- Permets d’avoir accès aux répertoires de données de l’utilisateur (contenant les documents, téléchargements, etc.)
- getFilesDir()
Il est à noter que depuis l’API 29, il n’est plus possible d’avoir directement accès aux données partagés de l’utilisateur (par exemple: « /sdcard/ »). Il est toujours possible d’y avoir accès, mais il faut utiliser le système de d’Accès aux répertoires de l’utilisateur (voir documentation)
Voici un exemple d’utilisation permettant d’avoir accès à un répertoire partagé et de stocker la permission de manière permanente:
public class MainActivity extends AppCompatActivity {
private String resultPath;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
validerAccesRepertoire();
}
private void validerAccesRepertoire() {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
List<UriPermission> lPermissions = getContentResolver().getPersistedUriPermissions();
if (lPermissions != null && lPermissions.size() > 0) {
resultPath = lPermissions.get(0).getUri().getPath();
Toast lToast = Toast.makeText(this,
resultPath, Toast.LENGTH_LONG);
lToast.show();
} else {
demanderAccesRepertoire();
}
}
}
private void demanderAccesRepertoire() {
Intent lIntent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
lIntent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, "/sdcard/Documents");
ActivityResultLauncher<Intent> lIntentResult = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
new demanderAccesRepertoireResultat());
lIntentResult.launch(lIntent);
}
private class demanderAccesRepertoireResultat implements
ActivityResultCallback<ActivityResult> {
@Override
public void onActivityResult(ActivityResult result) {
String lTexte = "Erreur!!!";
if (result.getResultCode() == Activity.RESULT_OK) {
Intent lIntent = result.getData();
if (Build.VERSION.SDK_INT >= 19) {
getContentResolver().takePersistableUriPermission(
lIntent.getData(),
Intent.FLAG_GRANT_READ_URI_PERMISSION);
getContentResolver().takePersistableUriPermission(
lIntent.getData(),
Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
}
resultPath = lIntent.getData().getPath();
lTexte = "Succes: " + resultPath;
} else if (result.getResultCode() == Activity.RESULT_CANCELED) {
lTexte = "Annuler!";
resultPath = null;
}
Toast lToast = Toast.makeText(getApplicationContext(),
lTexte, Toast.LENGTH_LONG);
lToast.show();
}
}
}
Également, il est à noter que depuis L’API 30 (Android 11), il est possible d’avoir accès aux répertoires contenant tous les points de montage externe (émulé ou réel) en utilisant la méthode « Environment.getStorageDirectory() ».
Finalement, prendre note que si vous désirez lire et écrire des fichiers dans le répertoire externe de l’application (par exemple, avec getExternalFilesDir), vous devrez utiliser les permissions:
-
- Manifest.permission.WRITE_EXTERNAL_STORAGE
- Permettre d’écrire dans des fichiers et de créer de nouveaux fichiers
- Manifest.permission.READ_EXTERNAL_STORAGE
- Permettre de lire le contenu des fichiers
- Manifest.permission.WRITE_EXTERNAL_STORAGE
Exemple
Voici un exemple qui affiche divers répertoires Android à l’écran. Pour cet exemple, vous aurez seulement besoin des fichiers de base d’un projet Android vide (MainActivity.java, activity_main.xml, etc.). Voici les fichiers qui devront être modifiés: Fichier « MainActivity.java »:
package me.louismarchand.exempleenvironment;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.widget.TextView;
import java.io.File;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initialiseVues();
}
private void initialiseVues(){
afficheFilePath(R.id.texte_vue_data, getFilesDir());
afficheFilePath(R.id.texte_vue_cache, getCacheDir());
afficheFilePath(R.id.texte_vue_utilisateur, getExternalFilesDir(null));
afficheFilePath(R.id.texte_vue_telechargement,
getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS));
}
private void afficheFilePath(int aId, File aFichier) {
TextView ltexteVue = findViewById(aId);
ltexteVue.setText(aFichier.getAbsolutePath());
}
}
Le fichier « activity_main.xml »:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:gravity="center"
android:layout_weight="1">
<TextView
android:id="@+id/texte_vue_data_label"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="right|center_vertical"
android:text="@string/texte_vue_data_texte" />
<TextView
android:id="@+id/texte_vue_data"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="left|center_vertical" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:layout_weight="1">
<TextView
android:id="@+id/texte_vue_cache_label"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="right|center_vertical"
android:text="@string/texte_vue_cache_texte" />
<TextView
android:id="@+id/texte_vue_cache"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="left|center_vertical" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:layout_weight="1">
<TextView
android:id="@+id/texte_vue_utilisateur_label"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="right|center_vertical"
android:text="@string/texte_vue_utilisateur_texte" />
<TextView
android:id="@+id/texte_vue_utilisateur"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="left|center_vertical" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:layout_weight="1">
<TextView
android:id="@+id/texte_vue_telechargement_label"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="right|center_vertical"
android:text="@string/texte_vue_telechargement_texte" />
<TextView
android:id="@+id/texte_vue_telechargement"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="left|center_vertical" />
</LinearLayout>
</LinearLayout>
Le fichier « strings.xml »:
<resources>
<string name="app_name">Exemple Environment</string>
<string name="texte_vue_data_texte">
Répertoire de données interne de l\'application:\u0020
</string>
<string name="texte_vue_cache_texte">
Répertoire de fichier temporaire de l\'application:\u0020
</string>
<string name="texte_vue_utilisateur_texte">
Répertoire racine des fichiers de l\'utilisateur:\u0020
</string>
<string name="texte_vue_telechargement_texte">
Répertoire des téléchargement de l\'utilisateur:\u0020
</string>
</resources>
Autre exemple
Cet exemple créera un fichier texte à la racine de la mémoire interne (sdcard) de l’appareil à l’ouverture du programme.
Voici le code java de l’Activité:
public class MainActivity extends AppCompatActivity {
private static final int AUTORISATION_ECRITURE = 123;
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == AUTORISATION_ECRITURE &&
grantResults[0] == PackageManager.PERMISSION_GRANTED) {
creerFichier();
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
demandePermission();
}
private void creerFichier(){
File lFile = new File(getExternalFilesDir(null), "test.txt");
FileWriter lWriter = null;
try {
lWriter = new FileWriter(lFile.getAbsolutePath());
lWriter.write("Allo!!!");
lWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
private void demandePermission() {
if (Build.VERSION.SDK_INT >= 23) {
requestPermissions(new String[]{
android.Manifest.permission.WRITE_EXTERNAL_STORAGE},
AUTORISATION_ECRITURE);
} else {
creerFichier();
}
}
}
Voici le fichier « AndroidManifest.xml »:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="me.louismarchand.testfichiers">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.TestFichiers">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Encore un autre
Cet exemple effectuera une lecture d’un fichier texte à la racine de la mémoire interne (sdcard) de l’appareil à l’ouverture du programme.
Le code Java de l’activité:
public class MainActivity extends AppCompatActivity {
private static final int AUTORISATION_LECTURE = 124;
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == AUTORISATION_LECTURE &&
grantResults[0] == PackageManager.PERMISSION_GRANTED) {
lireFichier();
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
demandePermission();
}
private void lireFichier(){
File lFile = new File(getExternalFilesDir(null), "test.txt");
BufferedReader lReader = null;
TextView lTexteVue = findViewById(R.id.texte_vue);
try {
lReader = new BufferedReader(new FileReader(lFile.getAbsolutePath()));
lTexteVue.setText(lReader.readLine());
} catch (IOException e) {
e.printStackTrace();
}
}
private void demandePermission() {
if (Build.VERSION.SDK_INT >= 23) {
requestPermissions(new String[]{
android.Manifest.permission.READ_EXTERNAL_STORAGE},
AUTORISATION_LECTURE);
} else {
lireFichier();
}
}
}
Le « AndroidManifest.xml »:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="me.louismarchand.testfichiers">
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.TestFichiers">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Le fichier de layout:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/texte_vue"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Auteur: Louis Marchand Sauf pour les sections spécifiées autrement, ce travail est sous licence Creative Commons Attribution 4.0 International.