Flutter-geolocator: 未来はIOS13で決して解決しません

作成日 2020年04月29日  ·  63コメント  ·  ソース: Baseflow/flutter-geolocator

🐛バグレポート

getCurrentLocationを取得しようとすると、解決されません。 私は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',
      ]

Info.plist:

    <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(Android10QkQ1.190828.002を搭載したXiomiPocophone F1でテスト済み)
android ios triage

最も参考になるコメント

みなさん、こんにちは。

私は(最終的に)リリースされたバージョン6.0.0-rc.1を発表できることをうれしく思います。これにより、これらすべての問題が解消されるはずです。

ぜひお試しいただき、フィードバックをいただければ幸いです。

全てのコメント63件

同じエラーが発生します。 これはiOSとAndroidの両方で発生しています.....

iOS10.3またはiOS13.4を実行しているシミュレーター、およびiOS13.4を搭載したiPadでも同じエラーが発生します。

mycode.dart:

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

Info.plist:

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

バージョン: 5.3.1

Android8.0でも同じ問題が発生します。 到達した場合にスローするソースコードに直接10秒のタイマーを書き込むことを検討します。

@brenoasmシミュレータまたは実際のデバイスでこの問題が発生していますか?

@dammelシミュレーターでは、位置を出力するようにシミュレーターを構成することが重要です。 これは、シミュレータアプリケーションの次のメニュー項目を使用して実行できます。[機能]-> [場所]->([なし]以外のオプションを選択)。

@mvanbeusekom実際のデバイスが場所を出力しない場合はどうなりますか? ユーザーがGPSをオフにしていた場合は、そうではありませんか?

@mvanbeusekom私はIOS用のシミュレーターでテストしました(実際のデバイスでテストするためのiPhoneがありません)。 実際のAndroidデバイスでテストしたところ、同じ問題が発生しました...Androidデバイスの情報を編集して追加します。

私は実際のAndroidデバイスで同じ問題を抱えています...

@mvanbeusekomご協力いただきありがとうございます。 シミュレーターのためのあなたのTippは私のために働いた。
何も変更していませんが、iPad(実際のデバイス)で再び動作しています。

iOSシミュレーターとiOSデバイスでテストしたところ、問題はありませんでしたが、Androidエミュレーターでも同じ問題が発生しました。

私の場合を詳しく説明しようと思います。

まず、この問題はAndroidデバイスとiPhoneデバイスの両方で発生します(私はTestflightを使用してQAチームでアプリをテストしています)が、AndroidエミュレーターとiOSシミュレーターでも発生します。

メソッド'getCurrentPosition'は位置を返さない場合がありますが、試行を続けた後は戻ります。 私は通常、アプリを初めてインストールするときにこの問題が発生します。 しばらくすると、突然メソッドが現在の位置に移動し始めます。

この問題の問題は、常に発生するとは限らないことです。 あなたはアプリをインストールすることができます、そして時々最初の試みでメソッドは現在の位置を返します...

追記:

  1. メソッドが正常に機能し始め、ホットリロードまたはホットリスタートを実行した場合、メソッドは引き続き正常に機能します
  2. このメソッドは例外をスローしません...しかし、「await」を入力すると、無期限に停止します
  3. 古いバージョンのGeolocatorを使用しようとしましたが、問題が解決しません
  4. プロジェクトでGoogleマップを使用しているので、「最近のバージョンのマップと競合している可能性があります...?」と思いました。 いいえ。 古いバージョンのGoogleマップでコンパイルしましたが、問題が解決しません
  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'が返された場合は、タイマーを開始して再試行します...しばらくすると(場合によっては数秒、場合によっては1分)、メソッドは現在の位置を返します
  2. 初期位置が必要な場合は、メソッド'getLastKnownPosition()'を使用します

#375と#386はこの問題に関連していると思います

ここでも同じ問題、LG G6、Android9.0。

解決することはありません。

