Flutter-geolocator: 未来永远不会在 IOS13 上解决

创建于 2020-04-29  ·  63评论  ·  资料来源: Baseflow/flutter-geolocator

🐛 错误报告

当我尝试获取当前位置时,它永远不会解决。 我不是IOS专家,所以如果我忘了做某事,请给我解释一下。

Future<Position> getCurrentPosition({
    LocationAccuracy accuracy = LocationAccuracy.best,
    GeolocationPermission geolocationPermission =
        GeolocationPermission.location,
  }) =>
      _geolocator.getCurrentPosition(
        desiredAccuracy: accuracy,
        locationPermissionLevel: geolocationPermission,
      );

播客文件:

config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [
        '$(inherited)',

        ## dart: [PermissionGroup.location, PermissionGroup.locationAlways, PermissionGroup.locationWhenInUse]
         'PERMISSION_LOCATION=1',
      ]

信息列表:

    <key>NSLocationWhenInUseUsageDescription</key>
    <string>Need location when in use</string>
    <key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
    <string>Always and when in use!</string>
    <key>NSLocationUsageDescription</key>
    <string>Older devices need location.</string>
    <key>NSLocationAlwaysUsageDescription</key>
    <string>Can I haz location always?</string>

编辑:

我已经在真正的 Android 设备上进行了测试,问题也正在发生。

我的清单位置权限:

    <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" />

预期行为

返回一个位置。

复制步骤

只需调用 geolocator.GetCurrentPosition。

版本: 5.1.5。

平台:

  • [x] :iphone: iOS (用 IOS 模拟器测试)
  • [x] :robot: Android(在带有 Android 10QkQ1.190828.002 的小米 Pocophone F1 上测试)
android ios triage

最有用的评论

大家好,

我很高兴地宣布我(最终)发布了6.0.0-rc.1版本,它应该可以解决所有这些问题。

如果您能试一试并给我您的反馈,我将不胜感激。

所有63条评论

我遇到了同样的错误。 这在iOS和Android上都发生......

我在运行iOS 10.3iOS 13.4模拟器上以及在装有iOS 13.4iPad上遇到了同样的错误。

mycode.dart:

Position pos = await Geolocator()
              .getCurrentPosition(
                  locationPermissionLevel:
                      GeolocationPermission.locationWhenInUse,
                  desiredAccuracy: LocationAccuracy.high)

信息列表:

<key>NSLocationAlwaysUsageDescription</key>
<string>Can I haz location always?</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>Need location when in use</string>

版本: 5.3.1

我在 Android 8.0 上遇到了同样的问题。 我考虑直接在源代码上编写一个 10 秒计时器,如果达到则抛出。

@brenoasm您是在模拟器还是真实设备上遇到这个问题?

@dammel在模拟器上,配置模拟器以发出位置很重要。 这可以使用模拟器应用程序的以下菜单项来完成:功能 -> 位置 ->(选择“无”以外的选项)。

@mvanbeusekom如果真实设备不发出位置怎么办? 如果用户关闭了 GPS,它不应该是吗?

@mvanbeusekom我已经在 IOS 模拟器上进行了测试(我没有 iPhone 可以在真实设备上对其进行测试)。 我已经在真正的 Android 设备上对其进行了测试,并且遇到了同样的问题……我将编辑并添加我的 Android 设备信息。

我对真正的android设备有同样的问题......

@mvanbeusekom感谢您的帮助。 你的模拟器提示对我有用。
我没有改变任何东西,但它现在再次在 iPad(真实设备)上运行。

在 iOS 模拟器和 iOS 设备上测试,我没有问题,但我在 Android 模拟器上遇到了同样的问题

我将尝试详细解释我的情况。

首先,问题发生在 Android 和 iPhone 设备中(我正在使用 Testflight 与我的 QA 团队一起测试应用程序),但也发生在 Android Emulator 和 iOS Simulator 中。

'getCurrentPosition' 方法有时不会返回位置,但经过一系列尝试后它会返回。 我第一次安装应用程序时通常会遇到这个问题。 一段时间后,突然方法开始为您带来当前位置。

