Flutter-geolocator: Ответ на уже отправленный сбой

Созданный на 4 сент. 2020  ·  16Комментарии  ·  Источник: Baseflow/flutter-geolocator

🐛 Отчет об ошибке

В примере приложения LastKnownLocationExampleWidget запрещает закрытие разрешения и повторно открывает приложение. Я получаю следующее исключение, и приложение вылетает.

E/AndroidRuntime(12916): Process: com.baseflow.geolocator_example, PID: 12916
E/AndroidRuntime(12916): java.lang.IllegalStateException: Reply already submitted
E/AndroidRuntime(12916):    at io.flutter.embedding.engine.dart.DartMessenger$Reply.reply(DartMessenger.java:139)
E/AndroidRuntime(12916):    at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler$1.success(MethodChannel.java:235)
E/AndroidRuntime(12916):    at com.baseflow.geolocator.MethodCallHandlerImpl.lambda$onGetLastKnownPosition$2(MethodCallHandlerImpl.java:149)
E/AndroidRuntime(12916):    at com.baseflow.geolocator.-$$Lambda$MethodCallHandlerImpl$tyxDngVVF7PcImb4PihgQ0FJ8po.onPositionChanged(Unknown Source:2)
E/AndroidRuntime(12916):    at com.baseflow.geolocator.location.-$$Lambda$FyNSKWRJ6K8pfIKflyK9zilTOk0.onSuccess(Unknown Source:4)
E/AndroidRuntime(12916):    at com.google.android.gms.tasks.zzn.run(Unknown Source:4)
E/AndroidRuntime(12916):    at android.os.Handler.handleCallback(Handler.java:883)
E/AndroidRuntime(12916):    at android.os.Handler.dispatchMessage(Handler.java:100)
E/AndroidRuntime(12916):    at android.os.Looper.loop(Looper.java:214)
E/AndroidRuntime(12916):    at android.app.ActivityThread.main(ActivityThread.java:7356)
E/AndroidRuntime(12916):    at java.lang.reflect.Method.invoke(Native Method)
E/AndroidRuntime(12916):    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
E/AndroidRuntime(12916):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)

Версия: 6.0.0 + 3

Платформа:

  • []: iphone: iOS
  • [x]: robot: Android
android in progress needs more info bug

Все 16 Комментарий

@humazed спасибо за отчет об ошибке. Я как бы знаю, откуда возникает ошибка (и я могу ее устранить), но я не могу ее воспроизвести, и, судя по трассировкам стека, которые вы мне отправляете, эта ошибка не должна возникать в первую очередь.

Поэтому мне интересно, можете ли вы помочь мне выяснить, что вызывает эту проблему, чтобы я мог решить ее правильным образом. Итак, чтобы дать вам некоторые подробности, вот что, как мне кажется, происходит (на основе информации трассировки стека и шагов, которые вы описываете):

Шаг 1:

  1. Вы запускаете пример приложения с помощью отладчика (впервые), и он запрашивает у вас разрешения;
  2. Вы запрещаете разрешения, и приложение показывает вам сообщение «Пользователь отказал в разрешении на доступ к местоположению устройства»;
  3. На этом этапе вы прекращаете отладку, и приложение закрывается.

Пока все хорошо.

Шаг 2:

  1. Вы снова начинаете отладку приложения, и оно запускается;
  2. На этом этапе приложение должно обнаружить, что разрешения были отклонены, и должно снова показать всплывающее окно с запросом разрешения (это то, что происходит со мной), однако для вас приложение вылетает из-за указанной выше трассировки стека.

Сбой происходит из-за того, что приложение каким-то образом входит в Java onRequestPermissionResult(int requestCode, String[] permissions, int[] grantResults) без отображения всплывающего окна с разрешениями, а массивы permissions и grantResults пусты. В моем предыдущем обновлении (6.0.0 + 3) я обнаружил, что эти параметры пусты, и попытался отправить обратно, что разрешения запрещены (см. Фрагмент кода ниже):

    <strong i="24">@Override</strong>
    public boolean onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        if (requestCode != PERMISSION_REQUEST_CODE || permissions.length == 0 || grantResults.length == 0) {
            if (this.resultCallback != null) {
                this.resultCallback.onResult(LocationPermission.denied);
            }
            return false;
        }

        ....
  }

