Git Product home page Git Product logo

Comments (13)

mvanbeusekom avatar mvanbeusekom commented on July 29, 2024 9

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.

 avatar commented on July 29, 2024 5

@mvanbeusekom There are at least three ways to get a false shouldShowRequestPermissionRationale (didn't test service-related situations):

  1. Checking a permission that has never been requested:
    status: denied
    shouldShowRequestPermissionRationale: false

  2. Checking or requesting a permission marked as "Don't ask again":
    status: denied
    shouldShowRequestPermissionRationale: false

  3. 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.

RafaRuiz avatar RafaRuiz commented on July 29, 2024 4

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.

mvanbeusekom avatar mvanbeusekom commented on July 29, 2024 2

@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.

mvanbeusekom avatar mvanbeusekom commented on July 29, 2024 1

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.

celiyawong avatar celiyawong commented on July 29, 2024

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.

 avatar commented on July 29, 2024

@celiyawong That's exactly my point.

from flutter-permission-handler.

 avatar commented on July 29, 2024

@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.

mvanbeusekom avatar mvanbeusekom commented on July 29, 2024

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):

  1. Make a call to the checkPermissions
  2. If the return value is denied call the shouldShowPermissionRationale:
    a. If the value returned equals false, the user selected "don’t ask again".
    b. If the value equals true 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.

tonisostrat avatar tonisostrat commented on July 29, 2024

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.

 avatar commented on July 29, 2024

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.

MazEbeid avatar MazEbeid commented on July 29, 2024

@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.

RafaRuiz avatar RafaRuiz commented on July 29, 2024

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)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.