Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

got LocationServiceDisabledException when `Geolocator.isLocationServiceEnabled() return true #585

Closed
1 of 2 tasks
Ralph-Li opened this issue Nov 6, 2020 · 25 comments · Fixed by #619
Closed
1 of 2 tasks
Labels
platform: android Issue is related to the Android platform. status: triage Indicates that this issue needs to be analyzed and decorated with the appropriate labels

Comments

@Ralph-Li
Copy link

Ralph-Li commented Nov 6, 2020

🐛 Bug Report

Expected behavior

try to get the current location after location permission is granted, and the location service is enabled too, but i got LocationServiceDisabledException when getCurrentPosition is called

Reproduction steps

try {
      final enabled = await Geolocator.isLocationServiceEnabled();

      print("enabled $enabled"); // true

      final permission = await Geolocator.checkPermission();

      print("permission $permission"); // whileInUse
 
      final position = await Geolocator.getCurrentPosition(
        desiredAccuracy: LocationAccuracy.medium,
      ); // throw exception here

    } catch (e) {
        // i got `LocationServiceDisabledException` here
    }

Configuration

all permissions related are granted, and all configurations in Android are done.

Version: 6.1.5

Platform:

  • 📱 iOS
  • 🤖 Android
@EdwynZN
Copy link

EdwynZN commented Nov 7, 2020

I have the same error but only when changing LocationAccuracy from the default to something else

StreamSubscription _streamSubscription  = Geolocator.getPositionStream(
      // desiredAccuracy: LocationAccuracy.medium, <-- LocationServiceDisabledException error if I use a different accuracy
     distanceFilter: 500
 ).listen(_listenData)..onError((e, stk) => print(e));

@mvanbeusekom
Copy link
Member

I am looking into this issue but having a hard time to reproduce it. Maybe you can answer the following questions and help me debug this issue:

  1. Are you seeing this on an emulator or also on real devices?
  2. Do you have Google Play Services installed (depending on this the geolocator will either use the FusedLocationProvider SDK or the LocationManager SDK, this might help me narrow down where to look for the problem)?

Looking forward for feedback so we can tackle this thing.

@mvanbeusekom mvanbeusekom added platform: android Issue is related to the Android platform. status: triage Indicates that this issue needs to be analyzed and decorated with the appropriate labels status: needs more info We need more information before we can continue work on this issue. labels Nov 24, 2020
@AlienKevin
Copy link

I got the same Unhandled Exception: The location service on the device is disabled. when I do

Position position = await Geolocator.getCurrentPosition(
        desiredAccuracy: LocationAccuracy.low);

even if the location service for that app is enabled.

  1. A real device at Android 10
  2. Google Play Services is installed

@MercurialG
Copy link

MercurialG commented Nov 24, 2020

I tried it and it works with medium accuracy. But it doesnt with any other settings.

  1. Emulators.
  2. Tried both.

@PollyGlot
Copy link

Got the same error and it also doesn't work with any settings. Tested on both emulator and real device with location always on.

@DonMatano
Copy link

It seems for me to be only working on best accuracy. But it doesn't for others.

  1. Emulator.
  2. Google Play Services installed

@mvanbeusekom
Copy link
Member

Thank you all for providing some more feedback. We are currently looking into it but still not able to reproduce it. This probably has something to do with specific settings being enabled/ disabled.

When we find out we will of course let you know. In the meantime we are open for additional information (i.e. does this occur on all Android API's or only Android 10).

@manhlhvm
Copy link

I have same error. https://prnt.sc/vr3glj

@ordinatorix
Copy link

ordinatorix commented Nov 29, 2020

I get the same issue only when the device is not connected to a network(WIFI or MOBILE) and i'm inside a building(i.e.: poor GPS connection)

current stream settings:
StreamSubscription<Position> positionStream = Geolocator.getPositionStream( desiredAccuracy: LocationAccuracy.best, distanceFilter: 0) .listen((Position position) {}

AndroidManifest.xml: <!--Location--> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />

Device location settings: High Accuracy (Use GPS, Wi-Fi, Bluetooth and mobile networks to determine location)
edit: Using physical device

@mvanbeusekom
Copy link
Member

Thank you @seb3n this is very helpful information. I am sure this will give me something to go on.

@pakindessama
Copy link

Thank you all for providing some more feedback. We are currently looking into it but still not able to reproduce it. This probably has something to do with specific settings being enabled/ disabled.

When we find out we will of course let you know. In the meantime we are open for additional information (i.e. does this occur on all Android API's or only Android 10).

@mvanbeusekom I have the same issue on Android 9

@cikichen
Copy link

cikichen commented Dec 1, 2020

E/flutter (31570): [ERROR:flutter/lib/ui/ui_dart_state.cc(177)] Unhandled Exception: The location service on the device is disabled.
E/flutter (31570): #0      MethodChannelGeolocator._handlePlatformException (package:geolocator_platform_interface/src/implementations/method_channel_geolocator.dart:192:9)
E/flutter (31570): #1      MethodChannelGeolocator.getCurrentPosition (package:geolocator_platform_interface/src/implementations/method_channel_geolocator.dart:121:7)
E/flutter (31570): <asynchronous suspension>
E/flutter (31570): #2      Geolocator.getCurrentPosition (package:geolocator/geolocator.dart:258:35)

isLocationServiceEnabled is true
code

      bool isLocationServiceEnabled =
          await Geolocator.isLocationServiceEnabled();
      AppLog.d(isLocationServiceEnabled);
      if (isLocationServiceEnabled) {
        Position position = await Geolocator.getCurrentPosition(
            desiredAccuracy: LocationAccuracy.high);
        return {"position": position.toString()};
      }

@pakindessama
Copy link

position = await Geolocator.getCurrentPosition( desiredAccuracy: LocationAccuracy.medium, forceAndroidLocationManager: true) .timeout(Duration(seconds: 10));

This piece of code worked for me.

@EdwynZN
Copy link

EdwynZN commented Dec 3, 2020

This is my attempt to create a minimal reproducible error

import 'package:flutter/material.dart';
import 'package:geolocator/geolocator.dart';
import 'dart:async';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        debugShowCheckedModeBanner: false,
        title: 'Flutter Demo',
        home: SafeArea(
          child: Scaffold(body: GeoLocatorWidget()),
        ));
  }
}

class GeoLocatorWidget extends StatefulWidget {
  const GeoLocatorWidget({
    Key key,
  }) : super(key: key);

  @override
  _GeoLocatorWidgetState createState() => _GeoLocatorWidgetState();
}

class _GeoLocatorWidgetState extends State<GeoLocatorWidget> {
  StreamSubscription<Position> _streamSubscription;
  String message = 'empty';

  @override
  void initState() {
    super.initState();
    _streamSubscription = Geolocator.getPositionStream(
            //desiredAccuracy: LocationAccuracy.medium,
            distanceFilter: 500)
        .listen(_onData, onError: _onError);
  }

  void _onData(Position position) {
    ScaffoldState _scaffoldKey = Scaffold.of(context, nullOk: true);
    if ((_scaffoldKey?.mounted ?? false)) _scaffoldKey.hideCurrentSnackBar();
    setState(() {
      message = 'latitude: ${position.latitude}, longitude: ${position.longitude}';
    });
  }

  void _onError(dynamic error) {
    bool geoService = error is LocationServiceDisabledException ||
        error is PermissionDeniedException;
    ScaffoldState _scaffoldKey = Scaffold.of(context, nullOk: true);
    if (!(_scaffoldKey?.mounted ?? false)) return;
    _scaffoldKey.hideCurrentSnackBar();
    _scaffoldKey.showSnackBar(SnackBar(
      content: Text('$error'),
      duration: const Duration(minutes: 2),
      action: geoService
          ? SnackBarAction(
              label: 'Change',
              onPressed: () async {
                if (error is LocationServiceDisabledException) {
                  bool locationEnabled =
                      await Geolocator.isLocationServiceEnabled();
                  if (!locationEnabled) await Geolocator.openLocationSettings();
                  else setState(() {
                    message = '''
                      locationService is enabled but the error says 
                      its of type LocationServiceDisabledException anyway :(
                    ''';
                  });
                } else await Geolocator.openAppSettings();
              },
            )
          : null,
    ));
  }

  @override
  void dispose() {
    _streamSubscription?.cancel();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Text(message),
    );
  }
}

Adding all the permissions in the AndroidManifest

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

STEPS TO REPRODUCE

  1. The streamSubscription will initialize and ask for permission and location service, we grant both and it shows correctly both latitude and longitude in the screen
  2. Turn off the screen with the app open (simulate the user is distracted and then come back after a minute)
  3. Turn on / Unlock screen and the app will now show an snackbar with the error (LocationServiceDisabledException) and an snackBarAction button "Change"
  4. If the button is tapped, it will check asynchronously if the location service is truly disable, if its disable it will try to open Geolocator.openLocationSettings();, if it's enabled even if the error is of type LocationServiceDisabledException (the issue of this thread) then just change the screen text telling you its enabled and it can't really do nothing

Considerations

  • Tested with a real device using Android 8.1.0 and Android 10, everything worked fine in Android 8.1.0 (turn off and on, come back to the app after a while and didn't show an error) but the issue persisted with Android 10
  • Couldn't make the error happen in the emulator (perhaps this is something to do with Doze or battery save mode)
  • I understand the plugin doesn't allow background location, but it shouldn't sent this error when the location is clearly enabled and just resume the stream when the app is in foreground again (or maybe send a different message to know if its really a location service problem)
  • This is also related to PositionStream does not work properly if location service is initially disabled then enabled #568 where the permission/service is disabled and then enabled, one way around to that is using WidgetsBindingObserver to re-create the stream when moving out of the app (When opening settings to change the location or permissions of the app)
@override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    switch (state) {
      case AppLifecycleState.paused:
        if (_streamSubscription != null) {
          _streamSubscription.cancel();
          _streamSubscription = null;
        }
        break;
      case AppLifecycleState.resumed:
        _streamSubscription ??= Geolocator.getPositionStream(
            //desiredAccuracy: LocationAccuracy.medium,
            distanceFilter: 500).listen(_onData, onError: _onError);
        break;
      default:
        break;
    }
  }

Which works fine if the user tap the "Change" button, gets redirected to the Location Service Settings, turn it on and goes back to the app, but it won't work if the user just enables it from the status bar (the stream simply stops returning values after that).

Other idea is to use cancelOnError: true and HandleError method to intercept some errors of the stream and prevent close it when it's not that important (something that cannot be handled) but because it returns LocationServiceDisabledException even if that's not really the problem makes it difficult to pick out when and when not to use HandleError

@AlienKevin
Copy link

I did another test on a physical device with Android 8.0.0 freshly installed

API call

Position position = await Geolocator.getCurrentPosition(
      desiredAccuracy: LocationAccuracy.$accuracy$,
    ).timeout(Duration(seconds: 10));

Results for each $accuracy$ value:

$accuracy$ Result
lowest TimeoutException
low LocationServiceDisabledException
medium LocationServiceDisabledException
high TimeoutException
best LocationServiceDisabledException
bestForNavigation TimeTimeoutException

AndroidManifest.xml

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

Device settings

Device location settings: High Accuracy (Use GPS, Wi-Fi, and mobile networks)
Wifi: Connected
VPN: None
GPS Signal Strength: Shold be strong
Location information: On
Recent location requests: Displays the app which called the geolocation API

@mvanbeusekom mvanbeusekom removed the status: needs more info We need more information before we can continue work on this issue. label Dec 4, 2020
@mvanbeusekom
Copy link
Member

mvanbeusekom commented Dec 4, 2020

I have just released version 6.1.10 of the geolocator plugin which should solve this problem.

Turned out in Android the onLocationAvailability callback method reports often that a location is not available and not only when the location services are disabled. I have fine-tuned handling this method and you should no longer experience false LocationServiceDisabledException exceptions anymore.

Thanks everyone for reporting, clarifying and helping out reproducing the issue.

@sejr1996
Copy link

I have the same error, I have reproduced it on the xiaomi Redmi Note 8, while on a huawei p20 lite it works fine.
I notice that the following method returns true when services are disabled on the xiaomi, it should return false, just as it happens on the huawei.
The plugin version is: geolocator: ^6.1.13
await Geolocator.isLocationServiceEnabled ()

@alabras
Copy link

alabras commented Jan 4, 2021

Like @sejr1996 I have detected the same problem with version 6.1.13 in Nokia 3.1 (android 9), Galaxy A10s (android 10)

The location service on the device is disabled.
       at MethodChannelGeolocator._handlePlatformException(MethodChannelGeolocator.java:192)
       at MethodChannelGeolocator.<fn>(MethodChannelGeolocator.java:171)

@aTeamSolace
Copy link

Like @sejr1996 I have detected the same problem with version 6.1.13 in Nokia 3.1 (android 9), Galaxy A10s (android 10)

The location service on the device is disabled.
       at MethodChannelGeolocator._handlePlatformException(MethodChannelGeolocator.java:192)
       at MethodChannelGeolocator.<fn>(MethodChannelGeolocator.java:171)

I'm getting same

@vinceramcesoliveros
Copy link

I belive it's fixed already. My last resort to fix the service location was to use the location package. but now with the new version of geolocator package. the location permission comes first, then the service location follow.

@iamahmedshah
Copy link

Launching lib\main.dart on vivo 1906 in debug mode... lib\main.dart:1 √ Built build\app\outputs\flutter-apk\app-debug.apk. I/flutter ( 9154): Observatory listening on ************************************ I/flutter ( 9613): Observatory listening on ************************************ E/flutter ( 9613): [ERROR:flutter/lib/ui/ui_dart_state.cc(199)] Unhandled Exception: User denied permissions to access the device's location. E/flutter ( 9613): #0 MethodChannelGeolocator._handlePlatformException package:geolocator_platform_interface/…/implementations/method_channel_geolocator.dart:199 E/flutter ( 9613): #1 MethodChannelGeolocator.getCurrentPosition package:geolocator_platform_interface/…/implementations/method_channel_geolocator.dart:118 E/flutter ( 9613): <asynchronous suspension> E/flutter ( 9613): #2 _MapState.locatePosition package:donation_yoga/screens/maps.dart:21 E/flutter ( 9613): <asynchronous suspension> E/flutter ( 9613):

Throws this, doesn't show live location neither asks for permissions, also the buttons on google maps don't work.

`import 'dart:async';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:geolocator/geolocator.dart';
//import 'package:provider/provider.dart';