Как вы могли догадаться, отправка статуса разрешения в этой ситуации вызовет исключение, которое вы указали выше, потому что информация уже была отправлена ​​по каналу. Это странно, потому что, насколько я понимаю, шаги, которые вы предпримете, будут новым каналом, и на самом деле это должен быть первый раз, когда информация отправляется обратно по каналу.

Еще странно то, что onRequestPermissionResults вызывается с пустыми параметрами permissions и grantResults . Я могу предотвратить возникновение исключения, обновив код до:

    <strong i="32">@Override</strong>
    public boolean onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        if (requestCode != PERMISSION_REQUEST_CODE) {
            if (this.resultCallback != null) {
                this.resultCallback.onResult(LocationPermission.denied);
            }
            return false;
        }

        if (permissions.length == 0 || grantResults.length == 0) {
            return false;
        }

        ....
  }

Но я боюсь, что это замаскирует реальную проблему. Можете ли вы помочь мне найти настоящую проблему, проверив следующее:

  1. Это действительно те шаги, которые вы предприняли?
  2. Вы что-нибудь изменили в примере кода?
  3. Не могли бы вы предоставить некоторую информацию о версии Android и устройстве, которое вы используете для запуска примера приложения?

Ваша помощь будет принята с благодарностью.

Шаг 1 :
запустить приложение и отказать в разрешении.
Шаг 2:
Нажмите кнопку "Назад".
Шаг 3:
откройте приложение и посмотрите на сбой.

пришлю вам запись экрана.

запись ошибки
https://drive.google.com/file/d/1dh2dIdiUWcOEysYX1Fh37kuCAc3-gTCl/view?usp=sharing

устройство:
pixel_2_XL_API_28 эмулятор

Привет,
У меня такая же проблема.

Шаги по воспроизведению моего просты: разрешить местоположение, затем разрешить файл, и мои приложения разбились.

Устройство:
Pixel_3a

