Baseflow / flutter-permission-handler

Permission plugin for Flutter. This plugin provides a cross-platform (iOS, Android) API to request and check permissions.
https://baseflow.com
MIT License
2.04k stars 850 forks source link

permission is showing phone setting. #655

Closed gbbest15 closed 3 years ago

gbbest15 commented 3 years ago
Map<Permission, PermissionStatus> statuses = await [
      Permission.locationWhenInUse,
      Permission.photos,
      Permission.camera,
      Permission.location,
      Permission.microphone,
      Permission.notification,
      Permission.storage,
      Permission.accessMediaLocation
    ].request();

    if (statuses[Permission.location].isDenied) {
      await Permission.location.request();
    }

but keep showing phone settings. other permission is showing but location permission is not showing not popping up instead showing phone settings.

here is the stackoverflow question https://stackoverflow.com/questions/68852007/location-permission-is-taking-me-to-appsettings

JDDV commented 3 years ago

HI @gbbest15, I tried to reproduce your issue but I can not see to get the same results. I removed the last piece of code

if (statuses[Permission.location].isDenied) {
      await Permission.location.request();     }

This way I could be certain the permission dialog about the location is from the list of permissions, and not from that if statement.

I then printed out every status of every permission, they all turned out to be true. It's possible that there are no dialogs for every permission. for example, Android does not have a Permission.photos permission, this one is for iOS only so it will not show a dialog where you can allow the permission. The same goes for different permissions that are granted by default because of the status of the permission (like the notification permission, if notifications are allowed on your phone the permission will automatically return `granted).

Also a small note, if Permission.locationWhenInUse is granted, Permission.location will always be granted too, this is also true for the other way around. So having them both in the list is not necessary. You can just use one out of the two.

If you still face this issue, can you provide me a bit more information? I would like to see/know:

gbbest15 commented 3 years ago
  1. it was tested on Android, Also the app is for both Os
  2. 
    [✓] Flutter (Channel stable, 2.2.3, on macOS 11.4 20F71 darwin-x64, locale
    en-NG)
    • Flutter version 2.2.3 at /Users/mac/Documents/Developer/flutter
    • Framework revision f4abaa0735 (7 weeks ago), 2021-07-01 12:46:11 -0700
    • Engine revision 241c87ad80
    • Dart version 2.13.4

[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.3) • Android SDK at /Users/mac/Library/Android/sdk • Platform android-30, build-tools 30.0.3 • Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6915495) • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS • Xcode at /Applications/Xcode.app/Contents/Developer • Xcode 12.4, Build version 12D4e • CocoaPods version 1.10.1

[✓] Chrome - develop for the web • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 4.1) • Android Studio at /Applications/Android Studio.app/Contents • Flutter plugin can be installed from: 🔨 https://plugins.jetbrains.com/plugin/9212-flutter • Dart plugin can be installed from: 🔨 https://plugins.jetbrains.com/plugin/6351-dart • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6915495)

[✓] VS Code (version 1.58.2) • VS Code at /Applications/Visual Studio Code.app/Contents • Flutter extension version 3.25.0

[✓] Connected device (2 available) • iPhone 12 Pro Max (mobile) • CDD00C1F-71D5-411D-8D11-74DE2986BFCF • ios • com.apple.CoreSimulator.SimRuntime.iOS-14-4 (simulator) • Chrome (web) • chrome • web-javascript • Google Chrome 92.0.4515.159

• No issues found!


