В примере приложения 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
Платформа:
@humazed спасибо за отчет об ошибке. Я как бы знаю, откуда возникает ошибка (и я могу ее устранить), но я не могу ее воспроизвести, и, судя по трассировкам стека, которые вы мне отправляете, эта ошибка не должна возникать в первую очередь.
Поэтому мне интересно, можете ли вы помочь мне выяснить, что вызывает эту проблему, чтобы я мог решить ее правильным образом. Итак, чтобы дать вам некоторые подробности, вот что, как мне кажется, происходит (на основе информации трассировки стека и шагов, которые вы описываете):
Шаг 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:
откройте приложение и посмотрите на сбой.
пришлю вам запись экрана.
запись ошибки
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
(или один из других методов позиционирования) несколько раз. Так что я могу справиться с этим тремя способами:
onRequestPermissionResults
которая игнорирует вызов, когда параметры permissions
и grantResults
пусты;getLastKnownPosition
, getCurrentPosition
и getPositionStream
только один раз, если их уже запущенный запрос;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 Понятно . Спасибо вам за разъяснение!