Flutter的Geolocator软件包返回的纬度和经度值为空,为什么?[Android]

t3psigkw  于 2022-11-17  发布在  Flutter
关注(0)|答案(4)|浏览(440)

这是我的第一个StackOverflow问题,我正在学习飞镖和Flutter作为一个新手。
我已经了解了geolocator软件包,并且一直在使用最新版本8.2.1。我还在使用Android Studio及其Android Emulator。
挑战是获得纬度和经度值,这些值来自地理定位器获得的位置数据。
在一些测试之后,结果是启用了定位服务,授予了通知位置数据的许可,但是尽管如此,地理定位器没有检索到位置数据。
我花了一些时间在模拟器的设置中,并设法在加州州的圣何塞设置了一个位置,我希望地理定位器随后会找到并使用它,但这样做没有什么区别。
控制台的响应似乎很重要,它是“Future Not Completed”(未来未完成):

  • 已构建build/app/output/flutter-apk/app-debug.apk.正在安装build/app/output/flutter-apk/app. apk.. D/FlutterGeolocator(6027):将地理定位器连接到活动D/FlutterGeolocator(6027):正在创建服务。D/FlutterGeolocator(6027):正在绑定到位置服务。D/FlutterGeolocator(6027):地理定位器前台服务已连接D/FlutterGeolocator(6027):正在初始化Geolocator服务调试服务监听ws://127.0.0.1:64162/f6U62iu6OXc=/ws正在将文件同步到设备sdk gphone 64 x86 64... I/flutter(6027):目前,仿真器的位置服务状态= true。D/CompatibilityChangeReporter(6027):已报告兼容更改ID:编号:78294732; UID 10149;状态:启用I/扑动(6027):当前位置权限状态= LocationPermission. whileInUse. I/flutter(6027):0:00之后发生逾时例外状况:05.000000:未来未完成 *

我的代码:

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: 5));
      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();
  }
}

如果您能帮助我了解哪里出了问题,以便我能够修复问题并获得结果,那就太好了。在您的回复中,请假设我使用了compileSdkVersion 32miniSdkVersion 23targetSdkVersion 32
陪谢道:)

wsewodh2

wsewodh21#

这里的问题与指定的期望精度有关。在mathemats 32的情况下,它被设置为LocationAccuracy.low。在Android上,这被转换为PRIORITY_LOW_POWER设置,这意味着Android将只使用Hive网络来三角测量设备的位置。这将在真实的设备上工作(只要它们有Hive连接),但不幸的是在模拟器上不工作。
getLastKnownPosition没有直接关系。getLastKnowPositionMap到Android FusedLocationProviderClient API上的getLastLocation,根据文档:
返回当前可用的最新历史位置。如果没有可用的历史位置,将返回null。历史位置的存在时间可以是任意的,因此客户端应检查该位置的存在时间,以确定它是否适合其用途。
getCurrentPosition将始终尝试返回实际位置(如果无法确定实际位置,则为null),而getLastKnownPosition将(非常快)返回设备缓存的最后已知位置(如果没有缓存位置,则为null)。后者可能非常旧,根本不具有代表性,因此您应该始终检查其时间戳并确定该位置是否足够新以满足您的需要。
如果您想在模拟器上测试位置,请将所需精度设置为LocationAccuracy.high或更高。下表显示了Geolocator使用的精度之间的转换以及它们如何Map到Android优先级:
| 地理定位器|安卓系统|
| - -|- -|
| LocationAccuracy.lowest |优先级_被动|
| LocationAccuracy.low |优先级_低_功率|
| LocationAccuracy.medium |优先级_平衡_功率_精度|
| LocationAccuracy.high |优先级_高_精度|
| LocationAccuracy.best | 优先级_高_精度|
| LocationAccuracy.bestForNavigation |优先级_高_精度|

更新(另请参阅GitHub上的issue 1082):

Android模拟器不支持getCurrentPosition方法的结论是不正确的。我已经在Android模拟器(Android Pixel 5 - API 30)上运行了您附加的代码,将desiredAccuracy改为LocationAccuracy.high,它正确地报告了配置的位置。以下是输出:

W/GooglePlayServicesUtil( 2212): Google Play Store is missing.
I/flutter ( 2212): Currently, the emulator's Location Services Status = true.
I/flutter ( 2212): Current Location Permission Status = LocationPermission.whileInUse.
W/GooglePlayServicesUtil( 2212): Google Play Store is missing.
I/flutter ( 2212): Latitude: 52.56731333333333, Longitude: 5.641091666666666

下面是我如何使用它:
1.已启动Android模拟器。
1.一旦开始,我配置了一个位置使用模拟器设置(见所附的图像,并确保击中“设置位置”按钮)。
1.现在开始运行示例应用程序。
1.检查控制台以获取调试信息。

不过我注意到有时候Android模拟器并不想播放得很好,我不得不在模拟器拾取它之前设置几次位置。我只有在新的模拟器上才遇到过这种情况,一旦我有了初始位置,它就可以继续正常工作了。在Android模拟器设置中设置一个路径并重复播放也可能会有所帮助。
还要确保android/app/src/main/AndroidManifest.xml包含正确的权限(ACCESS_COARSE_LOCATIONACCESS_FINE_LOCATION),如以下示例代码段所示:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.issue_1082">

   <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
   <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
 
   <application
        android:label="issue_1082"
        android:name="${applicationName}"
        android:icon="@mipmap/ic_launcher">
        <activity
            android:name=".MainActivity"
            android:exported="true"
            android:launchMode="singleTop"
            android:theme="@style/LaunchTheme"
            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
            android:hardwareAccelerated="true"
            android:windowSoftInputMode="adjustResize">
            <!-- Specifies an Android theme to apply to this Activity as soon as
                 the Android process has started. This theme is visible to the user
                 while the Flutter UI initializes. After that, this theme continues
                 to determine the Window background behind the Flutter UI. -->
            <meta-data
              android:name="io.flutter.embedding.android.NormalTheme"
              android:resource="@style/NormalTheme"
              />
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <!-- Don't delete the meta-data below.
             This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
        <meta-data
            android:name="flutterEmbedding"
            android:value="2" />
    </application>
</manifest>

不管它值多少钱,我是地理定位器包的作者和维护者。

ar5n3qh5

ar5n3qh52#

请使用以下代码进行修复:

Future<Position> _getGeoLocationPosition() async {
    bool serviceEnabled;
    LocationPermission permission;
    // Test if location services are enabled.
    serviceEnabled = await Geolocator.isLocationServiceEnabled();
    if (!serviceEnabled) {
      await Geolocator.openLocationSettings();
      return Future.error('Location services are disabled.');
    }
    permission = await Geolocator.checkPermission();
    if (permission == LocationPermission.denied) {
      permission = await Geolocator.requestPermission();
      if (permission == LocationPermission.denied) {
        print('Location permissions are denied');
        return Future.error('Location permissions are denied');
      }
    }
    if (permission == LocationPermission.deniedForever) {
      // Permissions are denied forever, handle appropriately.
      print('Location permissions are permanently denied, we cannot request permissions.');
      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.
    return await Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.high);
  }

结果:

Position position = await _getGeoLocationPosition();
whhtz7ly

whhtz7ly3#

我已经找到了一个解决方案和合理的解释,说明在使用操作时当前位置数据不会geolocator 检索

  • android仿真器


原因是Android模拟器不是真实的的设备,缺乏真实Android设备中的功能水平; android模拟器无法接受geolocator的当前位置函数。
Android模拟器接受geolocator的lastKnownLocation函数,并且geolocator将通过其lastKnownLocation函数注意并确认模拟器位置设置中的位置设置。
我相信,这一发现可以帮助所有使用geolocator(依赖于android模拟器)的人:)
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 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();
  }
}

带有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

**结论:**有人怀疑geolocator软件包有缺陷,但没有解释。上面显示并解释了geolocator在android模拟器上运行良好,应该仍然是android开发者的最爱。

blmhpbnm

blmhpbnm4#

geolocator 8.2.1我不知道,但为什么API 28饼模拟器的工作,但示例“设置位置”按钮-对我来说不工作的模拟器API版本29 30 31 --〉环D/FlutterGeolocator(26734):将地理定位器连接到活动D/FlutterGeolocator(26808):将地理定位器附加到活动中。我将在API模拟器28饼中工作。也许这会帮助一些人。

相关问题