D/AndroidRuntime(31159): Shutting down VM
E/AndroidRuntime(31159): FATAL EXCEPTION: main
E/AndroidRuntime(31159): Process: rest.clinimetric, PID: 31159
E/AndroidRuntime(31159): java.lang.RuntimeException: Failure delivering result ResultInfo{who=<strong i="10">@android</strong>:requestPermissions:, request=35569, result=-1, data=Intent { act=android.content.pm.action.REQUEST_PERMISSIONS (has extras) }} to activity {rest.clinimetric/rest.clinimetric.MainActivity}: java.lang.IllegalStateException: Reply already submitted
E/AndroidRuntime(31159):    at android.app.ActivityThread.deliverResults(ActivityThread.java:4845)
E/AndroidRuntime(31159):    at android.app.ActivityThread.handleSendResult(ActivityThread.java:4886)
E/AndroidRuntime(31159):    at android.app.servertransaction.ActivityResultItem.execute(ActivityResultItem.java:51)
E/AndroidRuntime(31159):    at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
E/AndroidRuntime(31159):    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
E/AndroidRuntime(31159):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016)
E/AndroidRuntime(31159):    at android.os.Handler.dispatchMessage(Handler.java:107)
E/AndroidRuntime(31159):    at android.os.Looper.loop(Looper.java:214)
E/AndroidRuntime(31159):    at android.app.ActivityThread.main(ActivityThread.java:7356)
E/AndroidRuntime(31159):    at java.lang.reflect.Method.invoke(Native Method)
E/AndroidRuntime(31159):    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
E/AndroidRuntime(31159):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
E/AndroidRuntime(31159): Caused by: java.lang.IllegalStateException: Reply already submitted
E/AndroidRuntime(31159):    at io.flutter.embedding.engine.dart.DartMessenger$Reply.reply(DartMessenger.java:139)
E/AndroidRuntime(31159):    at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler$1.success(MethodChannel.java:235)
E/AndroidRuntime(31159):    at com.baseflow.geolocator.MethodCallHandlerImpl.lambda$onRequestPermission$0(MethodCallHandlerImpl.java:133)
E/AndroidRuntime(31159):    at com.baseflow.geolocator.-$$Lambda$MethodCallHandlerImpl$HgwoSKdIeyav7j8ZZJufnb77Lqo.onResult(Unknown Source:2)
E/AndroidRuntime(31159):    at com.baseflow.geolocator.permission.PermissionManager.onRequestPermissionsResult(PermissionManager.java:103)
E/AndroidRuntime(31159):    at io.flutter.embedding.engine.FlutterEnginePluginRegistry$FlutterEngineActivityPluginBinding.onRequestPermissionsResult(FlutterEnginePluginRegistry.java:664)
E/AndroidRuntime(31159):    at io.flutter.embedding.engine.FlutterEnginePluginRegistry.onRequestPermissionsResult(FlutterEnginePluginRegistry.java:364)
E/AndroidRuntime(31159):    at io.flutter.embedding.android.FlutterActivityAndFragmentDelegate.onRequestPermissionsResult(FlutterActivityAndFragmentDelegate.java:573)
E/AndroidRuntime(31159):    at io.flutter.embedding.android.FlutterActivity.onRequestPermissionsResult(FlutterActivity.java:602)
E/AndroidRuntime(31159):    at android.app.Activity.dispatchRequestPermissionsResult(Activity.java:8289)
E/AndroidRuntime(31159):    at android.app.Activity.dispatchActivityResult(Activity.java:8139)
E/AndroidRuntime(31159):    at android.app.ActivityThread.deliverResults(ActivityThread.java:4838)
E/AndroidRuntime(31159):    ... 11 more
I/Process (31159): Sending signal. PID: 31159 SIG: 9
Lost connection to device.

Привет, @humazed , спасибо за предоставленные шаги воспроизведения, я думаю, что выяснил настоящую проблему, которая возникает. Я считаю, что ошибка возникает из-за того, что разрешения запрашиваются несколько раз, пока первый вызов все еще обрабатывается, что вызывает предупреждение об активности Android «W / Activity (24060): может запрашивать только один набор разрешений за раз», и приводит к onRequestPermissionsResult с пустыми параметрами permissions и grantResults . Это может произойти, например, когда мы напрямую вызываем getLastKnownPosition из метода Flutter build который может запускаться несколько раз. Или, в качестве примера, я могу последовательно воспроизвести проблему, используя следующий пример кода:

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

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

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  <strong i="12">@override</strong>
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      home: MyHomePage(title: 'Geolocator #396'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  <strong i="13">@override</strong>
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState 
  extends State<MyHomePage>
  with WidgetsBindingObserver {

  <strong i="14">@override</strong>
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this);
  }

  <strong i="15">@override</strong>
  void didChangeDependencies() {
    getCurrentPosition(forceAndroidLocationManager: true).then((position) => print('Start: $position'));
    super.didChangeDependencies();
  }

  <strong i="16">@override</strong>
  void didChangeAppLifecycleState(AppLifecycleState state) {
    print(state);
    getCurrentPosition(forceAndroidLocationManager: true).then((position) => print('Resume: $position'));
  }

  <strong i="17">@override</strong>
  Widget build(BuildContext context) {
   return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),// This trailing comma makes auto-formatting nicer for build methods.
    );
  }

  <strong i="18">@override</strong>
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }
}

Проблема в том, что это происходит только тогда, когда вам нужно запросить разрешения. Помните, что методы getLastKnownPosition , getCurrentPosition и getPositionStream будут автоматически запрашивать разрешения, когда это применимо. Дилемма состоит в том, что после того, как вы уже запросили разрешение, вполне нормально вызвать getLastKnownPosition (или один из других методов позиционирования) несколько раз. Так что я могу справиться с этим тремя способами:

  1. Добавьте проверку onRequestPermissionResults которая игнорирует вызов, когда параметры permissions и grantResults пусты;
  2. Убедитесь, что вы можете вызвать методы getLastKnownPosition , getCurrentPosition и getPositionStream только один раз, если их уже запущенный запрос;
  3. Удалите автоматическое разрешение разрешений из методов getLastKnownPosition , getCurrentPosition и getPositionStream и предоставьте разработчикам возможность обрабатывать разрешения.