这个问题的问题在于它并不总是发生。 您可以安装该应用程序,有时在第一次尝试该方法时返回当前位置...

额外说明:

  1. 如果该方法开始运行良好并且我进行了热重载或热重启,则该方法继续运行良好
  2. 该方法不会抛出任何异常......但如果你放一个“等待”它会无限期地停止
  3. 我尝试使用旧版本的 Geolocator,但问题仍然存在
  4. 我在我的项目中使用谷歌地图,所以我想“可能与最新版本的地图有冲突......?”。 没有。 我用旧版本的谷歌地图编译,问题仍然存在
  5. 奇怪的是,几周前我没有遇到这个问题......

我的环境:

$ flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, v1.12.13+hotfix.9, on Linux, locale en_GB.UTF-8)

[✓] Android toolchain - develop for Android devices (Android SDK version 29.0.2)
[✓] Android Studio (version 3.6)
[✓] IntelliJ IDEA Community Edition (version 2019.3)
[✓] Connected device (2 available)

• No issues found!

我项目中的临时解决方案:

  1. 我在“getCurrentPosition”方法中添加了一个超时,如果它返回“null”,我启动一个计时器并一次又一次地尝试……过了一会儿(有时是几秒钟,有时甚至是一分钟),该方法返回当前位置
  2. 如果我需要一个初始位置,我使用方法 'getLastKnownPosition()'

我猜 #375 和 #386 与这个问题有关

同样的问题,LG G6,Android 9.0。

永远解决不了。

有一种奇怪的方法可以让它工作:
我启动谷歌地图应用程序来获得那里的位置。 为此,我需要激活位置传感器和 wifi(可能移动数据连接也可以工作,未经测试)。
所以我得到了谷歌地图的位置。
之后它也适用于我的应用程序(无论我的应用程序是之后启动还是已经运行)。
如果我终止 wifi 或关闭位置,那么即使我再次打开它们,它也不再起作用。

随时关闭谷歌地图,甚至在我的应用程序打开之前,都没有关系(但有时我必须多次打开谷歌地图。)
在我看来,谷歌地图建立了一些即使在地图关闭后仍然存在并且地理定位器需要的东西。

编辑/更正:
更复杂的是,谷歌地图的过程适用于“desiredAccuracy”的所有参数,但在切换 wifi 时有 2 个类别:

  • LocationAccuracy.best 和 LocationAccuracy.high 仍在工作,但变慢了
  • LocationAccuracy.medium、LocationAccuracy.lower 和 LocationAccuracy.lowest 不再解析,同样使用这些参数,状态栏中的位置符号也永远不会显示。

重新启动后,设备位置不再解析。 所以我需要重复使用谷歌地图获取位置,然后它再次按描述工作。

(可能不重要,不相关,在新安装应用程序后,权限对话框看起来不同,没有“不再询问”复选框,但只有第一次显示对话框,之后它总是与复选框相同的对话框)

同样的问题,Android 10、OnePlus 7 Pro。

谷歌地图的上述技巧对我不起作用,但不知何故,一段时间后,该位置开始解决,而我没有做任何具体的事情。 我只是在浏览器中阅读以前打开的页面,然后切换回我的应用程序并看到一个告诉我位置的对话框 - 该对话框设置为显示未来何时解决,所以最终它确实解决了,但花了一段时间. 之后,该位置在每次尝试时都解决得很好。
如上所述,重新启动后该位置不再解析。

在模拟器上一切正常。

@SchmadenSchmuki的消息之后,我在我的项目中进行了一些测试,这是我的结论:影响地理定位器插件的谷歌地图插件有问题。 它们之间存在不相容性。

这是我第一次启动应用程序时的流程:

  1. 它显示一个启动画面
  2. 同时,应用程序连接到 API 以提取用户数据
  3. 我使用 Geolocator 来定位用户的当前位置
  4. 应用程序退出启动画面,然后显示用户所在位置的地图

使用此流程,应用程序将失败。 Geolocator 的“getCurrentPosition()”方法失败,它永远不会返回值。 注意:方法“isLocationServiceEnabled()”和“getLastKnownPosition()”工作正常。

