Kanu Thakor
Kanu Thakor

Reputation: 63

flutter geolocator package not returning the longitude and latitude values

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

Answers (5)

Nabeel Ahmed
Nabeel Ahmed

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

mathems32
mathems32

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

  • android's emulator

:

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

mathems32
mathems32

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

Maurits van Beusekom
Maurits van Beusekom

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

Mahi
Mahi

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

Related Questions