На данный момент мне больше всего подходит первое решение, так как другие будут иметь другие недостатки или действительно вносят огромные критические изменения. Я реализую первое решение сейчас, чтобы убедиться, что у нас есть работоспособное решение. Но мне интересно, как вы относитесь к различным вариантам?

Привет, @humazed , @NindoK , я только что выпустил версию 6.0.0 + 4 плагина

Благодаря информации от @humazed мне удалось воспроизвести проблему и подтвердить, что это изменение должно решить проблему. Однако вы можете по-прежнему видеть предупреждение «W / Activity (24060): может запрашивать только один набор разрешений за раз», которое вы можете игнорировать.

Сообщите мне, решит ли это проблему для вас, а пока я оставлю эту проблему открытой.

Спасибо, исправил!

Привет, @NindoK , спасибо за тестирование и подтверждение, что проблема решена. Закрою вопрос сейчас.

Я также могу подтвердить, что это исправлено, спасибо

Во вторник, 8 сентября 2020 г., в 19:49 Maurits van Beusekom <
[email protected]> написал:

Закрыт № 513 https://github.com/Baseflow/flutter-geolocator/issues/513 .

-
Вы получаете это, потому что вас упомянули.
Ответьте на это письмо напрямую, просмотрите его на GitHub
https://github.com/Baseflow/flutter-geolocator/issues/513#event-3742130966 ,
или отказаться от подписки
https://github.com/notifications/unsubscribe-auth/ACDNYJVA5E6SXFCN6LAIUITSEZVBHANCNFSM4QZMGFKQ
.

Я все еще испытываю этот сбой в 6.0.0+4 , поскольку пакет конфликтует с запросом другого обработчика разрешений. Согласно приведенному здесь объяснению, это имеет смысл. Как вы думаете, можно ли добавить параметр вручную, чтобы отключить автоматическое разрешение разрешений методов?
Спасибо!

Привет, @xJon , не могли бы вы предоставить трассировку стека или запись в журнал, показывающую

Мы видели аналогичные проблемы с другими плагинами, которые не обрабатывают обратный вызов Android onRequestPermissionResult правильно. Я думаю, что это может быть проблемой здесь, но я хотел бы исследовать и посмотреть, могу ли я помочь.