但是,如果我将流程更改为:

  1. 启动画面
  2. 连接 API 拉取用户数据
  3. 使用随机位置渲染地图
  4. 使用 Geolocator 定位用户的当前位置
  5. 将地图的相机移动到当前位置

有用!!!!!

所以,我的结论是,在某种程度上,谷歌地图插件占据了阻止其他插件使用地理定位服务的“东西”。 当谷歌地图渲染时,它释放了那个“东西”,然后每个人都可以毫无问题地工作。

如果其他人可以确认这一点,我们可以向 Flutter 人员打开一个问题以查看此内容

@KnucklesEQ非常感谢您的广泛报道。 我将开始调试这个问题,并花更多的时间来重现并希望能解决这个问题。 如果这里的其他人可以验证他们是否都在使用 Google Maps 插件,那将非常有帮助?

不过我认为存在多个问题(Android 9 + Android 10 之间的差异,iOS 有时需要几秒钟才能返回位置,结合使用 Geolocator 和谷歌地图),我将开始关注所有这些,看看我是否可以改善情况。 不过这将需要一些时间,所以请在我尽力而为时多多包涵,并尝试在此处留下有关我进度的更新。

我没有使用地图插件。 我注意到,当我仅在应用程序运行时授予权限时(locationWhenInUse),下次我询问时它不会显示并且永远不会解决(仅限 Android,在 IOS 上自从我打开此问题以来它从未工作过)。

我没有使用谷歌地图插件。

也不使用谷歌地图插件。
(当遇到问题时,我检查了谷歌地图应用程序是否也有获取位置的问题,然后我发现获取位置对我的应用程序有影响)

更多细节:
当满足以下条件时会出现此问题

  • 我正在使用位置管理器(Geolocator().forceAndroidLocationManager = true)
  • 我正在使用默认位置精度,即 LocationAccuracy.best
  • 我在里面

我通过代码对其进行了跟踪,发生的情况是,在前两种情况下,被选中的位置提供程序是“gps”,而设备无法接收到内部的 gps 信号。 我走到阳台上,几乎立刻一切都开始正常工作了。

我没有尝试使用位置准确性来查看它如何影响位置提供者的选择,但我确实尝试只是强制提供者“网络”(通过硬编码)。 这行得通,但检索到的位置的准确度显然不是很好 - 约 1080 米。

@minusminuszero是对的,对我来说也是如此。
所以对我来说,它正在做它应该做的事情,重启后也是如此,对于给您带来的不便,我们深表歉意。
(我没有设置位置管理器,所以在我的情况下它是 forceAndroidLocationManager = false。我使用 LocationAccuracy.best 并猜测它也适用于 LocationAccuracy.high,可能不适用于较低的准确度,因为在这些情况下,locationsymbol没有显示在状态栏中,但已经存在问题。)

我也遇到了上述情况,重现的步骤完全相同(在里面,默认位置 acc 等)

更多细节:
当满足以下条件时会出现此问题

  • 我正在使用位置管理器(Geolocator().forceAndroidLocationManager = true)
  • 我正在使用默认位置精度,即 LocationAccuracy.best
  • 我在里面

我通过代码对其进行了跟踪,发生的情况是,在前两种情况下,被选中的位置提供程序是“gps”,而设备无法接收到内部的 gps 信号。 我走到阳台上,几乎立刻一切都开始正常工作了。

我没有尝试使用位置准确性来查看它如何影响位置提供者的选择,但我确实尝试只是强制提供者“网络”(通过硬编码)。 这行得通,但检索到的位置的准确度显然不是很好 - 约 1080 米。

你是如何强制“网络”位置的? 就解决问题而言,这对我来说就足够了,因为它至少发生在室内

你是如何强制“网络”位置的? 就解决问题而言,这对我来说就足够了,因为它至少发生在室内

我通过直接在地理定位器插件代码中硬编码位置提供者的值来做到这一点。 我想选择低精度会产生相同的效果,但我没有尝试。

可能该方法应该有一个超时参数,不是吗?

Flutter/Geolocator 团队是否正在解决这个问题?

是的,我们是的

谢谢@mvanbeusekom!
你知道问题的根源是什么吗?
您是否找到绕过它的方法(或某种临时解决方案)?
(降级到 4.0.3 并没有为我们解决)

