Flutter-geolocator: Le futur ne se résout jamais sur IOS13

Créé le 29 avr. 2020  ·  63Commentaires  ·  Source: Baseflow/flutter-geolocator

🐛 Rapport de bogue

Lorsque j'essaie de getCurrentLocation, cela ne se résout jamais. Je ne suis pas expert sur IOS, donc s'il vous plaît, si j'ai oublié de faire quelque chose, expliquez-le moi.

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

Podfile :

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>

ÉDITER:

J'ai testé sur un vrai appareil Android et le problème se produit également.

Autorisations d'emplacement de mon manifeste :

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

Comportement prévisible

Renvoyez une position.

Étapes de reproduction

Appelez simplement geolocator.GetCurrentPosition.

Version : 5.1.5.

Plate-forme:

  • [x] :iphone : iOS (testé avec le simulateur IOS)
  • [x] :robot : Android (Testé sur un Pocophone Xiomi F1 avec Android 10QkQ1.190828.002)
android ios triage

Commentaire le plus utile

Salut tout le monde,

Je suis heureux d'annoncer que j'ai (enfin) sorti la version 6.0.0-rc.1 qui devrait résoudre tous ces problèmes.

J'apprécierais vraiment si vous pouviez l'essayer et me donner votre avis.

Tous les 63 commentaires

J'obtiens la même erreur. Cela se produit à la fois sur iOS et Android .....

Je reçois la même erreur sur le simulateur exécutant iOS 10.3 ou iOS 13.4 et également sur mon iPad avec iOS 13.4 .

moncode.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>

Version : 5.3.1

Même problème pour moi sur Android 8.0. J'envisage d'écrire une minuterie de 10 secondes directement sur le code source qui se lance si elle est atteinte.

@brenoasm rencontrez-vous ce problème sur le simulateur ou sur un appareil réel ?

@dammel Sur le simulateur, il est important de configurer le simulateur pour émettre un emplacement. Cela peut être fait en utilisant les éléments de menu suivants de l'application du simulateur : Fonctionnalités -> Emplacement -> (sélectionnez une option autre que "aucune").

@mvanbeusekom Et si un vrai appareil n'émet pas de localisation ? Cela ne devrait pas être le cas si l'utilisateur avait désactivé le GPS, n'est-ce pas ?

@mvanbeusekom J'ai testé sur le Simulator for IOS (je n'ai pas d'IPhone pour le tester sur un vrai appareil). Je l'ai testé sur un vrai appareil Android et j'ai le même problème... Je vais modifier et ajouter les informations de mon appareil Android.

J'ai le même problème avec un vrai appareil Android...

@mvanbeusekom Merci pour votre aide. Votre Tipp pour les simulateurs a fonctionné pour moi.
Je n'ai rien changé, mais cela fonctionne à nouveau sur l'iPad (appareil réel).

Testé sur un simulateur iOS et un appareil iOS, je n'ai eu aucun problème mais j'ai le même problème sur un émulateur Android

Je vais essayer d'expliquer mon cas en détail.

Tout d'abord, le problème se produit à la fois sur les appareils Android et iPhone (j'utilise Testflight pour tester l'application avec mon équipe QA), mais également sur Android Emulator et iOS Simulator.

La méthode 'getCurrentPosition' ne renvoie parfois pas de position, mais après une succession d'essais, elle le fait. J'ai généralement ce problème lorsque j'installe l'application pour la première fois. Après un certain temps, la méthode commence soudainement à vous apporter la position actuelle.

Le problème de ce problème est que cela ne se produit pas toujours. Vous pouvez installer l'application, et parfois lors du premier essai, la méthode renvoie la position actuelle...

Remarques supplémentaires :

  1. Si la méthode commence à bien fonctionner et que je fais un rechargement à chaud ou un redémarrage à chaud, la méthode continue de bien fonctionner
  2. La méthode ne lève aucune exception... mais si vous mettez un 'wait' elle s'arrête indéfiniment
  3. J'ai essayé d'utiliser une ancienne version de Geolocator, et le problème persiste
  4. J'utilise Google Maps dans mon projet, alors j'ai pensé "peut-être qu'il y a un conflit avec une version récente de Maps... ?". Nan. Je compile avec d'anciennes versions de Google Maps et le problème persiste
  5. Ce qui est curieux, c'est qu'il y a quelques semaines, je n'ai pas rencontré ce problème...

