Comments (13)
You have convinced me that we could maybe do a better job here and make it easier for other developers ;).
This means that we will be introducing a breaking change (since the enum value might change overnight).
from flutter-permission-handler.
@mvanbeusekom There are at least three ways to get a false
shouldShowRequestPermissionRationale
(didn't test service-related situations):
-
Checking a permission that has never been requested:
status: denied
shouldShowRequestPermissionRationale: false -
Checking or requesting a permission marked as "Don't ask again":
status: denied
shouldShowRequestPermissionRationale: false -
Checking or requesting a permission that has been granted:
status: granted
shouldShowRequestPermissionRationale: false
Please, feel free to test it:
void main() => runApp(Main());
class Main extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(body: Home()),
);
}
}
class Home extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
requestPermissionButton(),
checkPermissionButton(),
],
),
);
}
RaisedButton checkPermissionButton() {
return RaisedButton(
child: Text('Check permission'),
onPressed: checkPermissionAndPrintResult,
);
}
RaisedButton requestPermissionButton() {
return RaisedButton(
child: Text('Request permission'),
onPressed: requestPermissionAndPrintResult,
);
}
void checkPermissionAndPrintResult() async {
PermissionStatus status =
await PermissionHandler().checkPermissionStatus(PermissionGroup.microphone);
bool shouldShowRequestPermissionRationale =
await PermissionHandler().shouldShowRequestPermissionRationale(PermissionGroup.microphone);
print('status: $status');
print('shouldShowRequestPermissionRationale: $shouldShowRequestPermissionRationale');
}
void requestPermissionAndPrintResult() async {
Map<PermissionGroup, PermissionStatus> status =
await PermissionHandler().requestPermissions([PermissionGroup.microphone]);
bool shouldShowRequestPermissionRationale =
await PermissionHandler().shouldShowRequestPermissionRationale(PermissionGroup.microphone);
print('status: ${status[PermissionGroup.microphone]}');
print('shouldShowRequestPermissionRationale: $shouldShowRequestPermissionRationale');
}
}
Well, I can't distinguish between 1 and 2. As you said, seems like the only solution would be persisting if we requested permissions before, but I feel like this is a plugin responsibility. If you don't think so, at least the shouldShowRequestPermissionRationale
function should have a really clear documentation, which explains the developer its responsibility.
from flutter-permission-handler.
try this helper. It will answer "granted", "not granted" or "do not ask again".
I don't want to send a pull request because it implies another dependency (SharedPreferences)
If you think that can be added, let me know and I'll send a PR.
import 'package:flutter/foundation.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:shared_preferences/shared_preferences.dart';
enum MyAwesomeStatus { granted, notGranted, doNotAskAgain }
class PermissionHelper {
static Future<MyAwesomeStatus> askWriteExternalPermission(
TargetPlatform platform, PermissionGroup permissionGroup) async {
MyAwesomeStatus status;
if (platform == TargetPlatform.android) {
Map<PermissionGroup, PermissionStatus> permissionsGranted =
await PermissionHandler()
.requestPermissions(<PermissionGroup>[permissionGroup]);
PermissionStatus permissionStatus = permissionsGranted[permissionGroup];
if (permissionStatus == PermissionStatus.granted) {
status = MyAwesomeStatus.granted;
} else {
bool beenAsked = await hasPermissionBeenAsked(permissionGroup);
bool rationale = await PermissionHandler().shouldShowRequestPermissionRationale(permissionGroup);
if (beenAsked && !rationale) {
status = MyAwesomeStatus.doNotAskAgain;
} else {
status = MyAwesomeStatus.notGranted;
}
}
} else {
status = MyAwesomeStatus.granted;
}
setPermissionHasBeenAsked(permissionGroup);
return status;
}
static Future<void> setPermissionHasBeenAsked(
PermissionGroup permissionGroup) async {
(await SharedPreferences.getInstance())
.setBool('PERMISSION_ASKED_${permissionGroup.value}', true);
}
static Future<bool> hasPermissionBeenAsked(
PermissionGroup permissionGroup) async {
return (await SharedPreferences.getInstance())
.getBool('PERMISSION_ASKED_${permissionGroup.value}') ?? false;
}
}
from flutter-permission-handler.
@hugocbpassos, @celiyawong, you can use the shouldShowRequestPermissionRationale
method to figure this out.
This method returns true if the user has previously denied the request. But if the user has selected âDontâ ask againâ this method would always return false. It also returns false if we are prompting for permission for the first time.
from flutter-permission-handler.
This issue will be solved in our next release (4.2.0), where on Android the methods checkPermissionStatus and requestPermissions will return the neverAskAgain permission status when the user has denied the permission and selected the "Don't ask again" checkbox.
More info in PR #189.
from flutter-permission-handler.
Ibid.
selected No again ask , Then refuse, return content, versus Do not choose No again ask, return content same, Can't distinguish whether it is checked or not.
from flutter-permission-handler.
@celiyawong That's exactly my point.
from flutter-permission-handler.
@mvanbeusekom So the only way I can be 100% sure that the user selected "Don't ask again" is requesting the permission, checking if it's denied and then checking if shouldShowRequestPermissionRationale
returns false
, right? If I just want to check the permission, the same logic wouldn't work because if I haven't requested the permission at least once, it'll be denied and shouldShowRequestPermissionRationale
would return false
either. I would have to rely on my own code to know if the permission had been requested before or stop checking permissions, but always requesting.
I'm sorry, but you got to agree with me that this is a bad approach. Not only because it wouldn't work in the mentioned situation, but also because it makes things more complex and demands the plugin user to create more platform-specific code â if (Platform.isAndroid) doThis() else doThat()
.
I would be glad if you considered adding the dontAskAgain
to PermissionStatus
enum.
Please, feel free to correct me if something I said is wrong.
from flutter-permission-handler.
So to find out if the user selected âdonât ask againâ (even the first time you are requesting permissions) is (this is on Android):
- Make a call to the
checkPermissions
- If the return value is
denied
call theshouldShowPermissionRationale
:
a. If the value returned equalsfalse
, the user selected "donât ask again".
b. If the value equalstrue
it is either the first time you are requesting permissions or the user denied permissions earlier but did NOT select the âdonât ask againâ option. Either way it is save to continue requesting permissions.
So you donât have to âalwaysâ request permissions. I think I made a typo in the first reply where I said âit also returns false if we are prompting for permissions for the first timeâ this should have been true
(although documentation is not very clear on this and I havenât specifically tested it).
To my knowledge there is no other âdirectâ way on checking this on Android and this is how Google recommends it (please enlighten me if I am wrong). So if I were to solve it in the plugin, given my current understanding of the SDK, this would be the way I would implement it.
Either ways would be saving something to shared preferences and checking if we requested permissions before, however this feels more like something that the developer should decide for themselves.
from flutter-permission-handler.
I had the exact same problem on Android and I came up with this idea: I'm checking how long it takes for the requestPermissions()
method to return a value. If it's less than 100ms then I can be fairly certain it's an automatic response from the platform itself without any user interaction and I redirect the app to the Settings page, otherwise I parse the response from the requestPermissions()
method.
from flutter-permission-handler.
That's a nice trick. I could use that while this issue is opened, but I wonder how effective it is in some low-range devices.
from flutter-permission-handler.
@tonisostrat That is an awesome way of getting around this - great work.
However, it would be great if we can get a Don't Ask Again flag as it is considered Android best practice to redirect users to the setting screen in this case.
from flutter-permission-handler.
To do this we would need to store a bool
, for instance, in the SharedPreferences
and be able to call shouldShowRequestPermissionRationale
.
if shouldShowRequestPermissionRationale
is false
and it's been asked before (that's why we need the SharedPreferences
), then it's been denied forever.
from flutter-permission-handler.
Related Issues (20)
- Permission.backgroundRefresh.status not available anymore HOT 1
- /usr/include/c++/11/cmath:45:15: fatal error: math.h: No such file or directory *** 45 | #include_next <math.h> *** | ^~~~~~~~ *** compilation terminated. HOT 2
- [Bug]: Permission handler doesn't work on Android 14 HOT 1
- [Question]: isGranted getter method conflict HOT 2
- [Bug]: iOS GCC_PREPROCESSOR_DEFINITIONS 莞罎éŽé˘ HOT 1
- [Bug]: The existing windows implementation does not work in Windows 7 HOT 1
- [Feature request]: Detect when a user give a permission just for once HOT 2
- [Regression]: iOS now requires to obtain "When in use" location permission before requesting "Always" location permission
- [Question]: iOS `photosAddOnly` and `photo` always return `permanentlyDenied`, without dialog or app settings entry HOT 2
- [Question]: why set calendar Deprecated ? Forces me to use calendarFullAccessďź
- [Bug]:Permission.isDenied always return true. HOT 2
- [Question]: How to release or close camera after take photo in web flutter app ? HOT 1
- [Question]: add Android 14 permission READ_MEDIA_VISUAL_USER_SELECTED support HOT 2
- [Question]: Is POST_NOTIFICATIONS permission missing? HOT 5
- [Question]: How do we access the READ_PHONE_NUMBERS permission HOT 1
- [Bug]: Bluetooth permission on iOS permanently denied HOT 5
- [Question]: FormatException: Missing extension byte (at offset 1) HOT 4
- Remove references to deprecated v1 Android embedding HOT 1
- Kotlin version of package HOT 1
- [Feature request]: Implement full screen intent android permission request HOT 7
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
đ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. đđđ
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google â¤ď¸ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from flutter-permission-handler.