在模拟器上,配置模拟器以发出位置非常重要。 这可以使用模拟器应用程序的以下菜单项来完成:功能 -> 位置 ->(选择“无”以外的选项)。

这为我解决了这个问题。 但这是一个非常令人困惑的错误,因为它只是失败而没有任何异常或任何东西。

在模拟器上,配置模拟器以发出位置非常重要。 这可以使用模拟器应用程序的以下菜单项来完成:功能 -> 位置 ->(选择“无”以外的选项)。

这为我解决了这个问题。 但这是一个非常令人困惑的错误,因为它只是失败而没有任何异常或任何东西。

是的,对我来说也是。
请在位置请求中添加超时,并在没有设置位置的模拟器中抛出异常。

谢谢 :)

我在 iOS 上遇到了同样的问题,我也在使用谷歌地图插件。
我有一个使用 getLocationStream 的应用程序,但在我进入有谷歌地图的标签之前,我没有获得权限对话框。
我有另一个应用程序,我不再使用谷歌地图但忘记删除插件,我遇到了同样的问题。 我删除了谷歌地图插件,现在它可以正常工作了。

对此有何更新?

大家好,我正在努力解决这个问题。 基本上,我们决定从头开始构建地理定位器并一次解决多个问题。

将包括的要点是:

  • 修复权限问题;
  • 确保在合理时间内取回getCurrentLocation
  • getCurrentLocationgetPositionStream方法添加超时,这样如果获取位置的时间比预期的要长,请求将超时,您可以重新启动请求;
  • 改进潜在的错误信息;
  • 移至联合插件结构,以便我们为 Web 支持做好准备;
  • 更新到 Android v2 插件;

第一步是移除地理编码功能并将它们托管在他们自己的插件中(现在可以在pub.dev上使用。

第二步是创建所有必要的 Dart 代码并对其进行单元测试,这些代码现在已经准备就绪,可以在federated_plugin分支上查看。

接下来的步骤是添加 iOS 和 Android 实现并修复示例应用程序。 这就是我现在正在做的事情,希望我能够在接下来的两周内完成所有事情(请记住,我也需要在业余时间做这件事;))。

无论如何,我要感谢大家的耐心和反馈,请再坚持一会儿。

@mvanbeusekom
那是好消息。 很高兴您花时间为我们提供此插件。

非常感谢你!

我期待以下更新。

谢谢和最好的问候

好的! 让我们知道它何时发布,以便我们进行测试。

对于临时解决方法,您可以使用 GeolocationStatus checkGeolocationPermissionStatus()方法检查设备的状态。 如果位置关闭,则此方法返回“已禁用”。 然后你不需要调用getCurrentPosition()方法。

例子:

  Future<Position> getCurrentPosition() async {
    Position position;
    GeolocationStatus status = await _geolocator.checkGeolocationPermissionStatus(); 

    if (status != GeolocationStatus.disabled) {
      position = await _geolocator.getLastKnownPosition();

      if (position == null && status == GeolocationStatus.granted) {
        position = await _geolocator.getCurrentPosition(
          desiredAccuracy: LocationAccuracy.high,
          locationPermissionLevel: GeolocationPermission.locationWhenInUse,
        );
      }
    }

    return position;
  }

这里更新很少,今天早上我向federated_plugin分支推送了一个新更新,其中包括对 iOS 的全面支持,包括 Flutter 示例应用程序。

我们也已经开始开发支持检查权限状态的 Android,我们现在将实现请求权限和处理位置服务。

随意查看代码,甚至尝试将其集成到测试应用程序中并在 iOS 上运行。 请注意,这包括相当多的重大更改,这些更改都将被记录在案。 现在我只想让每个人都知道,虽然这需要一些时间,但仍有进展。 再次感谢您的耐心。

这里更新很少,今天早上我向federated_plugin分支推送了一个新更新,其中包括对 iOS 的全面支持,包括 Flutter 示例应用程序。

我们也已经开始开发支持检查权限状态的 Android,我们现在将实现请求权限和处理位置服务。

