flutter-geolocator
flutter-geolocator copied to clipboard
No position, when forceAndroidLocationManager: true and Google Play Services installed
🐛 Bug Report
It's not possible to retrieve a location, when forceAndroidLocationManager: true on a device with Google Play Services installed. Detailed findings below.
Expected behavior
Reproduction steps
I have written a minimal example main.dart. Just run it with different settings and see for yourself.
import 'package:flutter/material.dart';
import 'package:geolocator/geolocator.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Geolocator Test'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
/// Determine the current position of the device.
///
/// When the location services are not enabled or permissions
/// are denied the `Future` will return an error.
Future<Position> _determinePosition() async {
bool serviceEnabled;
LocationPermission permission;
Position pos;
// Test if location services are enabled.
permission = await Geolocator.checkPermission();
if (permission == LocationPermission.denied) {
permission = await Geolocator.requestPermission();
if (permission == LocationPermission.denied) {
// Permissions are denied, next time you could try
// requesting permissions again (this is also where
// Android's shouldShowRequestPermissionRationale
// returned true. According to Android guidelines
// your App should show an explanatory UI now.
return Future.error('Location permissions are denied');
}
}
if (permission == LocationPermission.deniedForever) {
// Permissions are denied forever, handle appropriately.
return Future.error(
'Location permissions are permanently denied, we cannot request permissions.');
}
// When we reach here, permissions are granted and we can
// continue accessing the position of the device.
print('Permission granted, asking for current location.');
pos = await Geolocator.getCurrentPosition(
forceAndroidLocationManager: true
);
print(pos);
return pos;
}
class _MyHomePageState extends State<MyHomePage> {
Position? _pos;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
// Here we take the value from the MyHomePage object that was created by
// the App.build method, and use it to set our appbar title.
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'You are here:',
),
Text(
'$_pos',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () async {
_pos = await _determinePosition();
setState(() {});
},
tooltip: 'Increment',
child: const Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
In build.gradle
android {
compileSdkVersion 33
...
}
In AndroidManifest.xml
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
My findings are as follows:
Device with Google Play Services
-
When forceAndroidLocationManager=true and LocationService=off and GoogleLocationAccuracy=off => Unhandled Exception: The location service on the device is disabled.
-
When forceAndroidLocationManager=true and LocationService=off and GoogleLocationAccuracy=on => Unhandled Exception: The location service on the device is disabled.
-
When forceAndroidLocationManager=true and LocationService=on and GoogleLocationAccuracy=off => No Position, No Error Message) [Here lays the PROBLEM!!!]
-
When forceAndroidLocationManager=true and LocationService=on and GoogleLocationAccuracy=on => No Position, No Error Message) [Here lays the PROBLEM!!!]
Device without Google Play Services
-
When forceAndroidLocationManager=true and LocationService=off => Unhandled Exception: The location service on the device is disabled.
-
When forceAndroidLocationManager=true and LocationService=on => POSITION
I hope someone can confirm my findings or even can provide a (quick) fix.
Configuration
Version: 8.2.1 / 9.0.1.
Platform:
- [ ] :iphone: iOS
- [x] :robot: Android
I've got multiple reports about the same issue. Geolocator for now is basically an interface to Google location services, and if I want to publish on e.g. F-Droid, I would need to switch libraries.
Remember that you need to be outdoor to have the GPS of the phone getting locations.
The problem is, even the GPS symbol does not appear in the status bar. It just does not communicate with the relevant services. Weirdly, even reverting to geolocator_android 3.0.4 does not help.
Have you tried to add a try catch with a timeout? It's working for me:
try{
position = await Geolocator.getCurrentPosition(
forceAndroidLocationManager: Platform.isAndroid,
timeLimit: const Duration(seconds: 5)
);
}catch(_){
position = await Geolocator.getCurrentPosition();
}
Tried your approach @ecastillopki but didn't work for me.
I'm not able to receive location updates from getPositionStream with Google Location Accuracy turned off (Google Services on), even if forceLocationManager is true.
geolocator: ^9.0.2
AndroidSettings(
forceLocationManager: true,
accuracy: LocationAccuracy.high,
intervalDuration: const Duration(seconds: 3),
timeLimit: const Duration(seconds: 5)
)
In addition, from my observations:
- forceLocationManager true, Google Services on and Google Location Accuracy off: I don't receive any updates.
- forceLocationManager false, Google Services on and Google Location Accuracy off:
E/flutter (31117): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: The location service on the device is disabled.
E/flutter (31117): #0 GeolocatorAndroid.getPositionStream.<anonymous closure> (package:geolocator_android/src/geolocator_android.dart:187:9)
Hi, has anyone solved this problem? For me is only happening when I use a Wear OS device, not on Android.
I see this same issue on all of my android devices. Looks like this issue has been opened for almost a year. I assume this plugin is no longer supported.
Dear @7h30n3,
I cannot reproduce your flow When forceAndroidLocationManager=true and LocationService=on and GoogleLocationAccuracy=off => No Position, No Error Message) [Here lays the PROBLEM!!!] with the example app.
Does it work in the example app? It seems to work fine if I test the example app op a Nexus 7, Android 13.
Did you request the proper permissions and did you setup the manifest correctly? (Check the README for detailed steps)
If you don't get positions in the example app then check if your device is setup properly. The forceLocationManager forces the old location manager that is based on either GPS or Network. If one of them is not setup properly then you might not be able to get a location. Also notice that it is important to test your gps locations in an open environment. I've personally tested this in concrete buildings and the gps might not be able to find an accurate location. Also be careful when you test locations in your Simulator. It might not be working as expected.
If the example apps works correctly and your app does not work correctly then the issue can be found in your code.
Kind regards,
Hi @TimHoogstrate,
I have retested everything with the latest version of geolocator, but unfortunately nothing has changed. I even tested the example app of geolocato, but when set:
locationSettings: AndroidSettings(forceLocationManager: true)
I still can't get any position on my Galaxy S10 with Android 12. However at the same location when I open OSMand I get a position almost instantly.
Hi @7h30n3! Thank you for raising this issue and providing us with valuable feedback. I'd be eager to get to the bottom of this issue since many people seem to be affected.
As fully diving into the code is rather time-consuming, I would like to assess the scope of this bug first. To that end I have some questions. Could you tell me if you experience this behavior:
- On different Android versions (ex. 11 and 13)
- In an emulator
- Both when providing
preciselocation access andapproximatelocation access - Both when allowing location
while using the appandonly this time
I'd like to point out that when using the example app of flutter-geolocator, starting the location stream will not ask for location permissions. Make sure these are granted, for example by getting the current location (second button).
Looking forward to hearing from you!
The issue should be resolved. You can pull in the latest changes by running dart pub upgrade. Please check if pubspec.lock contains
geolocator_android:
...
version: "4.2.3"
I think something is still off here. After updating to 4.2.3, I do indeed now get location updates when forceAndroidLocationManger = true and accuracy = best, but they are wildly inaccurate on emulators and real devices. However, if I force/hard code the LocationManagerClient.currentLocationProvider = "gps" then I get very precise location updates.
I believe something must have changed a while back that caused the LocationManagerClient to start returning very low accuracy location updates. As a result, the low accuracy location updates started getting caught in the accuracy filter that was removed in 4.2.3. In other words, removing the accuracy filtering didn't really fix the problem. Rather it merely let through very inaccurate location updates. As such, the root of this bug probably lies further upstream with the low accuracy position updates.
My guess is that getBestProvider() started returning one of the low accuracy providers even when the best accuracy was selected by the developer. I will also note that in in api 34, LocationManager.getbestProvider is now deprecated and the desired approach is to explicitly select the desired provider. Given the deprecation and the seemingly undesirable behavior of getBestProvider, is there any reason that the LocationManagerClient.currentLocationProvider shouldn't be explicitly set to 'gps' when high/best accuracy is selected?
Thank you for the elaborate explanation @rlueders!
This has helped us get an insight into what is actually going wrong. I opened a PR that aims to fix the inaccurate location readings: #1324.
Thanks for looking into it. I will test it once is is released.
@rlueders the issue should be resolved. You can pull in the latest changes by running dart pub upgrade. Please check if pubspec.lock contains
geolocator_android:
...
version: "4.2.4"
I did a couple tests on two real devices and everything looks good. Thanks for the fix.