私がそれを機能させる方法には奇妙な方法があります:
私はそこに位置を取得するためにグーグルマップアプリを起動します。 そのためには、位置センサーとWi-Fiをアクティブにする必要があります(おそらく、モバイルデータ接続も機能しますが、テストされていません)。
だから私はグーグルマップでの位置を取得します。
その後、それは私のアプリでも機能します(私のアプリが後で起動したか、すでに実行されているかに関係なく)。
Wi-Fiを終了するか、位置をオフにすると、再度オンにしても機能しなくなります。

アプリを開く前であっても、いつでもGoogleマップを閉じることは重要ではありません(ただし、Googleマップを複数回開かなければならない場合があります)。
グーグルマップは、マップが閉じられた後も持続し、ジオロケーターが必要とする何かを確立しているように私には思えます。

編集/修正:
それはさらに複雑で、グーグルマップを使った手順は「desiredAccuracy」のすべての引数で機能しましたが、wifiの切り​​替えには2つのカテゴリがありました。

  • LocationAccuracy.bestとLocationAccuracy.highはまだ機能していましたが、遅くなりました
  • LocationAccuracy.medium、LocationAccuracy.lower、LocationAccuracy.lowestは解決されなくなりました。また、これらの引数を使用すると、ステータスバーのlocationsシンボルが表示されなくなります。

再起動後、デバイスの場所は解決されません。 だから私はグーグルマップで場所を取得することを繰り返す必要があり、それからそれは説明されているように再び機能します。

(おそらく重要ではない、無関係なものです。アプリを新しくインストールした後は、権限ダイアログの外観が異なり、[今後は確認しない]チェックボックスがありませんが、ダイアログが最初に表示されたときのみ、その後は常にチェックボックスと同じダイアログ)

同じ問題、Android 10、OnePlus7Pro。

上記のグーグルマップのトリックは私にはうまくいきませんでしたが、しばらくして、私が特定のことを何もせずに場所が解決し始めました。 以前にブラウザで開いたページを読んでいて、アプリに戻って場所を示すダイアログが表示されました。ダイアログは、将来が解決したときに表示されるように設定されているため、最終的には解決しましたが、しばらく時間がかかりました。 。 その後、場所はすべての試行で正常に解決されていました。
上記のように、再起動後、場所は解決されなくなります。

シミュレーターでは、すべてが正常に機能します。

@SchmadenSchmukiのメッセージの後、プロジェクトでいくつかのテストを行いました。これが私の結論です。Geolocatorプラグインに影響を与えるGoogleMapsプラグインに問題があります。 それらの間には非互換性があります。

これは、初めてアプリを起動したときのアプリのフローです。

  1. スプラッシュ画面が表示されます
  2. 一方、アプリはAPIに接続してユーザーデータを取得します
  3. Geolocatorを使用してユーザーの現在の位置を特定します
  4. アプリがスプラッシュ画面を終了し、ユーザーがどこにいるかを示す地図を表示します

このフローでは、アプリは失敗します。 Geolocatorの「getCurrentPosition()」メソッドは失敗し、値を返すことはありません。 注:メソッド「isLocationServiceEnabled()」および「getLastKnownPosition()」は正常に機能します。

しかし、フローを次のように変更した場合:

  1. スプラッシュ画面
  2. APIに接続して、ユーザーデータをプルします
  3. ランダムな場所で地図をレンダリングする
  4. Geolocatorを使用して、ユーザーの現在の位置を特定します
  5. マップのカメラを現在の位置に移動します

できます!!!!!

したがって、私の結論は、ある意味で、Googleマッププラグインは、他のプラグインがジオロケーションサービスを使用するのをブロックする「何か」を占めているということです。 グーグルマップがレンダリングするとき、それはその「何か」を解放し、それから誰もが問題なく働くことができます。

他の誰かがそれを確認できれば、Flutterの人たちに問題を開いてこれを見ることができます

@KnucklesEQは、広範囲にわたる報告に感謝します。 私はこの問題のデバッグを開始し、問題の再現とできれば修正に多くの時間を費やします。 ここにいる他の人が全員がGoogleマッププラグインを使用しているかどうかを確認できれば非常に役立ちますか?