随意查看代码,甚至尝试将其集成到测试应用程序中并在 iOS 上运行。 请注意,这包括相当多的重大更改,这些更改都将被记录在案。 现在我只想让每个人都知道,虽然这需要一些时间,但仍有进展。 再次感谢您的耐心。

感谢您为此努力。 您是否会通过此更改更新 pub.dev 上的 geolocator 包?

这也是您上面提到的示例的文件:position_updates_example_widget.dart?

感谢您为此努力。 您是否会通过此更改更新 pub.dev 上的 geolocator 包?

这也是您上面提到的示例的文件:position_updates_example_widget.dart?

不,我目前还不会发布到 pub.dev。 这是对 geolocator 插件的全面改造,还不支持 Android。 一旦 Android 和文档完成,我将在 pub.dev 上发布它。

是的,这个小部件是示例应用程序的一部分,它演示了如何监听位置更新。

你好,

感谢这个包裹。

本周有机会完成上述所有 Android 任务吗?

这事有进一步更新吗?

仅在第一次请求时等待位置滞后。

关于重做版本何时发布的任何更新? @mvanbeusekom

@dalmia007 ,我还没有约会,但正在取得进展。 我在feature/federated_android分支上添加了对 Android 的基本支持。 它包含请求权限、获取最后一个已知位置、获取当前位置和位置更新,所有这些都使用融合的位置提供程序客户端(Google Play 服务的一部分)。

我仍在从事以下工作:

安卓专用:

  • 在 Google Play 服务不可用时实现上述功能;
  • 未启用定位服务时自动解决问题;

一般的:

  • 更新文档

随时在这里查看

@mvanbeusekom 非常感谢您的更新! 👍

大家好,

我很高兴地宣布我(最终)发布了6.0.0-rc.1版本,它应该可以解决所有这些问题。

如果您能试一试并给我您的反馈,我将不胜感激。

我很抱歉告诉你,但它现在崩溃了两次,足以恢复到 4.0.3。

E/AndroidRuntime(19881): java.lang.RuntimeException: Failure delivering result ResultInfo{who=<strong i="6">@android</strong>:requestPermissions:, request=24, result=-1, data=Intent { act=android.content.pm.action.REQUEST_PERMISSIONS (has extras) }} to activity {com.packagename.consumer.app/com.packagename.consumer.app.MainActivity}: java.lang.NullPointerException: Attempt to invoke interface method 'void com.baseflow.geolocator.permission.PermissionResultCallback.onResult(com.baseflow.geolocator.permission.LocationPermission)' on a null object reference

当我按下对话框上的允许授予以及按下拒绝时发生。 如果我错过了什么,请告诉我。

@Dohmanlechx只是确保,您是在 6.0.0-rc.x 还是在 5.3.2 版本上得到这个?

我确实在6.0.0-rc.1上得到了这个(IDE要求我“更新”到5.3.2+2 ,仅供参考)

@Dohmanlechx感谢您的反馈,我确实发现了一个问题。 显然,在您的情况下,地理定位器正在从另一个插件获得反馈(我猜您正在使用 permission_handler 来处理权限,因为 requestCode == 24 与 permission_handler 相同)它试图处理显然失败了。 在这些情况下,地理定位器应该简单地忽略这些消息,因为它们不属于地理定位器。 我今天会解决这个问题并发布一个新的候选版本。

感谢您的反馈意见!

哦,确实,我们正在使用permission_handler 。 好发现!

所有学分都归您@Dohmanlechx ;)。 感谢您的反馈,我能够发现这个错误,并且很快就能发布一个新版本。

@Dohmanlechx我刚刚发布了 6.0.0-rc.3 版本,它应该可以修复您遇到的错误。

非常酷,在 Android 模拟器上仔细测试,授予和拒绝,操纵位置,完美运行。 在我真正的 Android 设备上也能正常工作。

但是根本没有显示 iOS 模拟器的系统请求,你猜这是故意的吗? 但是,它至少不会崩溃,并且应用程序可以在没有任何可用位置的情况下按预期工作。 不幸的是,由于 Xcode 连接问题,我仍然无法在我的 iPhone 上进行测试,我不想将构建部署到 TestFlight 只是为了现在进行测试。 我在 iPhone 上测试后会尽快通知您。