Mon environnement :

$ 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!

Solution temporaire dans mon projet:

  1. J'ai ajouté un délai d'attente à la méthode 'getCurrentPosition', et si elle renvoie 'null', je démarre une minuterie et j'essaie encore et encore ... après un petit moment (parfois secondes, parfois même une minute) la méthode renvoie la position actuelle
  2. Si j'ai besoin d'une position initiale, j'utilise la méthode 'getLastKnownPosition()'

Je suppose que #375 et #386 sont liés à ce problème

Même problème ici, LG G6, Android 9.0.

Ne se résout jamais.

Il y a une façon étrange de le faire fonctionner:
Je lance l'application Google Maps pour obtenir la position là-bas. Pour cela, j'ai besoin d'activer le capteur de position et le wifi (probablement la connexion de données mobile fonctionnerait également, non testée).
J'obtiens donc la position dans google maps.
Après cela, cela fonctionne également dans mon application (peu importe si mon application a été démarrée par la suite ou déjà en cours d'exécution).
Si je mets fin au wifi ou que j'éteins la position, cela ne fonctionne plus, même si je les rallume.

Fermer google maps à tout moment, même avant l'ouverture de mon application, n'a pas d'importance (mais parfois je dois ouvrir google maps plus d'une fois.)
Il me semble que Google Maps établit quelque chose qui persiste même après la fermeture des cartes et qui est nécessaire au géolocalisateur.

Édition/Correction :
C'est encore plus compliqué, la procédure avec google maps fonctionnait avec tous les arguments pour "desiredAccuracy", mais lors du passage du wifi il y avait 2 catégories :

  • LocationAccuracy.best et LocationAccuracy.high fonctionnaient toujours mais sont devenus plus lents
  • LocationAccuracy.medium, LocationAccuracy.lower et LocationAccuracy.lowest n'ont plus été résolus, également avec ces arguments, le symbole de localisation dans la barre d'état n'est jamais affiché.

Après le redémarrage, l'emplacement de l'appareil ne se résout plus. Je dois donc répéter l'obtention de l'emplacement avec Google Maps, puis cela fonctionne à nouveau comme décrit.

