如何解决 "gps" 位置提供者需要 ACCESS_FINE_LOCATION 权限

How to solve "gps" location provider requires ACCESS_FINE_LOCATION permission

我正在开发一个 flutter 应用程序,它使用位置包来跟踪用户位置,它运行良好,但在同样的情况下,我已将位置包升级到 4.0.0(从 3.0.1),但现在是问题如出现:

E/AndroidRuntime(12224): at java.lang.reflect.Method.invoke(Native Method) E/AndroidRuntime(12224): at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492) E/AndroidRuntime(12224): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:980) E/AndroidRuntime(12224): Caused by: android.os.RemoteException: Remote stack trace: E/AndroidRuntime(12224): at com.android.server.LocationManagerService.checkResolutionLevelIsSufficientForProviderUseLocked(LocationManagerService.java:1979) E/AndroidRuntime(12224): at com.android.server.LocationManagerService.hasGnssPermissions(LocationManagerService.java:1752) E/AndroidRuntime(12224): at com.android.server.LocationManagerService.addGnssDataListener(LocationManagerService.java:3053) E/AndroidRuntime(12224): at com.android.server.LocationManagerService.registerGnssStatusCallback(LocationManagerService.java:2991) E/AndroidRuntime(12224): at android.location.ILocationManager$Stub.onTransact(ILocationManager.java:583)

我已经在 android 清单文件中正确添加了权限:

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

我在启动位置侦听器之前也检查了权限,但问题是允许存在。

我的定位服务:

class LocationService with ChangeNotifier {
  static LocationService _instance;

  factory LocationService() => _instance ??= LocationService._internal();
  LocationService._internal();

  bool hasPermission = false;
  bool hasService = false;
  String lastError;
  Location _locationService = Location();

  LatLng _currentLocation = LatLng(0, 0);

  set currentLocation(LatLng value) {
    _currentLocation = value;
    notifyListeners();
  }

  LatLng get currentLocation => _currentLocation;

  @override
  void dispose() {
    super.dispose();
  }

  void init() async {
    await _locationService.changeSettings(
      accuracy: LocationAccuracy.high,
      interval: 1000,
    );
    try {
      hasService = await _locationService.serviceEnabled();
      if (hasService) {
        print('Location service is enabled');

        var permission = await _locationService.requestPermission();
        hasPermission = permission == PermissionStatus.granted;

        if (hasPermission) {
          print('Location service has permission');
          final location = await _locationService.getLocation();
          currentLocation = LatLng(location.latitude, location.longitude);
          _locationService.onLocationChanged.listen((data) =>
              currentLocation = LatLng(data.latitude, data.longitude));
        } else
          throw geo.PermissionDeniedException(null);
      } else {
        hasService = await _locationService.requestService();
        if (hasService) {
          init();
          return;
        } else
          throw geo.LocationServiceDisabledException();
      }
    } catch (e) {
      lastError = e.toString();
      String message;
      if (e.runtimeType == geo.PermissionDeniedException)
        message = 'Veuillez vérifier l\'autorisation d\'activation';
      else if (e.runtimeType == geo.LocationServiceDisabledException)
        message = 'Veuillez activer votre service GPS';
      AlertUtils.showConfirmDialog(e.toString(),
          content: message, okLabel: 'Settings', okFunction: () async {
        Get.back();
        if (e.runtimeType == geo.PermissionDeniedException) {
          if (await geo.Geolocator.openAppSettings())
            AlertUtils.showConfirmDialog('Réessayez?', okLabel: 'Réessayez?',
                okFunction: () {
              Get.back();
              init();
            });
          else
            AlertUtils.showConfirmDialog(
                'Impossible d\'activer l\'autorisation automatiquement, merci de le faire manuellement.');
        } else if (e.runtimeType == geo.LocationServiceDisabledException) {
          if (await geo.Geolocator.openLocationSettings())
            AlertUtils.showConfirmDialog('Réessayez?', okLabel: 'Réessayez?',
                okFunction: () {
              Get.back();
              init();
            });
          else
            AlertUtils.showConfirmDialog(
                'Impossible d\'activer le GPS automatiquement, merci de le faire manuellement.');
        }
      });
    }
  }
}

感谢您的帮助

一些权限被认为是“危险的”(FINE_LOCATION 就是其中之一)。

为了保护用户,他们必须在运行时获得授权,以便用户知道这是否与他的操作有关。

为此:

ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 1);

它将显示一个对话框,用户可以在其中选择他是否授权您的应用使用位置信息。

然后使用这个函数获取用户答案:

public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
    switch (requestCode) {
        case 1: {
            // If request is cancelled, the result arrays are empty.
            if (grantResults.length > 0
            && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

            } else {
                // permission denied, boo! Disable the
                // functionality that depends on this permission.
            }
        return;
        }
            // other 'case' lines to check for other
            // permissions this app might request
    }
}

如果用户接受一次,那么您的应用程序将记住它,您将不再需要发送此 DialogBox。请注意,如果用户决定,他可以稍后将其禁用。然后在请求位置之前,您必须测试权限是否仍然被授予:

public boolean checkLocationPermission()
{
    String permission = "android.permission.ACCESS_FINE_LOCATION";
    int res = this.checkCallingOrSelfPermission(permission);
    return (res == PackageManager.PERMISSION_GRANTED);
}

请关注:https://developer.android.com/training/permissions/requesting.html

我发现问题是在检查权限之前设置我的本地化插件的配置,所以我只是将它移动到 if 条件中,例如:

 if (hasPermission) {
          print('Location service has permission');
          await _locationService.changeSettings(
            accuracy: LocationAccuracy.high,
            interval: 1000,
          );
          final location = await _locationService.getLocation();
          currentLocation = LatLng(location.latitude, location.longitude);
          _locationService.onLocationChanged.listen((data) =>
              currentLocation = LatLng(data.latitude, data.longitude));
        } else
          throw geo.PermissionDeniedException(null);