但到目前为止,一切都很好!

非常感谢您对@Dohmanlechx的广泛测试,非常感谢!

该插件确实没有在 iOS 上显示服务请求,因为没有(公共)API 可以这样做。 我们在这里唯一的选择是手动向用户显示一条消息,说明如何手动更新设置。 我们确实可以选择将用户重定向到设置应用程序(通过调用openAppSettings()openLocationSettings()方法)。 我在README.md文件中对此进行了更详细的记录。

我很遗憾地通知这一点,但它在我的 iPhone XS Max、OS 13.6.1 上就像一场灾难。

第一次获取位置就像旧版本一样,返回正确的位置,但仍然需要 7-8 秒。

但是从第二次开始,它就一直在瞬间抛出。 由于以下原因,我不得不从Exception err更改为dynamic err
_未处理的异常:类型“_TypeError”不是“异常”类型的子类型_。

我在失败时得到那些(在第一次获取之后):

2020-08-26 14:01:45.670206+0200 Runner[4565:206487] 颤振:无法获取位置:错误状态:无元素
2020-08-26 14:01:45.670416+0200 Runner[4565:206487] 颤振:无法获取位置:“NoLocationFoundException”实例

NoLocationFoundException是我的自定义类)

_Bad state: No element_并没有说明太多不幸的是......下面是我的代码:

static Future<void> _getUserLocation({bool isSneaky = false}) async {

  void _throw(dynamic err) {
    print("Could not fetch location: $err");
    if (!isSneaky) Fluttertoast.showToast(msg: getTranslation("location_fetch_error"));
    throw NoLocationFoundException();
  }

  await GeolocatorPlatform.instance
      .getCurrentPosition(
        desiredAccuracy: LocationAccuracy.high,
        timeLimit: const Duration(seconds: _TIMEOUT_DELAY),
      )
      .then((position) => _userLatestPosition = position)
      .catchError(
    (err) {
      // Debug only, remove later
      Fluttertoast.showToast(msg: "error: $err");

      if (err is TimeoutException) {
        GeolocatorPlatform.instance.getLastKnownPosition().then((position) {
          if (position == null) _throw(err);
          return position;
        }, onError: (err) {
          _throw(err);
        });
      } else if (err is PermissionDeniedException) {
        XxlPermissionsHandler.request(Permission.location);
      } else {
        _throw(err);
      }
    },
  ).catchError((err) => _throw(err));
}

我真诚地希望你能在你的 iPhone 上重现这个。

@Dohmanlechx ,感谢您的广泛反馈,我想我在这里找到了问题。 现在我需要找到一个修复它的好方法;)

简而言之, getCurrentPosition方法调用getPositionStream并获取第一个元素,然后关闭流。 问题是getPositionStream有这样的代码:

    if (_positionStream != null) {
      return _positionStream;
    }

您可以猜到在第二次调用getCurrentPosition时会导致Bad state: No element异常,因为它将在已经关闭的流上调用first 。 我将致力于此并很快发布一个新的候选人。

@Dohmanlechx ,您在我刚刚发布的6.0.0-rc.4中得到“错误状态:无元素”的问题应该已修复。 我无法重现该问题,但我能够确保getCurrentPosition在您第二次(以及任何后续)时间调用它时将使用新流。

我真的很感激你可以再试一次,让我知道它是否有效。

我注意到的是你直接使用GeolocatorPlatform.instance.<some_method> ,通过这样做你是通过传递位于geolocator包中的任何逻辑并直接进入geolocator_platform_instance中的默认实现geolocator包中没有具体的实现,但最好不要绕过它。

如果您导入 geolocator 包,您应该能够直接调用全局方法,例如:

import 'package:geolocator/geolocator.dart';

final position = await getCurrentPosition();

如果您遇到冲突或只是想为全局方法添加前缀,您可以为导入添加别名,如下所示:

import 'package:geolocator/geolocator.dart' as geolocator;

final position = await geolocator.getCurrentPosition();

谢谢,我也根据您的建议更改了代码。

