Reputation: 63
I am using the flutter geolocator package to get a device's current location. but, it is not returning the location and sends null values instead of longitude and latitude.
I have linked all the codes related to location access for Android and iOS.
Here is my code
loading_screen.dart
import 'package:flutter/material.dart';
import 'package:clima/services/location.dart';
class LoadingScreen extends StatefulWidget {
@override
_LoadingScreenState createState() => _LoadingScreenState();
}
class _LoadingScreenState extends State<LoadingScreen> {
@override
void initState() {
super.initState();
print('init state called');
getLocation();
}
double? lat;
double? long;
void getLocation() async {
Location location = Location();
await location.getCurrentLocation();
print(location.longitude);
print(location.latitude);
lat = location.latitude;
long = location.longitude;
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Text('$lat & $long'),
),
);
}
}
location.dart
import 'package:geolocator/geolocator.dart';
class Location {
double? longitude;
double? latitude;
Future<void> getCurrentLocation() async {
try {
Position position = await Geolocator.getCurrentPosition(
desiredAccuracy: LocationAccuracy.lowest);
longitude = position.longitude;
latitude = position.latitude;
} catch (e) {
print(e);
}
}
}
Here is the console log
Running Gradle task 'assembleDebug'...
√ Built build\app\outputs\flutter-apk\app-debug.apk.
D/FlutterGeolocator( 9601): Attaching Geolocator to activity
D/FlutterGeolocator( 9601): Creating service.
D/FlutterGeolocator( 9601): Binding to location service.
D/FlutterGeolocator( 9601): Geolocator foreground service connected
D/FlutterGeolocator( 9601): Initializing Geolocator services
Debug service listening on ws://127.0.0.1:52220/Dm4z5g8IYT4=/ws
Syncing files to device SM A528B...
I/flutter ( 9601): init state called
I/BufferQueueProducer( 9601): [SurfaceView - com.kanuthakor.clima/com.kanuthakor.clima.MainActivity@e98a93d@0#1(BLAST Consumer)1](id:258100000001,api:1,p:9601,c:9601) queueBuffer: queued for the first time.
D/ViewRootImpl@797d88a[MainActivity]( 9601): Creating frameDrawingCallback nextDrawUseBlastSync=false reportNextDraw=true hasBlurUpdates=false
D/ViewRootImpl@797d88a[MainActivity]( 9601): Creating frameCompleteCallback
I/SurfaceView@e98a93d( 9601): uSP: rtp = Rect(0, 0 - 1080, 2265) rtsw = 1080 rtsh = 2265
I/SurfaceView@e98a93d( 9601): onSSPAndSRT: pl = 0 pt = 0 sx = 1.0 sy = 1.0
I/SurfaceView@e98a93d( 9601): aOrMT: uB = true t = android.view.SurfaceControl$Transaction@10aa451 fN = 1 android.view.SurfaceView.access$500:124 android.view.SurfaceView$SurfaceViewPositionUpdateListener.positionChanged:1728 android.graphics.RenderNode$CompositePositionUpdateListener.positionChanged:319
I/SurfaceView@e98a93d( 9601): aOrMT: vR.mWNT, vR = ViewRootImpl@797d88a[MainActivity]
I/ViewRootImpl@797d88a[MainActivity]( 9601): mWNT: t = android.view.SurfaceControl$Transaction@10aa451 fN = 1 android.view.SurfaceView.applyOrMergeTransaction:1628 android.view.SurfaceView.access$500:124 android.view.SurfaceView$SurfaceViewPositionUpdateListener.positionChanged:1728
I/ViewRootImpl@797d88a[MainActivity]( 9601): mWNT: merge t to BBQ
D/ViewRootImpl@797d88a[MainActivity]( 9601): Received frameDrawingCallback frameNum=1. Creating transactionCompleteCallback=false
I/BufferQueueProducer( 9601): [ViewRootImpl@797d88a[MainActivity]#0(BLAST Consumer)0](id:258100000000,api:1,p:9601,c:9601) queueBuffer: queued for the first time.
D/OpenGLRenderer( 9601): GPIS:: SetUp Pid : 9601 Tid : 9632
D/ViewRootImpl@797d88a[MainActivity]( 9601): Received frameCompleteCallback lastAcquiredFrameNum=1 lastAttemptedDrawFrameNum=1
I/ViewRootImpl@797d88a[MainActivity]( 9601): [DP] pdf(0) 1 android.view.ViewRootImpl.lambda$addFrameCompleteCallbackIfNeeded$3$ViewRootImpl:4987 android.view.ViewRootImpl$$ExternalSyntheticLambda16.run:6 android.os.Handler.handleCallback:938
I/ViewRootImpl@797d88a[MainActivity]( 9601): [DP] rdf()
D/ViewRootImpl@797d88a[MainActivity]( 9601): reportDrawFinished (fn: -1)
I/ViewRootImpl@797d88a[MainActivity]( 9601): MSG_WINDOW_FOCUS_CHANGED 1 1
D/InputMethodManager( 9601): startInputInner - Id : 0
I/InputMethodManager( 9601): startInputInner - mService.startInputOrWindowGainedFocus
D/InputMethodManager( 9601): startInputInner - Id : 0
any help will be highly appreciated, thank you.
Upvotes: 2
Views: 6999
Reputation: 242
I had same issue with geolocator but when I added <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
permission along with ACCESS_COARSE_LOCATION
in manifest, and most importantly, I changed the accuracy to LocationAccuracy.high
. After this, everything worked perfectly.
Here is my code.
In manifest
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
In dart side.
Position position = await Geolocator.getCurrentPosition(
desiredAccuracy: LocationAccuracy.high);
Upvotes: 0
Reputation: 355
I have found a solution and a reasonable explanation for why current-position data will not be retrieved by geolocator when operating with
:
The reason is because the android emulator is not a real device and lacks the level of functionality found within real android devices; android emulator does not support geolocator's current-position function.
Android emulator does support geolocator's lastKnownLocation function though, and a location set within the emulator's location settings will be noticed and confirmed by geolocator via its lastKnownLocation function.
I trust that this finding helps everyone working with geolocator relying on the android emulator : )
Dart code example:
import 'package:flutter/material.dart';
import 'package:geolocator/geolocator.dart';
void main() {
runApp(ScreenView());
}
class ScreenView extends StatefulWidget {
double? latitude;
double? longitude;
ScreenView({this.latitude, this.longitude});
void lastKnownPosition() async {
await locationServicesStatus();
await checkLocationPermissions();
try {
Position? position = await Geolocator.getLastKnownPosition();
print(position);
} catch (e) {
print(e);
}
}
void locationHereIs() async {
await locationServicesStatus();
await checkLocationPermissions();
try {
Position position = await Geolocator.getCurrentPosition(
desiredAccuracy: LocationAccuracy.low)
.timeout(Duration(seconds: 28));
print(position);
} catch (e) {
print(e);
}
}
Future<void> checkLocationPermissions() async {
LocationPermission permission = await Geolocator.requestPermission();
print('Current Location Permission Status = $permission.');
}
void checkLocationSettings() async {
await Geolocator.openLocationSettings();
}
Future<void> locationServicesStatus() async {
bool isLocationServiceEnabled = await Geolocator.isLocationServiceEnabled();
print(
'Currently, the emulator\'s Location Services Status = $isLocationServiceEnabled.');
}
@override
State<ScreenView> createState() => _ScreenViewState();
}
class _ScreenViewState extends State<ScreenView> {
@override
void initState() {
ScreenView().lastKnownPosition();
super.initState();
}
@override
Widget build(BuildContext context) {
return Container();
}
}
Console output with lastKnownLocation:
✓ Built build/app/outputs/flutter-apk/app-debug.apk.
Installing build/app/outputs/flutter-apk/app.apk...
Debug service listening on ws://127.0.0.1:52586/aA04hHZ7dIg=/ws
Syncing files to device sdk gphone64 x86 64...
I/flutter (11353): Currently, the emulator's Location Services Status = true.
D/CompatibilityChangeReporter(11353): Compat change id reported: 78294732; UID 10149; state: ENABLED
I/flutter (11353): Current Location Permission Status = LocationPermission.whileInUse.
I/flutter (11353): Latitude: 37.333333333333336, Longitude: -121.89206891099967
Conclusion: there has been a suspicion that the geolocator package is flawed without explanation. The above shows and explains that geolocator works fine with android emulator and should remain a favourite of developers.
Upvotes: 0
Reputation: 355
I added an enquiry like yours today, I didn't see yours earlier, but yes, I have found that only null values are being given by geolocator 8.2.1 when position data is requested by Flutter. You might be using a real device, viewing your console response. I have been using the Android Emulator ... I checked, and the location services are enabled, the permission for position data to be noticed is given, and then despite these the position data given is null for long/lat ... I even entered settings to add a location to the emulator, but it made no difference ...
My Code, Dart:
import 'package:flutter/material.dart';
import 'package:geolocator/geolocator.dart';
void main() {
runApp(ScreenView());
}
class ScreenView extends StatefulWidget {
double? latitude;
double? longitude;
ScreenView({this.latitude, this.longitude});
void locationHereIs() async {
await locationServicesStatus();
await checkLocationPermissions();
try {
Position position = await Geolocator.getCurrentPosition(
desiredAccuracy: LocationAccuracy.low)
.timeout(Duration(seconds: 28));
print(position);
} catch (e) {
print(e);
}
}
Future<void> checkLocationPermissions() async {
LocationPermission permission = await Geolocator.requestPermission();
print('Current Location Permission Status = $permission.');
}
void checkLocationSettings() async {
await Geolocator.openLocationSettings();
}
Future<void> locationServicesStatus() async {
bool isLocationServiceEnabled = await Geolocator.isLocationServiceEnabled();
print(
'Currently, the emulator\'s Location Services Status = $isLocationServiceEnabled.');
}
@override
State<ScreenView> createState() => _ScreenViewState();
}
class _ScreenViewState extends State<ScreenView> {
@override
void initState() {
ScreenView().locationHereIs();
super.initState();
}
@override
Widget build(BuildContext context) {
return Container();
}
}
If anyone has an idea on what could be improved for position data to be received, please respond to my problem also ... I'm in the same boat as Kanu ... Thank you : )
Upvotes: 0
Reputation: 5989
The problem is most likely the use of LocationAccuracy.lowest
. On Android this translates to the PASSIVE_INTERVAL setting. This means that the location request will not trigger the location services to fetch a location but instead only return location triggered by other clients actively requesting a location update.
You'd most likely want to update the accuracy to LocationAccuracy.low
or higher if you want to actively trigger a location update and not rely on other applications to acquire a location for you.
Here is a complete overview of all accuracy options and their Android counterparts:
Geolocator | Android |
---|---|
LocationAccuracy.lowest | PRIORITY_PASSIVE |
LocationAccuracy.low | PRIORITY_LOW_POWER |
LocationAccuracy.medium | PRIORITY_BALANCED_POWER_ACCURACY |
LocationAccuracy.high | PRIORITY_HIGH_ACCURACY |
LocationAccuracy.best | PRIORITY_HIGH_ACCURACY |
LocationAccuracy.bestForNavigation | PRIORITY_HIGH_ACCURACY |
Upvotes: 2
Reputation: 1732
Did you given these permissions?
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
You need to check run time permission and I didn't use your Location class.
import 'package:flutter/material.dart';
import 'package:geolocator/geolocator.dart';
//import 'package:clima/services/location.dart';
class LoadingScreen extends StatefulWidget {
@override
_LoadingScreenState createState() => _LoadingScreenState();
}
class _LoadingScreenState extends State<LoadingScreen> {
@override
void initState() {
super.initState();
print('init state called');
getLocation();
}
double? lat;
double? long;
Future<Position> getLocation() async {
Location location = Location();
bool serviceEnabled;
LocationPermission permission;
print('inside getLoction1');
// Test if location services are enabled.
serviceEnabled = await Geolocator.isLocationServiceEnabled();
if (!serviceEnabled) {
// Location services are not enabled don't continue
// accessing the position and request users of the
// App to enable the location services.
print('Location services are disabled.');
}
print('inside getLoction2');
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.
print('Location permissions are denied');
}
print('inside getLoction3');
}
print('inside getLoction4');
if (permission == LocationPermission.deniedForever) {
// Permissions are denied forever, handle appropriately.
print(
'Location permissions are permanently denied, we cannot request permissions.');
}
print('inside getLoction5');
final position = await Geolocator.getCurrentPosition();
print(position.latitude);
print(location.longitude);
print(location.latitude);
print('inside getLoctio6');
lat = location.latitude;
long = location.longitude;
return position;
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: FutureBuilder<Position>(
future: getLocation(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(
child: CircularProgressIndicator(),
);
}
if (snapshot.connectionState == ConnectionState.done) {
print(snapshot.data!.latitude);
return Center(
child: Text(
'${snapshot.data!.latitude}${snapshot.data!.longitude}'),
);
} else {
return SizedBox.shrink();
}
}),
);
}
}
Upvotes: 1