flutter / flutter

Flutter makes it easy and fast to build beautiful apps for mobile and beyond
https://flutter.dev
BSD 3-Clause "New" or "Revised" License
164.3k stars 27.11k forks source link

java.lang.IllegalStateException: Reply already submitted with simultaneous method calls #29092

Closed crazecoder closed 2 years ago

crazecoder commented 5 years ago

Steps to Reproduce

flutter

Future<Null> avoid() async {
    await _channel.invokeMethod('a', map);
}
Future<Null> bvoid() async {
    await _channel.invokeMethod('b', map);
}

android

@Override
    public void onMethodCall(final MethodCall call, final Result result) {
        if (call.method.equals("a")) {
             result.success("result a");
        } else if(call.method.equals("b")) {
             result.success("result b");
        } else {
             result.notImplemented();
        }
    }

example

avoid();
bvoid();

Logs

 java.lang.IllegalStateException: Reply already submitted
        at io.flutter.view.FlutterNativeView$PlatformMessageHandlerImpl$1.reply(FlutterNativeView.java:197)
        at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler$1.success(MethodChannel.java:204)

An error is reported when two methods are executed at the same time

dnfield commented 5 years ago

I suspect this isn't just an issue on Android, but tagging it Android since it's reported for Android.

I'm not sure if we can easily support this use case, but maybe @mklim or @bkonyi have better ideas.

devxpy commented 5 years ago

@dnfield May I suggest something?

Can we just catch this, suppress it, and just print a message in the logs, instead of crashing the whole app?

In my experience, most often than not, it's a stupid callback that gets called multiple times, which in turn results in result.success being called multiple times, and crashing the whole app, when in reality the desired result was already sent back to flutter the first time around :/

dnfield commented 5 years ago

I suspect we actually need some kind of identifier to go with the request and response here, or perhaps a counter. Swallowing this seems like it could cause difficult to diagnose problems.

neiljaywarner commented 5 years ago

Is it odd that I am getting this in release mode and I wasn't getting it in debug mode? does that mean it's like a race condition...

dnfield commented 5 years ago

It is likely a race condition, but it could also mean there's a bug that's AOT vs JIT specific.

neiljaywarner commented 5 years ago

It is likely a race condition, but it could also mean there's a bug that's AOT vs JIT specific.

Any thoughts on how to determine which it is if i have time? I'm going to open another ticket for it because it is not quite the same...

see https://github.com/flutter/flutter/issues/29092

SAGARSURI commented 5 years ago

I am trying to build a messaging app. I am using method channels to send and receive messages. First time when I receive a message its working perfectly i.e passing the message from android to Flutter view using the MethodChannel. But the second it crashes resulting:

java.lang.IllegalStateException: Reply already submitted

Here is my android code:

call.method == "receiveMessage" -> receiveMessage(result)

private fun receiveMessage(result: MethodChannel.Result){
        val listenerID="com.sagar.gossip.MainActivity"

        MyChat.addMessageListener(listenerID, object : MyChat.MessageListener() {
            override fun onTextMessageReceived(p0: TextMessage?) {
                Log.d(TAG, "Message received successfully: " + p0?.toString())
                result.success(p0?.text)
            }
        })
    }

My Flutter code:

Future<String> receiveMessage() async {
    String message = '';
    try{
      message = await platform.invokeMethod('receiveMessage');
    } on PlatformException catch(e){
      message = e.message;
    }
    return message;
  }
devxpy commented 5 years ago

As a temporary fix, I've released a flutter plugin that tries to ingest this error.

The exception is muted here.

seyidnaali commented 5 years ago

I want to use the Authentication Registration feature with a Google Account, but when the function (_singInWithGoogle) is called, the application stops and displays the following error. ERROR

E/AndroidRuntime(11262): FATAL EXCEPTION: main 
E/AndroidRuntime(11262): Process: com.hayriyad.erpstage, PID: 11262 
E/AndroidRuntime(11262): java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=53293, result=0, data=null} to activity {com.hayriyad.erpstage/com.hayriyad.erpstage.MainActivity}: java.lang.IllegalStateException: Reply already submitted E/AndroidRuntime(11262): at android.app.ActivityThread.deliverResults(ActivityThread.java:4360)
E/AndroidRuntime(11262): at android.app.ActivityThread.handleSendResult(ActivityThread.java:4402) E/AndroidRuntime(11262): at android.app.servertransaction.ActivityResultItem.execute(ActivityResultItem.java:49) 