崩溃现在已经消失了,但不幸的是,它仍然太不稳定了。 10 次中有 3 次非常快(真希望 10 次中有 10 次),但 10 次中有 7 次超过时间限制(10 秒)并且函数抛出。 您是否在 iPhone 上进行了测试,向getCurrentPosition()发送垃圾邮件? 我在 iPhone XS Max、OS 13.6.1 上进行了测试。

_4.0.3_ 慢但稳定
_6.0.0-rc.4_ 速度快但不稳定

不过不用担心,这完全没问题,对我们来说绝对没有灾难,特别是因为我为 4.0.3 版本编写了自己的时间限制。

@Dohmanlechx很高兴听到崩溃已解决,至少是这样;)

我真的很感兴趣为什么您仍然收到缓慢的更新,因为我无法重现它。 我创建了一个非常简单的演示应用程序来试用它:

主要飞镖:

import 'package:flutter/material.dart';
import 'package:geolocator/geolocator.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  <strong i="10">@override</strong>
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  List<Position> _positions = <Position>[];

  <strong i="11">@override</strong>
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      home: Scaffold(
        body: ListView.builder(
          itemCount: _positions.length,
          itemBuilder: (BuildContext context, int index) {
            return ListTile(title: Text(_positions[index].toString()),);
          },),
        floatingActionButton: FloatingActionButton(
          child: Icon(Icons.add),
          onPressed: () => getCurrentPosition().then((position) {
            setState(() {
              _positions.add(position);
            });
          }),
        ),
      ),
    );
  }
}

信息列表:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>CFBundleDevelopmentRegion</key>
    <string>$(DEVELOPMENT_LANGUAGE)</string>
    <key>CFBundleExecutable</key>
    <string>$(EXECUTABLE_NAME)</string>
    <key>CFBundleIdentifier</key>
    <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
    <key>CFBundleInfoDictionaryVersion</key>
    <string>6.0</string>
    <key>CFBundleName</key>
    <string>geolocator_issue</string>
    <key>CFBundlePackageType</key>
    <string>APPL</string>
    <key>CFBundleShortVersionString</key>
    <string>$(FLUTTER_BUILD_NAME)</string>
    <key>CFBundleSignature</key>
    <string>????</string>
    <key>CFBundleVersion</key>
    <string>$(FLUTTER_BUILD_NUMBER)</string>
    <key>LSRequiresIPhoneOS</key>
    <true/>
    <key>UILaunchStoryboardName</key>
    <string>LaunchScreen</string>
    <key>UIMainStoryboardFile</key>
    <string>Main</string>
    <key>UISupportedInterfaceOrientations</key>
    <array>
        <string>UIInterfaceOrientationPortrait</string>
        <string>UIInterfaceOrientationLandscapeLeft</string>
        <string>UIInterfaceOrientationLandscapeRight</string>
    </array>
    <key>UISupportedInterfaceOrientations~ipad</key>
    <array>
        <string>UIInterfaceOrientationPortrait</string>
        <string>UIInterfaceOrientationPortraitUpsideDown</string>
        <string>UIInterfaceOrientationLandscapeLeft</string>
        <string>UIInterfaceOrientationLandscapeRight</string>
    </array>
    <key>UIViewControllerBasedStatusBarAppearance</key>
    <false/>
    <key>NSLocationWhenInUseUsageDescription</key>
    <string>The example App requires access to the device's location.</string>
</dict>
</plist>

所以每次我点击浮动操作按钮时都会调用getCurrentPosition并将结果添加到ListView 。 我已经在我的个人 iPhone 7、我妻子的 iPhone 6 和模拟器(都运行最新的 iOS 版本)上测试了这个应用程序,但我可以向按钮发送垃圾邮件,并且几乎立即返回位置。 我真的很困惑为什么你有不同的经历。 也许你可以测试这个示例代码,看看你是否还有同样的问题?

真佩服你的坚持。 我创建了一个新项目并使用了您的代码,几乎通过发送垃圾邮件按钮破坏了 iPhone 屏幕,该位置一直立即返回。 惊人的! 明天我将尝试在我们的代码中找到时间进行故障排除,首先在 Widget 中直接运行getCurrentPosition() ,然后将其越来越远,直到它的预期位置以找到罪魁祸首。 我怀疑这是因为权限插件,但我们会看到。