(Quelque chose probablement sans importance, sans rapport, après une nouvelle installation de l'application, la boîte de dialogue d'autorisation est différente, n'a pas la case à cocher "Ne plus demander", mais seulement la première fois que la boîte de dialogue s'affiche, après cela c'est toujours le même dialogue avec la case à cocher)

Même problème, Android 10, OnePlus 7 Pro.

L'astuce décrite ci-dessus avec Google Maps n'a pas fonctionné pour moi, mais d'une manière ou d'une autre, après un certain temps, l'emplacement a commencé à se résoudre sans que je fasse quoi que ce soit de spécifique. je lisais juste une page précédemment ouverte dans le navigateur, puis je suis revenu à mon application et j'ai vu une boîte de dialogue qui m'indiquait l'emplacement - la boîte de dialogue est configurée pour indiquer quand l'avenir se résout, donc finalement cela s'est résolu, mais cela a pris un certain temps . Après cela, l'emplacement se résolvait bien à chaque tentative.
Comme mentionné ci-dessus après le redémarrage, l'emplacement ne se résout plus.

Sur le simulateur, tout fonctionne parfaitement.

Après le message de @SchmadenSchmuki , j'ai fait quelques tests dans mon projet, et voici ma conclusion : Il y a quelque chose qui ne va pas avec le plugin Google Maps qui affecte le plugin Geolocator. Il y a une incompatibilité entre eux.

Voici le flux de mon application lorsque je la démarre pour la première fois :

  1. Il affiche un écran de démarrage
  2. Pendant ce temps, l'application se connecte à une API pour extraire les données de l'utilisateur
  3. J'utilise Geolocator pour localiser la position actuelle de l'utilisateur
  4. L'application quitte l'écran de démarrage, puis j'affiche une carte indiquant où se trouve l'utilisateur

Avec ce flux, l'application échoue. La méthode 'getCurrentPosition()' de Geolocator échoue, elle ne renvoie jamais de valeur. REMARQUE : les méthodes 'isLocationServiceEnabled()' et 'getLastKnownPosition()' fonctionnent correctement.

MAIS si je change le flux en :

  1. L'écran de démarrage
  2. Connectez-vous à l'API pour extraire les données utilisateur
  3. Rendre la carte avec un emplacement aléatoire
  4. Utilisez Geolocator pour localiser la position actuelle de l'utilisateur
  5. Déplacer la caméra de la carte vers la position actuelle

ÇA MARCHE!!!!!

Donc, ma conclusion est que, d'une certaine manière, le plugin Google Maps occupe "quelque chose" qui bloque les autres plugins pour utiliser le service de géolocalisation. Lorsque Google Maps effectue le rendu, cela libère ce "quelque chose" et tout le monde peut alors travailler sans problème.

Si quelqu'un d'autre peut le confirmer, nous pouvons ouvrir un problème aux gars de Flutter pour voir cela

@KnucklesEQ merci beaucoup pour le reportage détaillé. Je vais commencer à déboguer ce problème et passer plus de temps à reproduire et, espérons-le, à résoudre le problème. Il serait très utile que d'autres ici puissent vérifier s'ils utilisent également le plug-in Google Maps ?

Néanmoins, je pense qu'il y a plusieurs problèmes (différences entre Android 9 + Android 10, iOS prend parfois plusieurs secondes pour renvoyer un emplacement, en utilisant Geolocator en combinaison avec Google Maps) et je vais commencer à me concentrer sur tous ceux-ci et voir si je peux améliorer la situation. Cela prendra un certain temps, alors s'il vous plaît, soyez indulgent avec moi pendant que je fais de mon mieux et j'essaierai de laisser des mises à jour ici sur mes progrès.

Je n'utilise pas le plugin Maps. J'ai remarqué que lorsque j'accorde l'autorisation uniquement lorsque l'application est en cours d'exécution (locationWhenInUse), la prochaine fois que je demanderai, elle ne s'affichera pas et ne se résoudra jamais (Android uniquement, sur IOS Cela n'a jamais fonctionné depuis que j'ai ouvert ce problème).

Je n'utilise pas le plugin Google Maps.

Ne pas utiliser le plugin Google Maps non plus.
(Lorsque j'ai eu des problèmes, j'ai vérifié si l'application Google Maps avait également des problèmes pour obtenir l'emplacement, puis j'ai vu que l'obtention de l'emplacement avait un effet sur mon application)

plus de détails:
le problème se produit lorsque les conditions suivantes sont vraies

  • j'utilise le gestionnaire de localisation (Geolocator().forceAndroidLocationManager = true)
  • j'utilise la précision de localisation par défaut, qui est LocationAccuracy.best
  • je suis à l'intérieur

Je l'ai tracé à travers le code et ce qui se passe, c'est que dans les 2 premières conditions, le fournisseur de localisation choisi est "gps" et l'appareil ne peut tout simplement pas capter le signal gps à l'intérieur. Je suis sorti sur le balcon et presque immédiatement les choses ont commencé à fonctionner normalement.

Je n'ai pas essayé de jouer avec la précision de localisation pour voir comment cela affecte le choix du fournisseur de localisation, mais j'ai simplement essayé de forcer le fournisseur à « réseauter » (par codage en dur). Cela fonctionne, mais la précision sur l'emplacement récupéré n'était évidemment pas très bonne - ~ 1080 mètres.

@minusminuszero a raison, c'est pareil pour moi.
Donc pour moi, ça fait ce qu'il faut, même immédiatement après le redémarrage, désolé pour les inconvénients.
(Je ne définis pas le gestionnaire de localisation, donc c'est forceAndroidLocationManager = false dans mon cas. J'utilise LocationAccuracy.best et je suppose que cela fonctionnerait également avec LocationAccuracy.high, ne fonctionne probablement pas pour une précision inférieure car dans ces cas, le symbole de localisation n'apparaît pas dans la barre d'état, mais il y a déjà un problème pour cela.)

Je vis également ce qui précède, avec exactement les mêmes étapes à reproduire (être à l'intérieur, emplacement par défaut, etc.)

plus de détails:
le problème se produit lorsque les conditions suivantes sont vraies

  • j'utilise le gestionnaire de localisation (Geolocator().forceAndroidLocationManager = true)
  • j'utilise la précision de localisation par défaut, qui est LocationAccuracy.best
  • je suis à l'intérieur

Je l'ai tracé à travers le code et ce qui se passe, c'est que dans les 2 premières conditions, le fournisseur de localisation choisi est "gps" et l'appareil ne peut tout simplement pas capter le signal gps à l'intérieur. Je suis sorti sur le balcon et presque immédiatement les choses ont commencé à fonctionner normalement.

Je n'ai pas essayé de jouer avec la précision de localisation pour voir comment cela affecte le choix du fournisseur de localisation, mais j'ai simplement essayé de forcer le fournisseur à « réseauter » (par codage en dur). Cela fonctionne, mais la précision sur l'emplacement récupéré n'était évidemment pas très bonne - ~ 1080 mètres.

Comment avez-vous procédé pour forcer l'emplacement "réseau" ? Cela me suffirait pour résoudre le problème tel qu'il se produit à l'intérieur au moins

Comment avez-vous procédé pour forcer l'emplacement "réseau" ? Cela me suffirait pour résoudre le problème tel qu'il se produit à l'intérieur au moins

Je l'ai fait en codant en dur la valeur du fournisseur de localisation directement dans le code du plug-in de géolocalisation. Je suppose que choisir la faible précision aurait le même effet, mais je n'ai pas essayé.

La méthode devrait probablement avoir un paramètre de délai d'attente, non ?

L'équipe Flutter/Geolocator travaille-t-elle sur ce problème ?

Oui nous sommes

Merci @mvanbeusekom !
Savez-vous quelle est la source du problème ?
Avez-vous trouvé un moyen de le contourner (ou une sorte de solution temporaire) ?
(la rétrogradation à 4.0.3 ne l'a pas résolu pour nous)

Sur le simulateur il est important de configurer le simulateur pour émettre une localisation. Cela peut être fait en utilisant les éléments de menu suivants de l'application du simulateur : Fonctionnalités -> Emplacement -> (sélectionnez une option autre que "aucune").

Cela a résolu le problème pour moi. Mais c'est un bogue très déroutant car il échoue sans aucune exception ni quoi que ce soit.

Sur le simulateur il est important de configurer le simulateur pour émettre une localisation. Cela peut être fait en utilisant les éléments de menu suivants de l'application du simulateur : Fonctionnalités -> Emplacement -> (sélectionnez une option autre que "aucune").

Cela a résolu le problème pour moi. Mais c'est un bogue très déroutant car il échoue sans aucune exception ni quoi que ce soit.

Ouais, pour moi aussi.
Veuillez ajouter un délai d'attente dans la demande d'emplacement et lever une exception dans le simulateur qui n'a pas d'emplacement défini.

Merci :)

J'ai le même problème sur iOS, j'utilise également le plugin google maps.
J'ai une application qui utilise getLocationStream mais je n'obtiens pas de boîte de dialogue d'autorisation jusqu'à ce que j'aille sur l'onglet où j'ai une carte google.
J'ai une autre application où je n'utilisais plus Google Maps mais j'ai oublié de supprimer le plugin et j'ai eu le même problème. J'ai supprimé le plugin Google Maps et maintenant il fonctionne correctement.

Des mises à jour à ce sujet ?

Bonjour à tous, je travaille dur sur ce problème. Fondamentalement, nous avons décidé de créer le géolocalisateur à partir de zéro et de résoudre plusieurs problèmes à la fois.

Les points qui seront inclus sont :

  • Résoudre les problèmes d'autorisation ;
  • Assurez-vous que le getCurrentLocation est récupéré dans un délai raisonnable ;
  • Ajoutez un délai d'expiration aux méthodes getCurrentLocation et getPositionStream , de sorte que si l'acquisition de l'emplacement prend plus de temps que prévu, la demande expirera et vous pourrez redémarrer la demande ;
  • Améliorer les messages d'erreur potentiels ;
  • Passez à une structure de plug-in fédérée afin que nous soyons prêts pour le support Web ;
  • Mise à jour vers le plug-in Android v2 ;

La première étape à franchir était de déplacer les fonctionnalités de géocodage et de les héberger dans leur propre plugin (qui est maintenant disponible sur pub.dev .

La deuxième étape consistait à créer et à tester unitairement tout le code Dart nécessaire, qui est maintenant prêt et peut être consulté sur la branche federated_plugin .

Les étapes suivantes consistent à ajouter des implémentations iOS et Android et à corriger l'exemple d'application. C'est ce sur quoi je travaille actuellement, j'espère pouvoir tout finir dans les deux semaines à venir (veuillez garder à l'esprit que je dois aussi le faire pendant mon temps libre ;)).

Quoi qu'il en soit, je tiens à remercier tout le monde pour leur patience et leurs commentaires, veuillez patienter un peu plus longtemps.

@mvanbeusekom
C'est une bonne nouvelle. Je suis content que vous preniez le temps de nous fournir ce plugin.

Un grand merci vous est adressé !

J'attends avec impatience les mises à jour suivantes.

Merci et meilleures salutations

Agréable! Faites-nous savoir quand il sera publié afin que nous puissions tester.

Pour une solution de contournement temporaire, vous pouvez vérifier l'état de l'appareil avec la méthode GeolocationStatus checkGeolocationPermissionStatus() . Si l'emplacement est désactivé, cette méthode renvoie "disabled". Ensuite, vous n'avez pas besoin d'appeler la méthode getCurrentPosition() .

Exemple:

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

Petite mise à jour ici, ce matin, j'ai poussé une nouvelle mise à jour de la branche federated_plugin qui inclut un support complet sur iOS, y compris un exemple d'application Flutter.

Nous avons également commencé à travailler sur Android qui prend en charge la vérification de l'état des autorisations, nous allons maintenant implémenter la demande d'autorisations et gérer les services de localisation.

N'hésitez pas à consulter le code ou même à essayer de l'intégrer dans une application de test et à l'exécuter sur iOS. Notez qu'il inclut un grand nombre de changements avec rupture qui seront tous documentés. Pour l'instant, je voulais juste faire savoir à tout le monde qu'il y a des progrès, même si cela prend du temps. Encore merci pour toute votre patience.

Petite mise à jour ici, ce matin, j'ai poussé une nouvelle mise à jour de la branche federated_plugin qui inclut un support complet sur iOS, y compris un exemple d'application Flutter.

Nous avons également commencé à travailler sur Android qui prend en charge la vérification de l'état des autorisations, nous allons maintenant implémenter la demande d'autorisations et gérer les services de localisation.

N'hésitez pas à consulter le code ou même à essayer de l'intégrer dans une application de test et à l'exécuter sur iOS. Notez qu'il inclut un grand nombre de changements avec rupture qui seront tous documentés. Pour l'instant, je voulais juste faire savoir à tout le monde qu'il y a des progrès, même si cela prend du temps. Encore merci pour toute votre patience.

Merci d'avoir travaillé dur là-dessus. Mettez-vous à jour le package de géolocalisation sur pub.dev avec ce changement ?

Est-ce également le fichier de l'exemple que vous avez mentionné ci-dessus : position_updates_example_widget.dart ?

Merci d'avoir travaillé dur là-dessus. Mettez-vous à jour le package de géolocalisation sur pub.dev avec ce changement ?

Est-ce également le fichier de l'exemple que vous avez mentionné ci-dessus : position_updates_example_widget.dart ?

Non, je ne publierai pas encore sur pub.dev. Il s'agit d'une refonte complète du plugin de géolocalisation et ne prend pas encore en charge Android. Une fois Android et la documentation terminée, je la publierai sur pub.dev.

Oui, ce widget fait partie de l'exemple d'application et montre comment vous pouvez écouter les mises à jour de position.

Salut,

Merci pour ce colis.

Une chance de terminer toutes les tâches mentionnées ci-dessus pour Android cette semaine ?

Une mise à jour pour ceci?

N'attend que l'emplacement en retard lors de la toute première demande.

Des mises à jour sur la date de sortie de la version retravaillée ? @mvanbeusekom

@dalmia007 , je n'ai pas encore de date mais des progrès sont en cours. J'ai ajouté un support rudimentaire pour Android sur la branche feature/federated_android . Il contient la demande d'autorisations, l'obtention du dernier emplacement connu, l'obtention de l'emplacement actuel et les mises à jour de l'emplacement à l'aide du client du fournisseur de localisation fusionné (qui fait partie des services Google Play).

Je travaille toujours sur les éléments suivants :

Spécifique à Android :

  • Mise en œuvre des fonctionnalités ci-dessus lorsque les services Google Play ne sont pas disponibles ;
  • Résolvez automatiquement les problèmes lorsque les services de localisation ne sont pas activés ;

Général:

  • Mettre à jour la documentation

N'hésitez pas à le consulter ici

@mvanbeusekom merci beaucoup pour la mise à jour ! 👍

Salut tout le monde,

Je suis heureux d'annoncer que j'ai (enfin) sorti la version 6.0.0-rc.1 qui devrait résoudre tous ces problèmes.

J'apprécierais vraiment si vous pouviez l'essayer et me donner votre avis.

Je suis désolé de le dire, mais il s'est écrasé deux fois maintenant, assez pour revenir déjà à la version 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

Cela s'est produit lorsque j'ai appuyé sur Autoriser l'octroi dans la boîte de dialogue et aussi lorsque j'ai appuyé sur Refuser. Faites-moi savoir si j'ai raté quelque chose.

@Dohmanlechx juste pour s'assurer, avez-vous obtenu ceci sur 6.0.0-rc.x ou sur la version 5.3.2 ?

J'ai obtenu ceci sur 6.0.0-rc.1 (l'IDE m'a demandé de "mettre à jour" vers 5.3.2+2 , FYI)

@Dohmanlechx grâce à vos commentaires, j'ai trouvé un problème. Apparemment, dans votre cas, le géolocalisateur reçoit des commentaires d'un autre plugin (je suppose que vous utilisez le permission_handler pour gérer les autorisations puisque le requestCode == 24 qui est le même que le permission_handler) qu'il essaie de traiter, ce qui échoue évidemment. Dans ces cas, le géolocalisateur doit simplement ignorer ces messages puisqu'ils n'appartiennent pas au géolocalisateur. Je vais corriger cela aujourd'hui et publier une nouvelle version candidate.

Merci pour vos commentaires!

Oh, en effet, nous utilisons permission_handler . Bonne trouvaille !

Tous les crédits vous reviennent @Dohmanlechx ;). Grâce à vos retours j'ai pu découvrir ce bug et je pourrai bientôt sortir une nouvelle version.

@Dohmanlechx Je viens de publier la version 6.0.0-rc.3 qui devrait corriger le bogue que vous avez rencontré.

Très cool, testé avec soin sur l'émulateur Android, accordant et refusant, manipulant l'emplacement, a parfaitement fonctionné. A bien fonctionné sur mon vrai appareil Android également.

Mais aucune demande système ne s'affiche pour le simulateur iOS, devinez-vous que c'est prévu ? Cependant, il ne plantera pas au moins et l'application fonctionne comme souhaité sans aucun emplacement disponible. Malheureusement, je ne suis toujours pas en mesure de tester sur mon iPhone en raison d'un problème de connexion Xcode et je ne souhaite pas déployer une version de TestFlight uniquement pour tester maintenant. Je vous tiendrai au courant dès que j'aurai testé sur iPhone.

Mais jusqu'ici tout va bien!

Merci beaucoup pour les tests approfondis @Dohmanlechx , c'est très apprécié !

Le plugin n'affiche en effet pas de demande de service sur iOS, car il n'y a pas d'API (publique) pour le faire. La seule option que nous avons ici est de montrer manuellement à l'utilisateur un message expliquant comment mettre à jour les paramètres manuellement. Nous avons la possibilité de rediriger l'utilisateur vers l'application Paramètres (en appelant les méthodes openAppSettings() ou openLocationSettings() ). J'ai documenté cela plus en détail dans le fichier README.md .

Je regrette de l'informer, mais cela a fonctionné comme un désastre sur mon iPhone XS Max, OS 13.6.1.

La première fois que la récupération de la position a fonctionné comme l'ancienne version, a renvoyé la position correcte, mais cela a quand même pris 7 à 8 secondes.

Mais à partir de la deuxième fois et plus loin, il n'a cessé de lancer instantanément. J'ai dû passer de Exception err à dynamic err à cause de :
_ Exception non gérée : le type '_TypeError' n'est pas un sous-type du type 'Exception' _.

Je les reçois quand ça échoue (après la première récupération):

2020-08-26 14:01:45.670206+0200 Runner[4565:206487] flutter : impossible de récupérer l'emplacement : mauvais état : aucun élément
2020-08-26 14:01:45.670416+0200 Runner[4565:206487] flutter : impossible de récupérer l'emplacement : instance de 'NoLocationFoundException'

( NoLocationFoundException est ma classe personnalisée)

_Mauvais état : aucun élément_ ne dit pas grand-chose malheureusement... en dessous se trouve mon code :

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

J'espère sincèrement que vous pourrez reproduire cela sur votre iPhone.

@Dohmanlechx , merci pour les commentaires détaillés, je pense avoir trouvé le problème ici. Maintenant, je dois trouver un bon moyen de le réparer ;)

En bref, la méthode getCurrentPosition appelle le getPositionStream et prend le premier élément, puis ferme le flux. Le problème est que le getPositionStream a un code comme celui-ci :

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

Ce que vous pouvez deviner provoque l'exception Bad state: No element lors de l'appel du getCurrentPosition pour la deuxième fois, car il appellera first sur un flux déjà fermé. Je vais y travailler et publier un nouveau candidat bientôt.

@Dohmanlechx , vous indiquez où vous obtenez le "Bad state: No element" aurait dû être corrigé dans 6.0.0-rc.4 que je viens de publier. Je n'ai pas pu reproduire le problème, mais j'ai pu m'assurer que le getCurrentPosition utilisera un nouveau flux lorsque vous l'appellerez une deuxième fois (et toutes les suivantes).

J'apprécierais vraiment que vous puissiez faire un autre essai et me faire savoir si cela fonctionne.

Ce que j'ai remarqué, c'est que vous utilisez directement le GeolocatorPlatform.instance.<some_method> , en faisant cela, vous passez n'importe quelle logique qui se trouve dans le package geolocator et passez directement à l'implémentation par défaut qui se trouve dans le geolocator_platform_instance forfait. Pour l'instant, il n'y a pas d'implémentation spécifique dans le package geolocator mais il est toujours préférable de ne pas le contourner.

Si vous importez le package géolocalisateur, vous devriez pouvoir appeler directement les méthodes globales, par exemple :

import 'package:geolocator/geolocator.dart';

final position = await getCurrentPosition();

Si vous rencontrez des collisions ou si vous souhaitez simplement préfixer les méthodes globales, vous pouvez ajouter un alias à l'importation, comme ceci :

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

final position = await geolocator.getCurrentPosition();

Merci, j'ai aussi changé le code selon vos suggestions.

Le crash est parti maintenant mais malheureusement, c'est encore trop instable. 3 fois sur 10, c'est extrêmement rapide (j'aurais vraiment aimé que ce soit 10 fois sur 10), mais 7 fois sur 10, la limite de temps (10 secondes) dépasse et la fonction lance. Avez-vous testé sur votre iPhone, spammer le getCurrentPosition() ? J'ai testé sur iPhone XS Max, OS 13.6.1.

_4.0.3_ est lent mais stable
_6.0.0-rc.4_ est rapide mais instable

Mais pas de soucis, c'est tout à fait correct et absolument pas de catastrophe pour nous, d'autant plus que j'ai écrit mon propre délai pour la version 4.0.3.

@Dohmanlechx content d'apprendre que le crash est résolu, c'est au moins quelque chose ;)

Je suis vraiment intéressé par la raison pour laquelle vous recevez toujours des mises à jour lentes puisque je ne peux pas le reproduire. J'ai créé une application de démonstration très simple pour l'essayer :

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>

Ainsi, chaque fois que j'appuie sur le bouton d'action flottant, getCurrentPosition est appelé et le résultat est ajouté au ListView . J'ai testé cette application sur mon iPhone 7 personnel, l'iPhone 6 de ma femme et le simulateur (tous exécutant la dernière version d'iOS), mais je peux spammer le bouton et l'emplacement est renvoyé presque immédiatement. Je suis vraiment perplexe pourquoi vous avez une expérience différente. Peut-être pouvez-vous tester cet exemple de code et voir si vous rencontrez toujours le même problème ?

J'admire vraiment votre persévérance. J'ai créé un nouveau projet et utilisé vos codes, presque cassé l'écran de l'iPhone en spammant le bouton, l'emplacement est revenu immédiatement tout le temps. Impressionnant! Demain, j'essaierai de trouver le temps de dépanner dans notre code, en commençant par exécuter getCurrentPosition() directement dans le Widget, puis en le déplaçant de plus en plus loin jusqu'à son emplacement prévu afin de trouver le coupable. Je soupçonne que c'est à cause du plugin d'autorisations, mais nous verrons.

Merci pour les commentaires et les mots gentils, vraiment apprécié. J'ai mis beaucoup d'efforts à reconstruire le géolocalisateur et c'est ce problème qui m'a vraiment décidé à le démarrer, donc j'aimerais vraiment que ce soit bien cette fois ;)

S'il vous plaît laissez-moi savoir comment ça se passe et si je peux aider.

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

J'ai essayé cela directement dans le Widget et à chaque fois que je cliquais, un emplacement était enregistré sur la console ! C'est donc définitivement notre code. Alors c'est à nous maintenant, merci pour tout !

Cependant, cela se produit _parfois_ lors de la récupération de la position :

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 Je ne parviens pas du tout à obtenir le poste en utilisant la dernière version 6.0.0 + 1. Essayé sur simulateur iOS, émulateur Android API 29, OnePlus 6 physique. Le délai d'attente est levé à chaque fois.

image

image

Je ne sais pas quoi d'autre je peux ajouter ici pour vous aider à trouver le problème, getCurrentPosition renvoie le délai d'attente ou se bloque simplement si le paramètre timeLimit n'est pas spécifié. J'ai essayé différentes précisions de localisation. Est-ce que quelqu'un a ce problème?

La version 5.3.2 + 2 fonctionne correctement sur le simulateur iOS (avec l'emplacement personnalisé spécifié), l'appareil réel Android et l'émulateur Android

@mvanbeusekom , j'ai lu tout cela et je mets à niveau vers la dernière version pour résoudre le problème de délai de 10 secondes.

Il me manque peut-être quelque chose, mais il y a quelque chose que je ne peux plus faire dans la nouvelle version (géocodage).
J'avais l'habitude de pouvoir définir manuellement une position sur le centre-ville (au cas où l'utilisateur refuserait l'emplacement), en procédant comme suit :

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

Maintenant, il semble que _placemarkFromAddress_ ait été changé en _ locationFromAddress _, j'ai donc essayé de m'adapter en faisant les changements suivants dans ma formule :

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

Mais j'obtiens l'erreur suivante :

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

Comment puis-je convertir l'emplacement en position, ou finalement, si l'utilisateur nie l'emplacement, comment puis-je maintenant définir sa position sur son centre-ville ?

Merci.

J'ai mis à jour la dernière version, j'ai résolu le problème pour moi 👍👍👍

Cette page vous a été utile?
0 / 5 - 0 notes