それでもなお、複数の問題があると思います(Android9とAndroid10の違い、iOSはGoogleマップと組み合わせてGeolocatorを使用して、場所を返すのに数秒かかることがあります)。私はそれらすべてに焦点を当て始め、できるかどうかを確認します状況を改善します。 これには少し時間がかかりますので、私が最善を尽くしている間、私に耐えてください、そして私の進歩についてここに更新を残そうとします。

マッププラグインを使用していません。 アプリの実行中にのみアクセス許可を付与すると(locationWhenInUse)、次に要求したときに表示されず、解決されないことに気付きました(Androidのみ、IOSではこの問題を開いてから機能しませんでした)。

Googleマッププラグインを使用していません。

Googleマッププラグインも使用していません。
(問題が発生した場合、Googleマップアプリでも場所を取得するのに問題があるかどうかを確認したところ、場所を取得するとアプリに影響があることがわかりました)

詳細:
この問題は、次の条件が当てはまる場合に発生します

  • ロケーションマネージャーを使用しています(Geolocator()。forceAndroidLocationManager = true)
  • 私はデフォルトの位置精度を使用しています。これはLocationAccuracy.bestです。
  • 私は中にいます

私はコードを通してそれを追跡しました、そして何が起こるかというと、最初の2つの条件の下で選ばれるロケーションプロバイダーは'gps'であり、デバイスは内部のgps信号を拾うことができません。 私はバルコニーに出て、ほとんどすぐに物事は正常に機能し始めました。

ロケーション精度を試して、ロケーションプロバイダーの選択にどのように影響するかを確認しませんでしたが、プロバイダーを(ハードコーディングによって)「ネットワーク」に強制することを試みました。 それは機能しますが、取得された場所の精度は明らかにあまり良くありませんでした-〜1080メートル。

@minusminuszeroは正しいです、それは私にとっても同じです。
ですから、私にとっては、再起動直後も、ご不便をおかけして申し訳ありません。
(ロケーションマネージャーを設定しないので、私の場合はforceAndroidLocationManager = falseです。LocationAccuracy.bestを使用し、LocationAccuracy.highでも機能すると思います。これらの場合、locationsymbolは、精度が低い場合は機能しない可能性があります。ステータスバーには表示されませんが、すでに問題があります。)

私も上記を経験していますが、まったく同じ手順で再現します(内部にある、デフォルトの場所のアカウントなど)

詳細:
この問題は、次の条件が当てはまる場合に発生します

  • ロケーションマネージャーを使用しています(Geolocator()。forceAndroidLocationManager = true)
  • 私はデフォルトの位置精度を使用しています。これはLocationAccuracy.bestです。
  • 私は中にいます

私はコードを通してそれを追跡しました、そして何が起こるかというと、最初の2つの条件の下で選ばれるロケーションプロバイダーは'gps'であり、デバイスは内部のgps信号を拾うことができません。 私はバルコニーに出て、ほとんどすぐに物事は正常に機能し始めました。

ロケーション精度を試して、ロケーションプロバイダーの選択にどのように影響するかを確認しませんでしたが、プロバイダーを(ハードコーディングによって)「ネットワーク」に強制することを試みました。 それは機能しますが、取得された場所の精度は明らかにあまり良くありませんでした-〜1080メートル。

どのようにして「ネットワーク」の場所を強制しましたか? 少なくとも屋内で発生するため、問題を修正するという点では、これで十分です。

どのようにして「ネットワーク」の場所を強制しましたか? 少なくとも屋内で発生するため、問題を修正するという点では、これで十分です。

これを行うには、ロケーションプロバイダーの値をgeolocatorプラグインコードに直接ハードコーディングします。 低精度を選んでも同じ効果があると思いますが、試しませんでした。

おそらく、メソッドにはタイムアウトパラメータが必要です。

Flutter / Geolocatorチームはこの問題に取り組んでいますか?

はい、私たちは

ありがとう@mvanbeusekom!
問題の原因を知っていますか?
それを回避する方法(またはある種の一時的な解決策)を見つけましたか?
(4.0.3にダウングレードしても解決しませんでした)

シミュレーターでは、位置を放出するようにシミュレーターを構成することが重要です。 これは、シミュレータアプリケーションの次のメニュー項目を使用して実行できます。[機能]-> [場所]->([なし]以外のオプションを選択)。

