[UX] permission handeling on android 11+
Categories
(Fenix :: General, enhancement)
Tracking
(Not tracked)
People
(Reporter: boek, Unassigned)
References
(Blocks 1 open bug)
Details
From github: https://github.com/mozilla-mobile/fenix/issues/28110.
We could consider rethinking permission handling for devices running android11+.
We need to handle "allow once" permission option introduced introduced in android11. Currently there is a bug that causes the app to treat "allow once" option as "denied" on the next run. Here is the video to demonstrate the problem:
Adding a rationale would helps us to comply with the latest guidelines by google on permission handling:
<img width="600" alt="image" src="https://user-images.githubusercontent.com/92760693/206182464-7a594e7f-cc41-41b7-a63f-00a20cd54309.png">However, the guidelines does not mention the denied forever state which we also should take into account. It happens after the user has denied the app permission twice in a row and the system will block permission options dialog from showing forever (at that point we should help the user to navigate to app settings to change the allow the permission manually).
API for permissions in not a straightforward one, and the majority of the apps (even the most popular ones) handle this flow differently (and most of the time, not by the guidelines and failing to handle all of use-cases consistently, even Chrome). The challenging parts of the flow are: when to show the rationale, how to react to a permission denial and to a blocked permission window (two "denied" permissions). There is also an option to tap outside of the window, which makes telling them apart not possible without very hacky solutions.
┆Issue is synchronized with this Jira Task
Change performed by the Move to Bugzilla add-on.
Reporter | ||
Updated•2 years ago
|
Updated•2 years ago
|
Hey,
I have a PR with the associated issue 1815638 which is blocked by this.
Wanted to add some information from the past issue where the subject was discussed.
First from a technical point of view I'm aware of two ways to have information on the permission state :
shouldShowRequestPermissionRationale
which from the documentation :Gets whether you should show UI with rationale before requesting a permission.
This will betrue
only after the user deny one time the permission. If the user deny a second time it will switch back tofalse
.isPermissionGranted
will be returned after we ask for a permission but we do not know if the user was truly prompted.
It will returntrue
when either the user accepted (now or in the past) or selected theOnly once
(which will apply for the rest of the runtime of the application).
When prompted the user will always see three possible actions : Accept
, Only Once
and Denied
.
If the user deny twice in a row the permission then we will enter the Denied Forever
state.
From my tests the user cannot set the forever denied state; if the user change the permission to denied
in the setting then it will count as a first refusal (shouldShowRequestPermissionRationale
will then return true
).
I believe the possible states are :
-
Never prompted or Always ask
shouldShowRequestPermissionRationale
isfalse
- The permission prompt will be visible
-
Granted / Allowed once (will last for the runtime of the application)
shouldShowRequestPermissionRationale
isfalse
- The permission prompt will not be visible and
isPermissionGranted=true
-
Denied one time
shouldShowRequestPermissionRationale
istrue
- The permission prompt will be visible
-
Denied a second time in a row
shouldShowRequestPermissionRationale
isfalse
- The permission prompt will not be visible and
isPermissionGranted=false
We can identify the transition when the app enter the state denied forever: shouldShowRequestPermissionRationale
will switch from being true
before asking to false
after a second refusal.
In the context of the camera permission which is only used by the application to scan QR code ? I believe in general a Rationale
will never be useful since the link between scanning and using Camera is quite understandable ?
I would expect that even in what would seem the less logical flow: a user click to scan then deny the permission, no explication is needed since what I would expect is that the user either changed opinion or misclicked. In both of those case showing a rationale
would be an hindrance I believe.
With this in mind I proposed the following flow :
- Always try to prompt permission (the user might see nothing)
- Use a setting to register when we enter the
Denied Forever
state (I see no other way :() - Display the
Permission Needed
only when we believe the user did not see any prompt:isPermissionGranted=false
and we believe we already were inDenied Forever
state.
The important point is to always ask and rely on the internal state only to display the Permission Needed
when we believe the user did not see any prompt. This allow to minimize the impact of an invalid state.
The possible desync would be :
- We do not display the
Permission Needed
even when the user did not see the permission prompt.
I believe this is impossible since the user cannot enter theDenied forever
state outside of the application (setting permission asdenied
count as one refusal). - The user will be prompted with
Permission Needed
when he just refused, for this I believe the user would need to :- Refuse twice to enter the
Denied Forever
state. - Outside of the application switch the permission to allow to reset the denied state
- Outside of the application switch the permission to deny (it will count as a refusal)
- Deny the permission when prompted
- Refuse twice to enter the
Additionally made some tests using a phone running Android 10, from what I tested the handling is quite similar (outside of no Allowed Once
) it's just that instead of the denied forever being automatic the user is presented with an additional deny forever
option after declining a permission once.
Similarly a scenario exist where the user can be prompted by the Permission Needed
even when he just refused, but it relies too in modifying the permission outside of the app in a similar way :
- After refusing once the permission the user activate the Denied forever option
- Outside of the application switch the permission to allow to reset the denied state
- Outside of the application switch the permission to deny (it will count as a refusal)
- When prompt again click
Deny
orDeny Forever
As mentioned this solution can be tested in #822.
Description
•