You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter geolocator包无法返回经纬度、返回null值问题求助

Flutter geolocator 获取经纬度返回null问题排查

问题表现

  • 集成geolocator包获取设备当前位置时,经度、纬度字段均返回null值
  • 已完成Android、iOS端清单/配置文件中的位置访问权限声明

现有实现代码

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);
    }
  }
}

控制台运行日志

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

排查步骤与解决方案

  • 补全定位前置校验逻辑
    清单文件配置权限不代表运行时权限已授予、位置服务已开启,直接调用定位接口大概率拿不到结果。在调用getCurrentPosition前必须加两层校验:
    1. 检查系统位置开关是否开启:执行bool serviceEnabled = await Geolocator.isLocationServiceEnabled();,返回false时直接引导用户打开系统位置服务,终止后续定位流程
    2. 检查运行时权限状态:执行LocationPermission permission = await Geolocator.checkPermission();,权限为denied时调用requestPermission()主动申请权限,权限为deniedForever时引导用户跳转系统设置页手动授权
  • 修复页面不刷新问题
    定位结果返回后给lat、long赋值时没有调用setState(),Flutter不会重新触发build渲染,就算拿到有效值页面也会一直显示null。修改getLocation方法的赋值逻辑:
    void getLocation() async {
      Location location = Location();
      await location.getCurrentLocation();
      setState(() {
        lat = location.latitude;
        long = location.longitude;
      });
    }
    
  • 调整定位参数配置
    当前设置的desiredAccuracy: LocationAccuracy.lowest在多数安卓机型上需要依赖网络定位,信号差时会直接返回null,同时缺少超时配置会导致定位请求无限挂起。修改定位调用参数:
    Position position = await Geolocator.getCurrentPosition(
      desiredAccuracy: LocationAccuracy.high,
      timeLimit: const Duration(seconds: 10),
    );
    
  • 排查测试环境问题
    1. 优先用真机测试,安卓模拟器默认未开启位置模拟时无法返回有效定位结果
    2. 确认测试设备系统设置中位置信息总开关为开启状态,且已给测试应用授予位置访问权限
    3. 首次测试尽量在室外GPS信号良好的区域进行,室内遮挡环境下低精度定位很容易返回null
  • 补全异常日志
    当前catch块仅打印异常对象,很多定位失败的错误堆栈被吞无法定位根因,修改异常打印逻辑输出完整堆栈:
    catch (e, stack) {
      print('定位失败: $e');
      print(stack);
    }
    

内容的提问来源于stack exchange,提问作者Kanu Thakor

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 02:39:16