Comme nous l’avons vu dans le chapitre précédent, dans le cas d’Android 6.0, la demande de permission au sein du fichier AndroidManifest.xml
n’est plus suffisante. Il convient, dans le cas des permissions dites dangereuses, de demander explicitement l’autorisation à l’utilisateur. C’est ce que l’on appelle la demande de permission au runtime.
L’intégralité de ce cours est disponible dans le CourseLab OpenClassrooms !
Plan
- Les permissions sous Android (1/6) : Android et les permissions
- Les permissions sous Android (2/6) : Les différentes permissions
- Les permissions sous Android (3/6) : Demander une permission (½)
- Les permissions sous Android (4/6) : Demander une permission (2/2)
- Les permissions sous Android (5/6) : Demander plusieurs permissions
- Les permissions sous Android (6/6) : Prendre en compte une politique de sécurité particulière
Demander une permission au runtime
Nous allons donc voir comment demander la permission à l’utilisateur de passer un appel uniquement quand la permission n’est pas déjà acceptée et comment gérer les cas difficiles. C’est parti ! ;)
Vérifier si la permission est déjà acceptée
La première étape consiste à vérifier si l’application dispose d’ores-et-déjà de la permission nécessaire à notre action. Pour cela, nous pouvons utiliser la méthode statique checkSelfPermission
de la classe ActivityCompat
. Cette méthode accepte deux paramètres :
- un contexte ;
- la permission à vérifier.
Elle nous renvoie ensuite l’une des deux valeurs suivantes :
PackageManager.PERMISSION_GRANTED
si la permission est actuellement acceptés par l’utilisateur ;PackageManager.PERMISSION_DENIED
si la permission n’est actuellement pas acceptée par l’utilisateur.
Suite à la modification du code, voici ce à quoi doit normalement ressembler la méthode onClick
de notre fragment :
1 2 3 4 5 6 7 8 9 10 11 12 |
|
Vérifier si l’on doit immédiatement demander l’autorisation à l’utilisateur
Contrairement à ce que laisse croire le commentaire du code précédent, dans le cas où la permission n’est actuellement pas acceptée par l’utilisateur, nous n’allons pas immédiatement afficher une pop-up à l’utilisateur lui demandant d’accepter ou non notre permission. En effet, Google juge ce comportement un poil agressive et le proscrit.
Ainsi, il convient de vérifier si nous avons déjà demandé à l’utilisateur d’accepter ou non la permission. En fonction de sa réponse, nous allons devoir mettre en place deux comportements différents au sein de notre application :
- l’application n’a jamais demandé l’autorisation : nous la demandons à l’aide d’une pop-up système ;
- l’application a déjà demandé l’autorisation : nous affichons un mot à l’utilisateur lui expliquant pourquoi l’autorisation est nécessaire et lui nous lui proposons d’activer la permission. S’il clique sur notre bouton, nous lui affichons alors la pop-up système.
Pour savoir si l’application a déjà demandé ou non l’autorisation à l’utilisateur, il convient de d’utiliser la méthode shouldShowRequestPermissionRationale
de notre Fragment
. Cette méthode qui ne prend qu’un paramètre (la permission), nous renvoie deux valeurs possibles :
true
: dans le cas où la permission a déjà été demandée à l’utilisateur ;false
: dans le cas où la permission n’a pas déjà été demandée à l’utilisateur.
Suite à la modification du code, voici ce à quoi doit normalement ressembler la méthode onClick
de notre fragment :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|
Donner quelques explications à l’utilisateur
Avant de nous attaquer à la demande d’autorisation, je vous propose de traiter le cas qui consiste à expliquer pourquoi l’autorisation est nécessaire au bon fonctionnement de l’application.
Pour mettre en place ce message, il n’y a pas de bonne ou mauvaise façon de faire, il convient simplement que le widget graphique utilisé soit raccord avec le design général de votre application. Dans notre cas, nous allons utiliser le composant Snackbar
. Il convient alors de modifier le layout de notre fragment :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
Vous remarquerez que j’ai simplement ajouté un identifiant à mon RelativeLayout
.
Il convient maintenant, au sein de notre code java, de récupérer une référence vers ce RelativeLayout
et d’afficher notre Snackbar
avec un bouton d’action :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
|
Graphiquement, voici le rendu dans notre application :
Demander l’autorisation
Maintenant que tout est en place pour demander l’autorisation à notre utilisateur dans de bonnes conditions, nous allons pouvoir le faire. :)
Demander une permission est très simple, puisqu’il convient d’appeler la méthode requestPermissions
de la classe Fragment
. Cette méthode accepte deux paramètres :
- un tableau de permissions ;
- un code unique qui nous permettra d’identifier notre demande quand nous voudrons analyser la réponse de l’utilisateur.
C’est donc l’appel à cette méthode qui va permettre l’affichage de la pop-up système.
Voici le code du fragment mis à jour :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
|
Graphiquement, voici le rendu que vous devriez avoir dans votre application :
Gérer la réponse de l’utilisateur
Comme vous pouvez le constater, à l’affichage de la pop-up système, deux choix s’offre à l’utilisateur :
- autoriser ;
- refuser.
Nous allons donc devoir récupérer la réponse de l’utilisateur et vérifier que la permission a été acceptée ou non afin de pouvoir passer notre appel.
La récupération de la réponse de l’utilisateur doit se faire au sein de la méthode onRequestPermissionsResult
qui est une méthode de la classe Fragment
qu’il convient alors de surcharger :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
Comme vous pouvez le constater dans le morceau de code ci-dessus, cette méthode prend 3 paramètres :
requestCode
: il s’agit du fameux code unique permettant d’identifier la demande de permission dont je vous parlais plus haut ;permissions
: il s’agit des permissions qui ont fait l’objet d’une demande ;grandResults
: il s’agit du résultat de notre demande de permission.
Afin de vérifier la réponse de l’utilisateur, il convient dans un premier temps de filtrer la requête à l’aide du code unique. Dans notre cas, nous avions mis 2
:
1 2 3 4 5 6 7 8 9 10 |
|
Gérer une autorisation
Une fois notre requête identifiée, nous allons vérifier l’état de la permission en vérifiant la valeur de la première case du tableau grantResults
. Si la valeur est égale à PackageManager.PERMISSION_GRANTED
, c’est que la permission a été acceptée par l’utilisateur et que nous pouvons passer l’appel :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
Gérer un refus
Il nous reste encore un cas à traiter : celui ou l’utilisateur n’a pas accepté la permission.
Contrairement à ce que laisse penser mon commentaire, dans le cas où l’utilisateur n’a pas accepté la permission, il ne convient pas forcément de lui expliquer pourquoi la permission est nécessaire à l’aide de notre méthode explain
. En effet, dans le cas où ce n’est pas la première fois que la pop-up système est affichée à l’utilisateur, celle-ci se dote d’une case à cocher “Ne plus jamais demander” comme en témoigne la capture d’écran ci-dessous :
Dans le cas où l’utilisateur coche la case, l’appel à la méthode requestPermissions
n’aura plus aucun effet et notre pop-up système ne s’affichera plus. Le seul moyen pour que l’utilisateur puisse accepter de nouveau la permission, c’est qu’il le fasse directement depuis l’écran système d’information de l’application.
Nous allons devoir gérer les deux cas suivants :
- si l’utilisateur a cliqué sur “refuser” : nous allons appeler la méthode explain ;
- si l’utilisateur a cliqué sur “refuser” et qu’il a coché la case “Ne plus jamais demander”, nous appellerons une méthode
displayOptions
qu’il conviendra alors d’écrire.
Comment différencier les deux cas ?
J’y viens ! ;)
Pour différencier les résultats, il convient, dans le cas d’un refus de l’utilisateur, de rappeler la méthode shouldShowRequestPermissionRationale
et de vérifier son résultat.
- Si elle renvoie
false
, c’est qu’on ne peut plus justifier notre utilisation de la permission. C’est donc que l’utilisateur a refusé et qu’il a coché “Ne plus jamais demander”. - Si elle renvoie
true
, c’est que l’utilisateur refusé la permission sans cocher “Ne plus jamais demander”.
Voici ce à quoi ressemble notre méthode onRequestPermissionsResult
une fois modifiée :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
|
Comme vous pouvez le voir, j’ai écrit shouldShowRequestPermissionRationale(permissions[0])
, mais j’aurais très bien pu écrire shouldShowRequestPermissionRationale(permission.CALL_PHONE)
. Cela revient strictement au même puisque la permission demandée était la permission CALL_PHONE
. ;)
Il nous reste maintenant à écrire la fameuse méthode displayOptions
. Pour ne pas faire dans l’originalité, je vous propose, à l’image de notre méthode explain
, d’afficher un message dans une Snackbar
, à la différence près que lorsque l’utilisateur cliquera sur le bouton d’action, on ne fera pas une demande de permission, mais on ouvrira l’écran d’information système de l’application :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
Et voici le rendu graphique :
Au clic sur le bouton “Paramètres” l’utilisateur sera alors redirigé vers l’écran d’information de l’application via lequel il pourra activer manuelle la permission.
En résumé
- Demander une permission est complexe car nécessite de vérifier plusieurs cas.
- A tout moment un utilisateur peut activer ou désactiver une permission.
- Il convient de respecter l’utilisateur et de vérifier tous les cas d’usage avant de demander une permission.
Pour ceux qui en aurait besoin, voici le code complet du fragment :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
|
A lire aussi…