Привет @mvanbeusekom , да, это мой журнал:

    java.lang.RuntimeException: Failure delivering result ResultInfo{who=<strong i="7">@android</strong>:requestPermissions:, request=109, result=-1, data=Intent { act=android.content.pm.action.REQUEST_PERMISSIONS (has extras) }} to activity {com.gather/com.gather.MainActivity}: java.lang.IllegalStateException: Reply already submitted
        at android.app.ActivityThread.deliverResults(ActivityThread.java:3699)
        at android.app.ActivityThread.handleSendResult(ActivityThread.java:3742)
        at android.app.ActivityThread.-wrap16(ActivityThread.java)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1393)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:148)
        at android.app.ActivityThread.main(ActivityThread.java:5417)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
     Caused by: java.lang.IllegalStateException: Reply already submitted
        at io.flutter.embedding.engine.dart.DartMessenger$Reply.reply(DartMessenger.java:139)
        at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler$1.error(MethodChannel.java:240)
        at com.baseflow.geolocator.MethodCallHandlerImpl.lambda$onGetLastKnownPosition$3(MethodCallHandlerImpl.java:150)
        at com.baseflow.geolocator.-$$Lambda$MethodCallHandlerImpl$OCefduhIkqAV59oMDlIQqmk7z8g.onError(lambda)
        at com.baseflow.geolocator.location.GeolocationManager.lambda$handlePermissions$2(GeolocationManager.java:128)
        at com.baseflow.geolocator.location.-$$Lambda$GeolocationManager$boCQNh-1HzLRO8yyNdeq6cg70Yc.onResult(lambda)
        at com.baseflow.geolocator.permission.PermissionManager.onRequestPermissionsResult(PermissionManager.java:161)
        at io.flutter.embedding.engine.FlutterEnginePluginRegistry$FlutterEngineActivityPluginBinding.onRequestPermissionsResult(FlutterEnginePluginRegistry.java:664)
        at io.flutter.embedding.engine.FlutterEnginePluginRegistry.onRequestPermissionsResult(FlutterEnginePluginRegistry.java:364)
        at io.flutter.embedding.android.FlutterActivityAndFragmentDelegate.onRequestPermissionsResult(FlutterActivityAndFragmentDelegate.java:573)
        at io.flutter.embedding.android.FlutterActivity.onRequestPermissionsResult(FlutterActivity.java:602)
        at android.app.Activity.dispatchRequestPermissionsResult(Activity.java:6553)
        at android.app.Activity.dispatchActivityResult(Activity.java:6432)
        at android.app.ActivityThread.deliverResults(ActivityThread.java:3695)
        at android.app.ActivityThread.handleSendResult(ActivityThread.java:3742) 
        at android.app.ActivityThread.-wrap16(ActivityThread.java) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1393) 
        at android.os.Handler.dispatchMessage(Handler.java:102) 
        at android.os.Looper.loop(Looper.java:148) 
        at android.app.ActivityThread.main(ActivityThread.java:5417) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 

Я убедился, что использую последнюю версию пакета.
Другой пакет, который я использую, - permission_handler .

Это странно, потому что я не могу воспроизводить эту проблему постоянно; Я повторно добавил код, который, казалось, вызвал проблему, и у меня не происходит сбоя.
Я также хотел бы отметить, что наличие функции отключения автоматического разрешения разрешений было бы полезно для приложений, которые предпочитают запрашивать определенные разрешения при первой загрузке / на экране-заставке или при вызове getCurrentPosition() а затем getLastKnownPosition() (который в противном случае отправил бы 2 отдельных запроса на разрешение).

Нет необходимости отключать автоматическое разрешение разрешений, поскольку геолокатор сначала проверит, были ли предоставлены / отключены разрешения, прежде чем предпринимать какие-либо действия и запрашивать разрешение. Это означает, что если вы уже позаботились об обработке разрешений, геолокатор просто пропустит разрешение разрешений.

Может быть, вы использовали старую версию плагина геолокатора и повторно добавляли код, чтобы убедиться, что вы обновились до последней версии геолокатора? Может быть, вы запустили flutter pub upgrade между ними?

Я мог бы поклясться, что заранее запустил flutter pub upgrade , но, возможно, я этого не сделал. Я сообщу вам, если проблема возникнет снова.

Я не совсем понимаю, что вы имеете в виду под автоматическим разрешением разрешений, так как в настоящее время, если пользователь отклоняет мой первый запрос при запуске приложения (с использованием пакета permission_handler ), он получит другой запрос, когда getCurrentPosition() запускается и еще один, когда запускается getLastKnownPosition() (при условии, что они все их отвергают).

@xJon Он имеет в виду, что если у пользователя есть «всегда разрешенные» разрешения или «отказано (не спрашивайте меня снова)», плагин не будет делать запрос к Android для отображения диалогового окна разрешений.

Причина, по которой ваш пользователь получает запрос, вероятно, заключается в том, что он временно разрешил или запретил свое разрешение (или «только один раз»).

@ianendboss Понятно . Спасибо вам за разъяснение!

Была ли эта страница полезной?
0 / 5 - 0 рейтинги

Смежные вопросы

BigWillieStyle picture BigWillieStyle  ·  6Комментарии

shrishti08 picture shrishti08  ·  3Комментарии

jaumard picture jaumard  ·  3Комментарии

deisold picture deisold  ·  3Комментарии

DineshKachhot picture DineshKachhot  ·  7Комментарии