3. permission_handler: "i did not specify the version but i am using the latest version"
4. testing on Samsung - but the version is above Android 9 release Mode
5.[the output on video](https://drive.google.com/file/d/1-q6tnL0RBuMA7wfaoN7GTHYSdpD1EoDu/view?usp=sharing)      check out the behaviour out put.
JDDV commented 3 years ago

Hi @gbbest15, that's weird behavior, since nowhere in the permission_handler the intent gets started to go to the location settings screen. Also the permission keeps getting asked the whole team, even though the setting is on Allow Only While Using App.

I would like to help you further but I need a bit more information about your app since I don't see anything strange. The code snippet you gave when you made this issue, is that how you ask for the permission when you go to the 'profile screen'? and does it get asked every time you go to the 'profile screen' (is that the reason why the settings screen gets prompted multiple times?).

I would like to see more of your code where you ask the permissions and get an explanation when the permissions gets asked. I've added a video as well so you can see how it looks on my Samsung S20 FE when I ask the permissions. The code I used looks like this (basically your code minus the iOS permissions):

Map<Permission, PermissionStatus> statuses = await [
      Permission.locationWhenInUse,
      Permission.camera,
      Permission.microphone,
      Permission.notification,
      Permission.storage,
    ].request();

Maybe you can try it too on your Samsung with the standard Flutter Incremental Counter app, see if it shows you the same behavior as it does in your app.

Let me know the outcome so I can help you further, thanks in advance!

https://user-images.githubusercontent.com/47666699/130237505-e29d2371-f69e-4174-beb4-33f0c197b4b5.mp4

gbbest15 commented 3 years ago

Thanks here is my code:

this is called in the login screen.... so where.

import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:permission_handler/permission_handler.dart';

class PermissionService {
  Future permissionHandler() async {
    final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
        FlutterLocalNotificationsPlugin();
    await Permission.contacts.shouldShowRequestRationale;
    if (await Permission.contacts.request().isGranted) {
      // Either the permission was already granted before or the user just granted it.
    }
    Map<Permission, PermissionStatus> statuses = await [
      Permission.location,
      Permission.photos,
      Permission.camera,
      Permission.microphone,
      Permission.notification,
      Permission.storage,
      Permission.accessMediaLocation
    ].request();

    if (statuses[Permission.location].isDenied) {
      await Permission.location.request();
    }
    if (statuses[Permission.storage].isDenied) {
      print('storage permision denied');
    }
    if (statuses[Permission.accessMediaLocation].isDenied) {
      print('accessMediaLocation permision denied');
    }
    if (statuses[Permission.camera].isDenied) {
      print('camera permision denied');
    }
    if (statuses[Permission.photos].isDenied) {
      print('photo permision denied');
    }
    if (statuses[Permission.notification].isDenied) {
      print('notification permision denied');
    }
    if (statuses[Permission.microphone].isDenied) {
      print('microphone permision denied');
    }

    final bool result = await flutterLocalNotificationsPlugin
        .resolvePlatformSpecificImplementation<
            IOSFlutterLocalNotificationsPlugin>()
        ?.requestPermissions(
          alert: true,
          badge: true,
          sound: true,
        );

    if (result) {
      print('local Notification is =========> $result');
    } else {
      print('local Notification is ======> $result');
    }
  }
}

this is call in the profile screen

import 'package:FaithMeetsLove/controller/authentication.dart';
import 'package:flutter/material.dart';
import 'package:geocoder/geocoder.dart';

import 'package:location/location.dart';

class Constants {
  static const color1 = Color(0xffFEBB53);
  static const color2 = Color(0xffBB1271);

  static const String SKIP = "Skip";
  static const String NEXT = "Next";
  static const String SLIDER_HEADING_1 = "Connect people with Faith";
  static const String SLIDER_HEADING_2 = "Easy to Use!";
  static const String SLIDER_HEADING_3 = "Connect with Others";
  static const String SLIDER_DESC =
      "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla ultricies, erat vitae porta consequat.";
}

final primaryColor = Color(0xff203152);
final greyColor = Color(0xffaeaeae);
final greyColor2 = Color(0xffE8E8E8);

getUserLocation() async {
  Location location = new Location();
  location.enableBackgroundMode(enable: true);

  bool _serviceEnabled;
  PermissionStatus _permissionGranted;
  // LocationData locationData;

  _serviceEnabled = await location.serviceEnabled();
  if (!_serviceEnabled) {
    _serviceEnabled = await location.requestService();
    if (!_serviceEnabled) {
      return;
    }
  }

  _permissionGranted = await location.hasPermission();
  if (_permissionGranted == PermissionStatus.denied) {
    _permissionGranted = await location.requestPermission();
    if (_permissionGranted != PermissionStatus.granted) {
      return;
    }
  }

  //LocationData locationData = await location.getLocation();
  location.onLocationChanged.listen((LocationData currentLocation) async {
    final coordinates =
        new Coordinates(currentLocation.latitude, currentLocation.longitude);
    var addresses =
        await Geocoder.local.findAddressesFromCoordinates(coordinates);
    var first = addresses.first;

    firestore
        .collection('users')
        .doc(auth.currentUser.uid)
        .update({'location': '${first.locality}, ${first.countryCode}'});
  });
}
gbbest15 commented 3 years ago

is working on debug here but on release is getting the wired behaviour..

dkaera commented 3 years ago

Hey guys, looks like navigation to system settings causes due to the Android OS requirements. From Android 11 in case of the app is requesting background location permission, it will navigated to the system settings instead of show popup like it was on the previous versions. Here is a link to documentation.

I guess will be great to expand interface by the adding a method that will check do we need move to the system settings for the granting permission.

JDDV commented 3 years ago

Hi @dkaera, I can not find the text on the documentation where it tells you the OS will open the settings screen for you, it only tells:

On Android 11 (API level 30) and higher, however, the system dialog doesn't include the Allow all the time option. Instead, users must enable background location on a settings page, as shown in figure 3.

Underneath that line of text it says:

You can help users navigate to this settings page by following best practices when requesting the background location permission. The process for granting the permission depends on your app's target SDK version.

So this implies it does not automatically open the setting screen, the developer can help the user though to navigate to the setting screen by executing an intent to the right screen for example.

Also @gbbest15 mentions he uses locationWhenInUse and not locationAlways, so I think what you mentioned is not the case here, but please tell me if I overlooked something!

@gbbest15 for me it works on both my emulators (Android 9, 10 and 11) and on my Samsung S20 FE in release mode., I tested it with the same code as shown in the video I've uploaded.

Maybe the weird behavior has to do with the permission you try to request/check in this piece of code in the profile screen class:

_permissionGranted = await location.hasPermission();
  if (_permissionGranted == PermissionStatus.denied) {
    _permissionGranted = await location.requestPermission();
    if (_permissionGranted != PermissionStatus.granted) {
      return;
    }
  }

Maybe this gives some kind of weird error since you check using 2 libraries if the permission is granted or denied. _permissionGranted = await location.hasPermission(); is from the location package you use. if (_permissionGranted == PermissionStatus.denied) is a check using the permission_handlers PermissionStatus.denied _permissionGranted = await location.requestPermission(); here you request it using the location package again if (_permissionGranted != PermissionStatus.granted) { And here you're checking again using the permission_handlers PermissionStatus.granted.

That might be where the fault is, mixing the function of 2 packages. Can you clean/re-code that part and let me know if it worked?

no-response[bot] commented 3 years ago

This issue has been automatically closed because there has been no response to our request for more information from the original author. With only the information that is currently in the issue, we don't have enough information to take action. Please reach out if you have or find the answers we need so that we can investigate further.