class Map extends StatefulWidget {
@OverRide
State createState() => _MapState();
}

class _MapState extends State {
Completer _controllerGoogleMap = Completer();
GoogleMapController newGoogleMapController;

Position currentPosition;
var geoLocator = Geolocator();

void locatePosition() async {
Position position = await Geolocator.getCurrentPosition(
desiredAccuracy: LocationAccuracy.medium);
currentPosition = position;

LatLng latLngPos = LatLng(position.latitude, position.longitude);

CameraPosition cameraPosition =
    CameraPosition(target: latLngPos, zoom: 15.0);

newGoogleMapController
    .animateCamera(CameraUpdate.newCameraPosition(cameraPosition));

}

static final CameraPosition _kGooglePlex = CameraPosition(
target: LatLng(37.42796133580664, -122.085749655962),
zoom: 14.4746,
);

@OverRide
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: GoogleMap(
mapType: MapType.normal,
myLocationButtonEnabled: true,
initialCameraPosition: _kGooglePlex,
myLocationEnabled: true,
zoomGesturesEnabled: true,
zoomControlsEnabled: true,
onMapCreated: (GoogleMapController controller) {
_controllerGoogleMap.complete(controller);
newGoogleMapController = controller;
locatePosition();
},
),
),
);
}
}
`

@tehsunnliu
Copy link

tehsunnliu commented Jun 16, 2021

Hi, I'm facing the same problem with geolocator: ^7.1.0
Geolocator.isLocationServiceEnabled() returns true, Device location service is enabled, app is granted with the permission still I get
"The location service on the device is disabled." while calling Geolocator.getCurrentPosition()
This happens only on specific devices. The one I've tested on is XiaoMi MI 6X running MIUI 11.0.6 Android Version 9
and some of the other users reported this problem too. However, I'm not sure which device they are using.

@sunnykinger
Copy link

@tehsunnliu have you found any solution to this. Some of our clients are also facing the same issue.

@tehsunnliu
Copy link

Hi. For now the solution that I've used is, I've given an option to the user that if the package fails to get location then the user can set their location manually.

I wasn't getting this problem when I was using older version of flutter and Geolocator package. However after updating everything to the latest some of my users have started complaining about this problem.

@Alfre2021
Copy link

Hello, I am using geolacator ^10.1.0 with a real Android 13 device, and it is unstable. I still have this problem, when I start my app with the GPS enabled and all permissions enabled as well, it works fine, but when you disable the GPS in the quick access bar, the top bar, and enable it again, it no longer works the service, the coordinates stop and no longer work

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
platform: android Issue is related to the Android platform. status: triage Indicates that this issue needs to be analyzed and decorated with the appropriate labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.