Flutter Geolocator 无法在 Android 上运行,但可以在 iOS 上完美运行
Posted
技术标签:
【中文标题】Flutter Geolocator 无法在 Android 上运行,但可以在 iOS 上完美运行【英文标题】:Flutter Geolocator not working on Android, but working perfectly on iOS 【发布时间】:2021-12-07 15:45:33 【问题描述】:我使用 Flutter 为 ios 和 android 平台构建了一个应用程序。它使用 Geolocator 包,版本 7.7.0。奇怪的是,虽然它可以在 iOS 模拟器和物理设备上运行,但它在 Android 模拟器或物理设备上根本不起作用。这是我根据 pub.dev 的指导创建的基于地理定位器的异步函数,用于检查权限并获取用户的当前位置:
_determineCurrentPositionStarting() async
bool serviceEnabled;
LocationPermission permission;
// 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.
return Future.error('Location services are disabled.');
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, so 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.best,
forceAndroidLocationManager: true,
).then((Position position)
setState(()
gcStartingLatitudeGEODEG.text = position.latitude.toStringAsFixed(6);
gcStartingLongitudeGEODEG.text = position.longitude.toStringAsFixed(6);
);
).catchError((e)
print(e);
);
另外,调用上述函数的onPressed命令,在一个按钮中,如下所示:
onPressed: () async
_determineCurrentPositionStarting();
,
在 iOS 上,它可以正常工作,获取用户的位置。它只是不适用于Android。问题是,根本没有为它生成错误日志,所以我没有明显的工作目标。终端中的一切似乎都运行良好。我已经做了一些试验和错误,看看我是否可以弄清楚这个过程在哪个阶段卡住了。这是我发现的:
-
该功能能够检查位置服务是否已启用,如果未启用,则会弹出警告。
该函数能够检查权限并在没有权限时通过弹出窗口请求权限(总是,仅在使用应用程序时,从不等)。如果选择从不,则会按预期生成警告。
如果权限被永久拒绝,该函数会发出警告。
当我们到达 return await Geolocator.getCurrentPosition...
这让我觉得 android 平台和 await Geolocator.getCurrentPosition() 函数存在问题。
由于在我的 iOS 设备和模拟器上一切正常,但在 Android 上却不行,我认为这与 Android 特定设置有关。
据我所知,在我的 androidmanifest.xml 文件中,记录了正确的权限:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
我正在使用 gradle 版本 7.0.0,在我的 build.gradle 文件(android > app > build.gradle)中,我的 SDK 版本是:
compileSdkVersion: 31 minSdkVersion: 23 targetSdkVersion:31如果有帮助,Flutter Doctor 没有错误:
[✓] Flutter (Channel stable, 2.5.3, on macOS 11.6 20G165 darwin-x64, locale en-GB)
[✓] Android toolchain - develop for Android devices (Android SDK version 31.0.0)
[✓] Xcode - develop for iOS and macOS
[✓] Chrome - develop for the web
[✓] Android Studio (version 2020.3)
[✓] Connected device (2 available)
我有什么遗漏吗?有什么理由可以说明为什么它不能在 Android 上运行?任何帮助将不胜感激!
编辑
我刚刚在运行 Android 11.0 而不是 12.0 的 Android Emulator 上进行了尝试,它运行良好。这对我来说表明它可能与包版本 7.0.0 中的重大更改如何交互可能与 Android 12.0 模拟器交互有关。我会查看它们,如果我能解决,我会将其发布为我的查询的答案。
【问题讨论】:
【参考方案1】:首先我修改了获取坐标的函数,基于7.0.0版插件作者描述的breaking changes,主要是权限部分。
_determineCurrentPositionStarting() async
bool serviceEnabled;
LocationPermission permission;
// 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.
return;
permission = await Geolocator.checkPermission();
if (permission == LocationPermission.denied)
permission = await Geolocator.requestPermission();
if (permission == LocationPermission.deniedForever)
// Permissions are denied forever, handle appropriately.
return;
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;
// When we reach here, permissions are granted and we can
// continue accessing the position of the device.
return await Geolocator.getCurrentPosition(
desiredAccuracy: LocationAccuracy.bestForNavigation,
forceAndroidLocationManager: true,
timeLimit: null,
).then((Position position)
setState(()
gcStartingLatitudeGEODEG.text = position.latitude.toStringAsFixed(6);
gcStartingLongitudeGEODEG.text = position.longitude.toStringAsFixed(6);
);
).catchError((e)
print(e);
);
然后,我决定做一个计时测试,似乎基本上,即使对于我最初认为它不起作用的 Android 设备,它实际上也起作用了,只是延迟了很长时间。
例如,在我的 Android 物理设备三星 Galaxy A21s 上,它需要 48 秒到几分钟不等,但它确实返回了坐标。
因此,我只能假设它确实适用于所有平台,并且完全取决于设备的类型、其中的 GPS 模块的质量以及用户所在位置的 GPS 连接,至于速度结果。
这就是它没有导致错误日志的原因。它正在工作,只是需要一段时间。
【讨论】:
以上是关于Flutter Geolocator 无法在 Android 上运行,但可以在 iOS 上完美运行的主要内容,如果未能解决你的问题,请参考以下文章
Flutter:Geolocator返回方法'compareTo'在null上被调用
无法从 Flutter 中的 Open Weather API 获取数据
Flutter Geolocator 显示方法 toDouble() 在 null 上被调用
Flutter Geolocator 和 Google Maps:显示静态位置