感谢您的反馈和客气话,非常感谢。 我在重建地理定位器方面付出了很多努力,这个问题是真正让我决定开始它的问题,所以我真的希望这次能做得很好;)

请让我知道它是怎么回事,如果我能提供帮助。

getCurrentPosition().then((position) {
   print(position);
}).catchError((err) {
   print(err);
});

直接在 Widget 中尝试过,每次单击时,控制台都会记录一个位置! 所以这绝对是我们的代码。 所以它现在就在我们身上,谢谢你所做的一切!

虽然,这_sometimes_发生在获取位置时:

I/flutter (  393): ══╡ EXCEPTION CAUGHT BY SERVICES LIBRARY ╞══════════════════════════════════════════════════════════
I/flutter (  393): The following PlatformException was thrown while de-activating platform stream on channel
I/flutter (  393): flutter.baseflow.com/geolocator_updates:
I/flutter (  393): PlatformException(error, No active stream to cancel, null)
I/flutter (  393): 
I/flutter (  393): When the exception was thrown, this was the stack:
I/flutter (  393): #0      StandardMethodCodec.decodeEnvelope (package:flutter/src/services/message_codecs.dart:572:7)
I/flutter (  393): #1      MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart:161:18)
I/flutter (  393): <asynchronous suspension>
I/flutter (  393): #2      MethodChannel.invokeMethod (package:flutter/src/services/platform_channel.dart:334:12)
I/flutter (  393): #3      EventChannel.receiveBroadcastStream.<anonymous closure> (package:flutter/src/services/platform_channel.dart:554:29)
I/flutter (  393): #4      EventChannel.receiveBroadcastStream.<anonymous closure> (package:flutter/src/services/platform_channel.dart:551:18)
I/flutter (  393): #18     MethodChannelGeolocator.getPositionStream.<anonymous closure> (package:geolocator_platform_interface/src/implementations/method_channel_geolocator.dart:135:13)
I/flutter (  393): (elided 24 frames from class _RawReceivePortImpl, class _Timer, dart:async, and dart:async-patch)
I/flutter (  393): ════════════════════════════════════════════════════════════════════════════════════════════════════

@mvanbeusekom我无法使用最新的 6.0.0+1 版本获得该职位。 在 iOS 模拟器、Android 模拟器 API 29、物理 OnePlus 6 上尝试过。每次都会抛出超时。

image

image

我不知道我还可以在此处添加什么来支持您查找问题, getCurrentPosition返回超时或如果未指定timeLimit参数则挂起。 我尝试了不同的定位精度。 有人有这个问题吗?

版本 5.3.2+2 在 iOS 模拟器(指定自定义位置)、Android 真机和 Android 模拟器上运行良好

@mvanbeusekom ,我已经阅读了所有这些内容,并且正在升级到最新版本以解决 10 秒延迟问题。

也许我遗漏了一些东西,但是在新版本中我不能再做一些事情(地理编码)。
我曾经能够通过执行以下操作手动将位置设置为市中心(以防用户拒绝位置):

Position userLocation;
List<Placemark> listAddresses = [];
if(permission.toString() != "PermissionStatus.granted"){
        listAddresses = await placemarkFromAddress("$city, $state");
         userLocation = listAddresses[0].position;
    }else{
getCurrentPosition...
}

现在,似乎_placemarkFromAddress_已更改为 _ locationFromAddress _,因此我尝试在公式中进行以下更改:

Position userLocation;
List<Location> listAddresses = [];
if(permission.toString() != "PermissionStatus.granted"){
        listAddresses = await locationFromAddress("$city, $state");
         userLocation = listAddresses[0].position;
    }else{
getCurrentPosition...
}

但我收到以下错误:

A value type 'Location' can't be assigned to a variable of type 'Position'.

如何将位置转换为位置,或者最终,如果用户拒绝该位置,我现在如何将他的位置设置为他的市中心?

谢谢。

我更新到最新版本,为我解决了问题👍👍👍

此页面是否有帮助?
0 / 5 - 0 等级