それで問題は解決しました。 しかし、例外などなく失敗するだけなので、非常に紛らわしいバグです。

シミュレーターでは、位置を放出するようにシミュレーターを構成することが重要です。 これは、シミュレータアプリケーションの次のメニュー項目を使用して実行できます。[機能]-> [場所]->([なし]以外のオプションを選択)。

それで問題は解決しました。 しかし、例外などなく失敗するだけなので、非常に紛らわしいバグです。

うん、私も。
ロケーションリクエストにタイムアウトを追加し、ロケーションが設定されていないシミュレータで例外をスローしてください。

ありがとう :)

iOSでも同じ問題があり、Googleマッププラグインも使用しています。
getLocationStreamを使用するアプリがありますが、Googleマップがあるタブに移動するまで許可ダイアログが表示されません。
私はもうグーグルマップを使用していなかったがプラグインを削除するのを忘れた別のアプリを持っていて、私は同じ問題を抱えていました。 グーグルマッププラグインを削除しましたが、正しく機能しています。

これに関する更新はありますか?

みなさん、こんにちは。私はこの問題に一生懸命取り組んでいます。 基本的に、ジオロケーターを最初から作成し、複数の問題を一度に修正することにしました。

含まれるポイントは次のとおりです。

  • 権限の問題を修正します。
  • getCurrentLocationが妥当な時間内に取得されることを確認してください。
  • getCurrentLocation #$メソッドとgetPositionStreamメソッドにタイムアウトを追加します。これにより、場所の取得に時間がかかる場合、予想されるリクエストがタイムアウトし、リクエストを再開できます。
  • 潜在的なエラーメッセージを改善します。
  • フェデレーションプラグイン構造に移動して、Webサポートの準備をします。
  • Androidv2プラグインに更新します。

実行する最初のステップは、ジオコーディング機能を移動し、それらを独自のプラグイン(現在、 pub.devで利用可能)でホストすることでした。

2番目のステップは、必要なすべてのDartコードを作成して単体テストすることでした。これで準備が整い、 federated_pluginブランチで表示できます。

次のステップは、iOSとAndroidの実装を追加し、サンプルアプリを修正することです。 これは私が現在取り組んでいることであり、うまくいけば、今後2週間ですべてを完了することができるでしょう(私も空き時間にこれを行う必要があることを覚えておいてください;))。

とにかく、忍耐とフィードバックをありがとうございました。もう少しお待ちください。

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

ここで少し更新しました。今朝、Flutterサンプルアプリを含むiOSでの完全なサポートを含む新しい更新をfederated_pluginブランチにプッシュしました。

また、パーミッションステータスの確認をサポートするAndroidの開発も開始しました。現在、パーミッションのリクエストと位置情報サービスの処理を実装しています。

気軽にコードをチェックするか、テストアプリに統合してiOSで実行してみてください。 これには、すべて文書化される非常に多くの重大な変更が含まれていることに注意してください。 今のところ、少し時間がかかりますが、進歩があることをみんなに知らせたかったのです。 しばらくお待ちいただきますようお願いいたします。

ここで少し更新しました。今朝、Flutterサンプルアプリを含むiOSでの完全なサポートを含む新しい更新をfederated_pluginブランチにプッシュしました。

また、パーミッションステータスの確認をサポートする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サービスの一部)を使用して含まれています。

私はまだ次のことに取り組んでいます:

Android固有:

  • GooglePlayサービスが利用できない場合の上記の機能の実装。
  • 位置情報サービスが有効になっていない場合、問題を自動的に解決します。

全般的:

  • ドキュメントを更新する

こちらからお気軽にチェックしてください

@mvanbeusekom更新していただきありがとうございます! 👍

みなさん、こんにちは。

私は(最終的に)リリースされたバージョン6.0.0-rc.1を発表できることをうれしく思います。これにより、これらすべての問題が解消されるはずです。

ぜひお試しいただき、フィードバックをいただければ幸いです。