i use this fonction


void _signInWithGoogle() async {
    final GoogleSignInAccount googleUser = await _googleSignIn.signIn();
    final GoogleSignInAuthentication googleAuth =
    await googleUser.authentication;
    final AuthCredential credential = GoogleAuthProvider.getCredential(
      accessToken: googleAuth.accessToken,
      idToken: googleAuth.idToken,

    );
    final FirebaseUser user = await _auth.signInWithCredential(credential);
    assert(user.email != null );
    assert(user.displayName != null);
    assert(!user.isAnonymous);
    assert(await user.getIdToken() != null);

    final FirebaseUser currentUser = await _auth.currentUser();
    assert(user.uid == currentUser.uid);
    setState(() {
      if (user != null) {
        _success = true;
        _userID = user.uid;
      } else {
        _success = false;
      }
    });
  }```
devxpy commented 5 years ago

Does a similar issue exist on ios?

Karlheinzniebuhr commented 5 years ago

same issue

D/AndroidRuntime(30555): Shutting down VM E/AndroidRuntime(30555): FATAL EXCEPTION: main E/AndroidRuntime(30555): Process: com.example.TODOer, PID: 30555 E/AndroidRuntime(30555): java.lang.IllegalStateException: Reply already submitted E/AndroidRuntime(30555): at io.flutter.embedding.engine.dart.DartMessenger$Reply.reply(DartMessenger.java:124) E/AndroidRuntime(30555): at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler$1.success(MethodChannel.java:204) E/AndroidRuntime(30555): at com.lyokone.location.LocationPlugin$2.onLocationResult(LocationPlugin.java:281) E/AndroidRuntime(30555): at com.google.android.gms.internal.location.zzau.notifyListener(Unknown Source:4) E/AndroidRuntime(30555): at com.google.android.gms.common.api.internal.ListenerHolder.notifyListenerInternal(Unknown Source:17) E/AndroidRuntime(30555): at com.google.android.gms.common.api.internal.ListenerHolder$zaa.handleMessage(Unknown Source:5) E/AndroidRuntime(30555): at android.os.Handler.dispatchMessage(Handler.java:105) E/AndroidRuntime(30555): at android.os.Looper.loop(Looper.java:164) E/AndroidRuntime(30555): at android.app.ActivityThread.main(ActivityThread.java:6944) E/AndroidRuntime(30555): at java.lang.reflect.Method.invoke(Native Method) E/AndroidRuntime(30555): at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327) E/AndroidRuntime(30555): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374) I/zygote64(30555): Background concurrent copying GC freed 11907(1065KB) AllocSpace objects, 0(0B) LOS objects, 65% free, 815KB/2MB, paused 11.645ms total 46.643ms

jaceshim commented 5 years ago

same issue

E/AndroidRuntime(19943): FATAL EXCEPTION: main E/AndroidRuntime(19943): Process: nomad9.unsego.user, PID: 19943 E/AndroidRuntime(19943): java.lang.IllegalStateException: Reply already submitted E/AndroidRuntime(19943): at io.flutter.embedding.engine.dart.DartMessenger$Reply.reply(DartMessenger.java:126) E/AndroidRuntime(19943): at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler$1.success(MethodChannel.java:225) E/AndroidRuntime(19943): at nomad9.unsego.user.MainActivity$3.onSuccess(MainActivity.java:199) E/AndroidRuntime(19943): at nomad9.unsego.user.MainActivity$3.onSuccess(MainActivity.java:142) E/AndroidRuntime(19943): at com.kakao.network.callback.ResponseCallback.onSuccessForUiThread(ResponseCallback.java:76) E/AndroidRuntime(19943): at com.kakao.network.tasks.KakaoResultTask$1$1.run(KakaoResultTask.java:78) E/AndroidRuntime(19943): at android.os.Handler.handleCallback(Handler.java:873) E/AndroidRuntime(19943): at android.os.Handler.dispatchMessage(Handler.java:99) E/AndroidRuntime(19943): at android.os.Looper.loop(Looper.java:214) E/AndroidRuntime(19943): at android.app.ActivityThread.main(ActivityThread.java:7045) E/AndroidRuntime(19943): at java.lang.reflect.Method.invoke(Native Method) E/AndroidRuntime(19943): at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493) E/AndroidRuntime(19943): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:965) I/Process (19943): Sending signal. PID: 19943 SIG: 9


❯ flutter doctor Doctor summary (to see all details, run flutter doctor -v): [✓] Flutter (Channel unknown, v1.7.4, on Mac OS X 10.14.5 18F132, locale en-KR)

[✓] Android toolchain - develop for Android devices (Android SDK version 28.0.3) [✓] Xcode - develop for iOS and macOS (Xcode 10.2.1) [✓] iOS tools - develop for iOS devices [✓] Android Studio (version 3.3) [✓] IntelliJ IDEA Ultimate Edition (version 2018.3.2) [✓] VS Code (version 1.35.1) [✓] Connected device (1 available)

• No issues found!


bradyt commented 5 years ago

Same.

E/MethodChannel#cone.tangential.info/uri( 4515): Failed to handle method call
E/MethodChannel#cone.tangential.info/uri( 4515): java.lang.IllegalStateException: Reply already submitted
E/MethodChannel#cone.tangential.info/uri( 4515):    at io.flutter.embedding.engine.dart.DartMessenger$Reply.reply(DartMessenger.java:124)
E/MethodChannel#cone.tangential.info/uri( 4515):    at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler$1.error(MethodChannel.java:209)
E/MethodChannel#cone.tangential.info/uri( 4515):    at info.tangential.cone.MainActivity.isUriOpenable(MainActivity.java:144)
E/MethodChannel#cone.tangential.info/uri( 4515):    at info.tangential.cone.MainActivity.access$000(MainActivity.java:35)
E/MethodChannel#cone.tangential.info/uri( 4515):    at info.tangential.cone.MainActivity$1.onMethodCall(MainActivity.java:57)
E/MethodChannel#cone.tangential.info/uri( 4515):    at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.onMessage(MethodChannel.java:201)
E/MethodChannel#cone.tangential.info/uri( 4515):    at io.flutter.embedding.engine.dart.DartMessenger.handleMessageFromDart(DartMessenger.java:88)
E/MethodChannel#cone.tangential.info/uri( 4515):    at io.flutter.embedding.engine.FlutterJNI.handlePlatformMessage(FlutterJNI.java:219)
E/MethodChannel#cone.tangential.info/uri( 4515):    at android.os.MessageQueue.nativePollOnce(Native Method)
E/MethodChannel#cone.tangential.info/uri( 4515):    at android.os.MessageQueue.next(MessageQueue.java:323)
E/MethodChannel#cone.tangential.info/uri( 4515):    at android.os.Looper.loop(Looper.java:136)
E/MethodChannel#cone.tangential.info/uri( 4515):    at android.app.ActivityThread.main(ActivityThread.java:6186)
E/MethodChannel#cone.tangential.info/uri( 4515):    at java.lang.reflect.Method.invoke(Native Method)
E/MethodChannel#cone.tangential.info/uri( 4515):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:889)
E/MethodChannel#cone.tangential.info/uri( 4515):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:779)
bradyt commented 5 years ago

I believe my issue was resolved by making sure I use try catch finally properly to close my Java InputStream.

moonljt521 commented 5 years ago

我也遇到了这个问题,是因为在android端用MethodChannel.Result 回调的时候,在switch case 语句里,丢失了break语句,大概是多次Result多次调用引起的崩溃,我补上了break,这个问题便被解决了

moonljt521 commented 5 years ago

I also encountered this problem when callbacked on the android side using the Method Channel Result.It is because that the “break statement” is lost in the switch case statement.It probably that the multiple “Results”and multiple “Calls” caused the crash. I made up the “break”, then the problem was solved.

jigarpatel17 commented 5 years ago

@moonljt521 Can you please share more details, or probably, code snippet will also helpful. Thanks

bradyt commented 5 years ago

I believe my issue was resolved by making sure I use try catch finally properly to close my Java InputStream.

Oh, I made a similar mistake again during a refactor. Glad I found this. Really need to make sure my code does not try to return a result twice.

FangWW commented 5 years ago

Avoid multiple calls to a "result".

PolashPaul2367 commented 4 years ago

same issue

E/AndroidRuntime(19977): Caused by: java.lang.IllegalStateException: Reply already submitted E/AndroidRuntime(19977): at io.flutter.embedding.engine.dart.DartMessenger$Reply.reply(DartMessenger.java:151) E/AndroidRuntime(19977): at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler$1.success(MethodChannel.java:225) E/AndroidRuntime(19977): at vn.hunghd.flutter.plugins.imagecropper.ImageCropperDelegate.onActivityResult(ImageCropperDelegate.java:106) E/AndroidRuntime(19977): at io.flutter.app.FlutterPluginRegistry.onActivityResult(FlutterPluginRegistry.java:204) E/AndroidRuntime(19977): at io.flutter.app.FlutterActivityDelegate.onActivityResult(FlutterActivityDelegate.java:132) E/AndroidRuntime(19977): at io.flutter.app.FlutterActivity.onActivityResult(FlutterActivity.java:142) E/AndroidRuntime(19977): at android.app.Activity.dispatchActivityResult(Activity.java:8924) E/AndroidRuntime(19977): at android.app.ActivityThread.deliverResults(ActivityThread.java:4422) E/AndroidRuntime(19977): ... 11 more

longravuth commented 4 years ago

For anyone who is facing this issue because you are calling result.success() or result.error() from a native callback function, i found the solution. Implement your request handler like in CameraRequestPermissionsListener class in https://github.com/flutter/plugins/blob/master/packages/camera/android/src/main/java/io/flutter/plugins/camera/CameraPermissions.java

then when you receive the callback in your methodhandler class, simple set result = null after you call result.success or result.failure to reset its state like processResult() method in https://github.com/BaseflowIT/flutter-permission-handler/blob/develop/android/src/main/java/com/baseflow/permissionhandler/PermissionHandlerPlugin.java

:<

103style commented 4 years ago

if you call result.success() or result.xxx() twice, you will get this problem!

public class MainActivity extends FlutterActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        GeneratedPluginRegistrant.registerWith(this);

        new MethodChannel(getFlutterView(), CHANNEL)
                .setMethodCallHandler(
                        (methodCall, result) -> {
                            if (methodCall.method.equals(METHOD_NAME)) {
                                int batteryLevel = 0;
                                result.success(batteryLevel);
                               // result.success(batteryLevel);   
                               // if you call result.success() or result.xxx()  twice,  you will get this problem!   

                            } else {
                                result.notImplemented();
                            }
                        });
    }
}
hatemragab commented 4 years ago

Yes

On Mon, Nov 11, 2019, 8:45 AM luoxiaoke notifications@github.com wrote:

if you call result.success() or result.xxx() twice, you will get this problem!

public class MainActivity extends FlutterActivity {

@Override

protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    GeneratedPluginRegistrant.registerWith(this);

    new MethodChannel(getFlutterView(), CHANNEL)

            .setMethodCallHandler(

                    (methodCall, result) -> {

                        if (methodCall.method.equals(METHOD_NAME)) {

                            int batteryLevel = 0;

                            result.success(batteryLevel);

                           // result.success(batteryLevel);

                           // if you call result.success() or result.xxx()  twice,  you will get this problem!

                        } else {

                            result.notImplemented();

                        }

                    });

}

}

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/flutter/flutter/issues/29092?email_source=notifications&email_token=AI5HEQMOY3D7D5LHXCW4I5DQTD5P3A5CNFSM4G42HD42YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEDV2M7I#issuecomment-552314493, or unsubscribe https://github.com/notifications/unsubscribe-auth/AI5HEQN5QS35VDP5BPXSLITQTD5P3ANCNFSM4G42HD4Q .

naveenkumardot25 commented 4 years ago

Hey, guys, I solved Reply already submitted problem by adding a break to my switch statement like a return for if-else statement.

DhavalRKansara commented 4 years ago

Yeah guys, I found the solution for this check if you call result.success() twice from native, you will get this problem!

tabarakMohammed commented 4 years ago

if (registrar.activity() == null) { // If a background flutter view tries to register the plugin, there will be no activity from the registrar, // we stop the registering process immediately because requires an activity. return; }

OmkarSsawant commented 4 years ago

I am trying to build a messaging app. I am using method channels to send and receive messages. First time when I receive a message its working perfectly i.e passing the message from android to Flutter view using the MethodChannel. But the second it crashes resulting:

java.lang.IllegalStateException: Reply already submitted

Here is my android code:

call.method == "receiveMessage" -> receiveMessage(result)

private fun receiveMessage(result: MethodChannel.Result){
        val listenerID="com.sagar.gossip.MainActivity"

        MyChat.addMessageListener(listenerID, object : MyChat.MessageListener() {
            override fun onTextMessageReceived(p0: TextMessage?) {
                Log.d(TAG, "Message received successfully: " + p0?.toString())
                result.success(p0?.text)
            }
        })
    }

My Flutter code:

Future<String> receiveMessage() async {
    String message = '';
    try{
      message = await platform.invokeMethod('receiveMessage');
    } on PlatformException catch(e){
      message = e.message;
    }
    return message;
  }

Getting same error

efreibe commented 4 years ago

@OmkarSsawant. Because you are calling addMessageListener every time you execute receiveMessage, you ended calling result.success multiple times. That is why you have this error. Try to add the listener one time only.

OmkarSsawant commented 4 years ago

@OmkarSsawant. Because you are calling addMessageListener every time you execute receiveMessage, you ended calling result.success multiple times. That is why you have this error. Try to add the listener one time only

But In my case I am replying the message in onActivityResultListner in which it occurs only once .when i try to submit result my app crashes with error result already submitted . When actually i have not submitted it

Kelier commented 4 years ago

So what should I do if I want to call the plugin multiple times and return different values?

efreibe commented 4 years ago

@OmkarSsawant Yes. But you are adding a listener every time you call the plugin, so, the first time it fires ok, the second call it fires twice, the third call it fires three times and so on. Try removing the listener before sending the result back.

@Kelier MethodChannel allows you to make one call and receive one result at a time. You can call it any number of times and wil receive a result every time it was called. If you want to receive multiple results, like events, then you will need to implement an EventChannel. See https://api.flutter.dev/flutter/services/EventChannel-class.html

OmkarSsawant commented 4 years ago
The `_result` is just assisgned in onmethodcall method
@Override
    public boolean onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == REQUEST_CODE) {

            AuthorizationResponse response = AuthorizationClient.getResponse(resultCode, data);
            if (response.getType() == TOKEN) {
                // Handle successful response
                final String accessToken = response.getAccessToken();
              _result.success( accessToken);

                return false;
            } else if (response.getType() == ERROR) {
               _result.error("",responce.getError(),null);

                return false;
            }
        }
        return false;
    }

I get same error

efreibe commented 4 years ago

Could be related to this issue #48202?

anakin-jin commented 4 years ago

it's weird. following code (in android side) will cause the same problem:

@Override
  public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
    if (call.method.equals("getPlatformVersion")) {
      result.success("Android " + android.os.Build.VERSION.RELEASE);
    }
    if (call.method.equals("getDHKeys")) {
      result.success( getDHPGK() );
    }
    else {
      result.notImplemented();
    }
  }

after adding a word 'else' before second 'if' sentence. the problem fixed.

 @Override
  public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
    if (call.method.equals("getPlatformVersion")) {
      result.success("Android " + android.os.Build.VERSION.RELEASE);
    }
    else if (call.method.equals("getDHKeys")) {//!!!! here! added a word 'else'!!!!
      result.success( getDHPGK() );
    }
    else {
      result.notImplemented();
    }
  }

the flutter side code:

      platformVersion = await Libblufi.platformVersion;
      print("ver:$platformVersion");
xster commented 4 years ago

Seems like a pretty annoying problem. @gaaclarke can you take a look to see if there are concurrency problems with our platform channel implementation?

gaaclarke commented 4 years ago

@crazecoder @xster This works for me. Here is an example app that does it. Here is the double calls. I tested it on:

[✓] Flutter (Channel unknown, 1.18.0-14.0.pre.3, on Mac OS X 10.15.4 19E287, locale en-US)
    • Flutter version 1.18.0-14.0.pre.3 at /Users/aaclarke/dev/flutter
    • Framework revision e6b697a9df (5 days ago), 2020-05-07 11:03:05 -0700
    • Engine revision d6aa099de7
    • Dart version 2.9.0 (build 2.9.0-5.0.dev 4da5b40fb6)

I suspect there is extra steps required to reproduce this issue that aren't enumerated in the issue description. Feel free to use my code as an example of what you want to do. Let me know if you think there is something I missed.

edit: I saw somewhere there was speculation that this could be related to release builds so I made sure to test on release builds and debug builds, same results.

IkhwanSI13 commented 4 years ago

So this error happened when you use native code like Java right? In my case, I didn't type a single code like result.success or another result. I just type native code for Firebase Cloud Messaging. Maybe this error comes from the packages that I used? So how to solve this? Btw, I get this error from Firebase Crashlytics

gaaclarke commented 4 years ago

@IkhwanSI13 if you are getting the error and you aren't implementing method channels I'd audit the plugin's code to see if they are doing something like https://github.com/flutter/flutter/issues/29092#issuecomment-619784521

yeahia2508 commented 3 years ago

Still getting this issue. any solution?

bhanuka96 commented 3 years ago

any solution.

I used the google_maps_flutter. I got GPS service to enable message from the device. and I clicked the No Thanks button. And I have another alert display by me. I click the button(pop event- just remove alert). Then the app crash. every time I process this way, the app is crashed.

D/ViewRootImpl@f495d82[MainActivity](30172): Relayout returned: old=[0,0][1080,1920] new=[0,0][1080,1920] result=0x3 surface={valid=true 490758094848} changed=false
D/ViewRootImpl@245c40[MainActivity](30172): MSG_WINDOW_FOCUS_CHANGED 1
D/AndroidRuntime(30172): Shutting down VM
E/AndroidRuntime(30172): FATAL EXCEPTION: main
E/AndroidRuntime(30172): Process: myapp.prod, PID: 30172
E/AndroidRuntime(30172): java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=1, result=0, data=Intent { (has extras) }} to activity {myapp.prod/myapp.MainActivity}: java.lang.IllegalStateException: Reply already submitted
E/AndroidRuntime(30172):    at android.app.ActivityThread.deliverResults(ActivityThread.java:4491)
E/AndroidRuntime(30172):    at android.app.ActivityThread.handleSendResult(ActivityThread.java:4534)
E/AndroidRuntime(30172):    at android.app.ActivityThread.-wrap20(Unknown Source:0)
E/AndroidRuntime(30172):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1752)
E/AndroidRuntime(30172):    at android.os.Handler.dispatchMessage(Handler.java:105)
E/AndroidRuntime(30172):    at android.os.Looper.loop(Looper.java:164)
E/AndroidRuntime(30172):    at android.app.ActivityThread.main(ActivityThread.java:6942)
E/AndroidRuntime(30172):    at java.lang.reflect.Method.invoke(Native Method)
E/AndroidRuntime(30172):    at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327)
E/AndroidRuntime(30172):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)
E/AndroidRuntime(30172): Caused by: java.lang.IllegalStateException: Reply already submitted
E/AndroidRuntime(30172):    at io.flutter.embedding.engine.dart.DartMessenger$Reply.reply(DartMessenger.java:139)
E/AndroidRuntime(30172):    at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler$1.error(MethodChannel.java:240)
E/AndroidRuntime(30172):    at com.lyokone.location.FlutterLocation.onActivityResult(FlutterLocation.java:173)
E/AndroidRuntime(30172):    at io.flutter.embedding.engine.FlutterEnginePluginRegistry$FlutterEngineActivityPluginBinding.onActivityResult(FlutterEnginePluginRegistry.java:691)
E/AndroidRuntime(30172):    at io.flutter.embedding.engine.FlutterEnginePluginRegistry.onActivityResult(FlutterEnginePluginRegistry.java:378)
E/AndroidRuntime(30172):    at io.flutter.embedding.android.FlutterActivityAndFragmentDelegate.onActivityResult(FlutterActivityAndFragmentDelegate.java:619)
E/AndroidRuntime(30172):    at io.flutter.embedding.android.FlutterActivity.onActivityResult(FlutterActivity.java:584)
E/AndroidRuntime(30172):    at android.app.Activity.dispatchActivityResult(Activity.java:7556)
E/AndroidRuntime(30172):    at android.app.ActivityThread.deliverResults(ActivityThread.java:4487)
E/AndroidRuntime(30172):    ... 9 more
I/System.out(30172): (HTTPLog)-Static: isSBSettingEnabled false
I/System.out(30172): (HTTPLog)-Static: isSBSettingEnabled false
Lost connection to device.
msarkrish commented 3 years ago

Any Update on this? I'm also facing this problem. I'm using Native code encrypting and decrypting the file. In particular screen I decrypt all the encrypted files and displayed to the User. If i'm showing 1 file then it works fine. If i have more than 1 file then app will crash as Reply already submitted. I want to call the native method continuously in that screen. How to solve this?

AmandaOlearczuk commented 3 years ago

Any Update on this? I'm also facing this problem. I'm using Native code encrypting and decrypting the file. In particular screen I decrypt all the encrypted files and displayed to the User. If i'm showing 1 file then it works fine. If i have more than 1 file then app will crash as Reply already submitted. I want to call the native method continuously in that screen. How to solve this?

I also would like to call native method (from a plugin) continuously and Im getting Reply already submitted..

hamdikahloun commented 3 years ago

I'm not able to reproduce the issue.

Hi @msarkrish @AmandaOlearczuk

Can you please provide your flutter doctor -v, your flutter run --verbose and a minimal complete reproducible code sample?

Native code ``` public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) { if (call.method.equals("getPlatformVersion")) { result.success(android.os.Build.VERSION.RELEASE); } else if (call.method.equals("getCurrentTime")) { result.success("00:00"); } else { result.notImplemented(); } } ```
Dart code ``` static const MethodChannel _channel = const MethodChannel('mychannel'); static Future get platformVersion async { await _channel.invokeMethod('getPlatformVersion'); } static Future get currentTime async { await _channel.invokeMethod('getCurrentTime'); } static void get callTwoMethods { currentTime; platformVersion; } ```
flutter doctor -v ``` [√] Flutter (Channel stable, 1.22.2, on Microsoft Windows [version 10.0.19041.572], locale fr-FR) • Flutter version 1.22.2 at D:\fork\flutter • Framework revision 84f3d28555 (2 weeks ago), 2020-10-15 16:26:19 -0700 • Engine revision b8752bbfff • Dart version 2.10.2 [√] Android toolchain - develop for Android devices (Android SDK version 30.0.2) • Android SDK at C:\Users\hamdi\AppData\Local\Android\Sdk • Platform android-30, build-tools 30.0.2 • ANDROID_HOME = C:\Users\hamdi\AppData\Local\Android\Sdk • Java binary at: C:\Program Files\Android\Android Studio\jre\bin\java • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b01) • All Android licenses accepted. [!] Android Studio (version 4.1.0) • Android Studio at C:\Program Files\Android\Android Studio X Flutter plugin not installed; this adds Flutter specific functionality. X Dart plugin not installed; this adds Dart specific functionality. • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b01) [√] VS Code (version 1.50.1) • VS Code at C:\Users\hamdi\AppData\Local\Programs\Microsoft VS Code • Flutter extension version 3.15.1 [√] Connected device (1 available) • STK L21 (mobile) • XMJ4C19B09007407 • android-arm64 • Android 10 (API 29) ! Doctor found issues in 1 category. ```

Thank you

volgin commented 3 years ago

Same error with a different plugin (AudioFilePlayer):

E/AndroidRuntime(18077): java.lang.IllegalStateException: Reply already submitted
E/AndroidRuntime(18077):    at io.flutter.embedding.engine.dart.DartMessenger$Reply.reply(DartMessenger.java:139)
E/AndroidRuntime(18077):    at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler$1.error(MethodChannel.java:243)
E/AndroidRuntime(18077):    at com.google.flutter.plugins.audiofileplayer.AudiofileplayerPlugin.lambda$onLoad$1$AudiofileplayerPlugin(AudiofileplayerPlugin.java:377)
E/AndroidRuntime(18077):    at com.google.flutter.plugins.audiofileplayer.-$$Lambda$AudiofileplayerPlugin$A6LKsuboaeEM7gfQPisQG3fhlSg.onRemoteLoadComplete(Unknown Source:11)
E/AndroidRuntime(18077):    at com.google.flutter.plugins.audiofileplayer.RemoteManagedMediaPlayer.onError(RemoteManagedMediaPlayer.java:116)
E/AndroidRuntime(18077):    at android.media.MediaPlayer$EventHandler.handleMessage(MediaPlayer.java:3440)
E/AndroidRuntime(18077):    at android.os.Handler.dispatchMessage(Handler.java:107)
E/AndroidRuntime(18077):    at android.os.Looper.loop(Looper.java:214)
E/AndroidRuntime(18077):    at android.app.ActivityThread.main(ActivityThread.java:7356)
E/AndroidRuntime(18077):    at java.lang.reflect.Method.invoke(Native Method)
E/AndroidRuntime(18077):    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
E/AndroidRuntime(18077):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
hamdikahloun commented 3 years ago

Hi @volgin @bhanuka96

From what I can see, the issue is related to a audiofileplayer and FlutterLocation plugin rather than to Flutter itself .

E/AndroidRuntime(18077):    at com.google.flutter.plugins.audiofileplayer.AudiofileplayerPlugin.lambda$onLoad$1$AudiofileplayerPlugin(AudiofileplayerPlugin.java:377)
E/AndroidRuntime(18077):    at com.google.flutter.plugins.audiofileplayer.-$$Lambda$AudiofileplayerPlugin$A6LKsuboaeEM7gfQPisQG3fhlSg.onRemoteLoadComplete(Unknown Source:11)
E/AndroidRuntime(18077):    at com.google.flutter.plugins.audiofileplayer.RemoteManagedMediaPlayer.onError(RemoteManagedMediaPlayer.java:116)

E/AndroidRuntime(30172): at com.lyokone.location.FlutterLocation.onActivityResult(FlutterLocation.java:173)

Thank you

volgin commented 3 years ago

@hamdikahloun

Of course :), and I was able to resolve it. The point is that this exception should not crash the entire app. If someone runs into this problem in any plugin, they may not be able to figure out what happens unless they catch it in their IDE - app crashing means that it cannot report this exception back to its developers.

nateshmbhat commented 3 years ago

any solution for this problem ? i actually have a use case which needs to make simultaneous method channel calls and fetch different results for corresponding calls.

xster commented 3 years ago

Seems like we were never able to reproduce it https://github.com/flutter/flutter/issues/29092#issuecomment-627627863.

If anyone has a reduced reproduction project, we could take a look.

adamshamsudeen commented 3 years ago

@bhanuka96 Were you able to solve the issue?

khiromoshito commented 3 years ago

Hi.

I've arrived with this issue already, and fortunately I think I have found a solution for this. I actually assumed that maybe there are duplication in the success method of the MethodChannel.Result, and it could be the reason for the "already submitted" issue.

What I did was make a class that handles my requests instead of directly calling the success method. Inside this class is a boolean flag that checks if the channel already submitted before. The code looks like this:


class FlutterRequest {
    boolean hasSubmitted = false;
    MethodCall call;
    MethodChannel.Result submitter;

    FlutterRequest(MethodCall call, MethodChannel.Result submitter) {
        this.call = call;
        this.submitter = submitter;
    }

    public Object getArguments() {
        return call.arguments();
    }

    public String getMethod() {
        return call.method;
    }

    public void submit(Object message) {
        if(!this.hasSubmitted) {
            this.hasSubmitted = true;

            this.submitter.success(message);
        }
    }

    public void reportError(Object message) {
        if(!this.hasSubmitted) {
            this.hasSubmitted = true;

            this.submitter.error(message);
        }
    }

}

So, I wrapped the request with this class and did all my methods and calls with it.

final FlutterRequest myRequest = new FlutterRequest(call, result);

If ever I want to call the original success method, I would instead call myRequest.submit("message") to make sure there will be no 'agains.'

I haven't benchmarked this yet, but when I tried this code out, the errors did not show up anymore. Hope it helps :)