RxTips – Permissions Android
Android Marshmallow apporte la gestion des permissions au runtime
int permissionCheck = ContextCompat.checkSelfPermission(thisActivity, Manifest.permission.WRITE_EXTERNAL_STORAGE);
Pour vérifier si nous possédons une permission, il faut apeller ContextCompat.checkSelfPermission, puis pour demander la permissions ActivityCompat.requestPermissions
private static final int MY_PERMISSIONS_WRITE_EXTERNAL_STORAGE = 1660; if (ContextCompat.checkSelfPermission(thisActivity, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(thisActivity, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, MY_PERMISSIONS_WRITE_EXTERNAL_STORAGE); } } else { //nous avons la permission openFile(); }
Le retour de cette demande se fait via la méthode onRequestPermissionsResult des activités
@Override public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { switch (requestCode) { case MY_PERMISSIONS_WRITE_EXTERNAL_STORAGE: { // If request is cancelled, the result arrays are empty. if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // permission accordée displayContacts(); } else { // permission non accordée } } } }
Le code me semble assez monstrueux seulement pour demander une permissions, et nous voyons que la méthode openFile est appelée à deux endroits, ce qui apporte une incertitude lors de la relecture du code.
Cela nous oblige aussi à repasser via l’activité pour avoir le retour d’une permission, imaginons que nous avions découpé notre code en MVC ou MVP, cela rajoute des allers retours assez inutiles.
RxPermission
Avec Rx, oubliez tout ces allers retours, commencez par importer RxPermissions dans votre build.gradle
compile 'com.tbruyelle.rxpermissions2:rxpermissions:0.9.4@aar' compile 'io.reactivex.rxjava2:rxjava:2.0.9' compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
Vous pouvez maintenant demander votre permission en une seule ligne
new RxPermissions(this) .request(Manifest.permission.WRITE_EXTERNAL_STORAGE) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(granted -> { //permission accordée }, error -> { //permission refusée } );
Si la permission est déjà accordée, ou que l’utilisateur accepte que l’application utilise cette permission, le code contenu dans subscribe(granted -> sera appelé, sinon cela lèvera une erreur, récupérée en second argument du subscribe avec error ->.
FlatMap
Pour aller encore plus loin, il est possible d’utiliser les flatMap de Rx afin d’enchainer nos appels, et être sure que la permission nous est accordée avant d’effectuer une opération,
par exemple, pour ouvrir un fichier, il nous faut la méthode WRITE_EXTERNAL_STORAGE
new RxPermissions(this) .request(Manifest.permission.WRITE_EXTERNAL_STORAGE) .flatMap(permitted -> //go to onError if permission denied return Observable.fromCallable(() -> { final String fileName = "myFile.txt"; final File file = new File(Environment.getExternalStorageDirectory(), "/Download/" + fileName); return file; }) ) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(file -> { //j'ai mon fichier ! }, error -> { //permission refusée } );
C’est beaucoup plus simple non ? 😛
Si vous ne connaissez pas RxJava, n’hésitez pas à aller faire un tour sur notre un article d’introduction sur RxJava .
Petit rappel on vient de lancer une nouvelle rubrique sur le site, où vous pouvez découvrir des livres et des Goodies Android, allez-y faire un tour 😀
1 réponse
[…] RxFingerprint et RxPermissions à votre fichier […]