申し訳ありませんが、現在2回クラッシュしており、すでに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フィードバックのおかげで、問題が見つかりました。 どうやらあなたの場合、ジオロケーターは別のプラグインからフィードバックを受け取っているようです(requestCode == 24はpermission_handlerと同じなので、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、OS13.6.1では災害のように機能しました。

初めて位置を取得するのは古いバージョンと同じように機能し、正しい位置を返しましたが、それでも7〜8秒かかりました。

しかし、2回目以降は瞬時に投げ続けました。 次の理由により、 Exception errからdynamic errに変更する必要がありました。
_未処理の例外:タイプ'_TypeError'はタイプ'Exception'_のサブタイプではありません

失敗したとき(最初のフェッチ後)にそれらを取得しています:

2020-08-26 14:01:45.670206 + 0200ランナー[4565:206487]フラッター:場所を取得できませんでした:不良状態:要素なし
2020-08-26 14:01:45.670416 + 0200ランナー[4565:206487]フラッター:場所を取得できませんでした:「NoLocationFoundException」のインスタンス

NoLocationFoundExceptionは私のカスタムクラスです)

_悪い状態:要素はありません_残念ながらあまりわかりません...下に私のコードがあります:

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

すでに閉じられているストリームでfirstを呼び出すため、2回目にgetCurrentPositionを呼び出すと、 Bad state: No element例外が発生すると推測できます。 私はこれに取り組んでおり、すぐに新しい候補者をリリースします。

@Dohmanlechx 、「不良状態:要素なし」が発生する問題は、私が公開したばかりの6.0.0-rc.4で修正されているはずです。 問題を再現することはできませんでしたが、 getCurrentPositionを2回目(およびそれ以降)に呼び出すと、新しいストリームが使用されることを確認できました。

もう一度試してみて、うまくいくかどうか教えていただければ幸いです。

私が気付いたのは、 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秒)の10回のうち7回を超え、関数がスローされます。 getCurrentPosition()をスパムして、iPhoneでテストしましたか? iPhone XS Max、OS13.6.1でテストしました。

_4.0.3_は遅いですが、安定しています
_6.0.0-rc.4_は高速ですが、不安定です

しかし、心配する必要はありません。これは完全に問題なく、特にバージョン4.0.3に独自の時間制限を作成したため、まったく問題はありません。

@Dohmanlechxクラッシュが解決されたことを聞いてうれしい、それは少なくとも何かです;)

私はそれを再現できないので、なぜあなたがまだ遅い更新を受け取っているのか本当に興味があります。 私はそれを試すために非常に簡単なデモアプリを作成しました:

main.dart:

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

Info.plist:

<?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に追加されます。 私はこのアプリを個人のiPhone7、妻のiPhone 6、およびシミュレーター(すべて最新のiOSバージョンを実行している)でテストしましたが、ボタンをスパムする可能性があり、場所はほぼすぐに返されます。 なぜあなたが違う経験をしているのか、私は本当に困惑しています。 たぶん、このサンプルコードをテストして、同じ問題がまだ発生するかどうかを確認できますか?

私はあなたの粘り強さに本当に感心しています。 私は新しいプロジェクトを作成し、あなたのコードを使用しました。ボタンをスパムすることでiPhoneの画面をほとんど壊し、場所は常にすぐに返されました。 素晴らしい! 明日は、コードでトラブルシューティングを行う時間を見つけて、ウィジェットで直接getCurrentPosition()を実行し、原因を見つけるために目的の場所までさらに移動していきます。 パーミッションプラグインが原因だと思いますが、これから見ていきます。

フィードバックと親切な言葉をありがとう、本当に感謝しています。 ジオロケーターの再構築に力を入れましたが、今回の問題で始めようと思ったので、今回は本当にいいものにしたいと思います;)

それがどうなるか、そして私が助けることができるかどうか私に知らせてください。

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

ウィジェットでこれを直接試してみました。クリックするたびに、場所がコンソールに記録されました。 つまり、これは間違いなく私たちのコードです。 だから今、私たちにあります、すべてに感謝します!

ただし、これは位置の取得中に発生することがあります。

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、物理OnePlus6で試してみました。毎回タイムアウトがスローされます。

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 評価