You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter插件Kotlin代码出现Reply already submitted异常如何解决?

Flutter PowerManager插件「Reply already submitted」异常修复

问题场景

开发Android proximity唤醒锁控制的Flutter插件时,调用方法抛出如下异常:

E/MethodChannel#powermanager(16953): Failed to handle method call
E/MethodChannel#powermanager(16953): java.lang.IllegalStateException: Reply already submitted
E/MethodChannel#powermanager(16953):    at io.flutter.embedding.engine.dart.DartMessenger$Reply.reply(DartMessenger.java:435)
E/MethodChannel#powermanager(16953):    at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler$1.notImplemented(MethodChannel.java:273)
E/MethodChannel#powermanager(16953):    at com.powermanager.powermanager.PowermanagerPlugin.onMethodCall(PowermanagerPlugin.kt:55)
E/MethodChannel#powermanager(16953):    at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.onMessage(MethodChannel.java:258)
E/MethodChannel#powermanager(16953):    at io.flutter.embedding.engine.dart.DartMessenger.invokeHandler(DartMessenger.java:295)
E/MethodChannel#powermanager(16953):    at io.flutter.embedding.engine.dart.DartMessenger.lambda$dispatchMessageToQueue$0$io-flutter-embedding-engine-dart-DartMessenger(DartMessenger.java:322)
E/MethodChannel#powermanager(16953):    at io.flutter.embedding.engine.dart.DartMessenger$$ExternalSyntheticLambda0.run(Unknown Source:12)
E/MethodChannel#powermanager(16953):    at android.os.Handler.handleCallback(Handler.java:873)
E/MethodChannel#powermanager(16953):    at android.os.Handler.dispatchMessage(Handler.java:99)
E/MethodChannel#powermanager(16953):    at android.os.Looper.loop(Looper.java:193)
E/MethodChannel#powermanager(16953):    at android.app.ActivityThread.main(ActivityThread.java:6669)
E/MethodChannel#powermanager(16953):    at java.lang.reflect.Method.invoke(Native Method)
E/MethodChannel#powermanager(16953):    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
E/MethodChannel#powermanager(16953):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)

原Kotlin插件代码

package com.powermanager.powermanager
import android.content.Context
import android.os.PowerManager
import androidx.annotation.NonNull
import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import io.flutter.plugin.common.MethodChannel.Result

/** PowermanagerPlugin */
class PowermanagerPlugin: FlutterPlugin, MethodCallHandler {
  private lateinit var applicationContext: Context
  private lateinit var channel : MethodChannel
  private lateinit var powerManager: PowerManager
  private lateinit var lock: PowerManager.WakeLock

  override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
    applicationContext = flutterPluginBinding.getApplicationContext();
    channel = MethodChannel(flutterPluginBinding.binaryMessenger, "powermanager")
    channel.setMethodCallHandler(this)
    powerManager = applicationContext.getSystemService(Context.POWER_SERVICE) as PowerManager
    if(powerManager.isWakeLockLevelSupported(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK)) {
      lock = powerManager.newWakeLock(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK,"PROXIMITYSCREENOFFWAKELOCK")
      lock.setReferenceCounted(false)
    }
  }

  override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) {
    if (call.method == "on") {
      if(powerManager.isWakeLockLevelSupported(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK)) {
        if(lock.isHeld) {
          lock.release(1)
        }
        lock.acquire()
        result.success(true)
      } else {
        result.error("notSupported", "PowerManager PROXIMITY_SCREEN_OFF_WAKE_LOCK is notSupported", null)
      }
    } else {
      result.notImplemented()
    }
    if (call.method == "off") {
      if(powerManager.isWakeLockLevelSupported(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK)) {
        if(lock.isHeld) {
          lock.release(1)
        }
        result.success(true)
      } else {
        result.error("notSupported", "PowerManager PROXIMITY_SCREEN_OFF_WAKE_LOCK is notSupported", null)
      }
    } else {
      result.notImplemented()
    }
  }

  override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {
    if(::lock.isInitialized) {
      if(lock.isHeld) {
        lock.release(1)
      }
    }
    channel.setMethodCallHandler(null)
  }
}

Dart端调用代码

_powerManager(bool makeActive) async {
      try {
        if (makeActive) {
          await Powermanager().on();
        } else {
          await Powermanager().off();
        }
      } catch (e) {
        debugPrint(e.toString());
      }
  }

@override
  void initState() {
    super.initState();
    _powerManager(true);
  }
@override
  void dispose() {
    _powerManager(false);
    super.dispose();
  }

问题原因

核心问题是onMethodCall中存在两次独立的if判断逻辑,导致单个方法调用触发两次结果回复:

  • 调用on方法时,第一个if分支执行result.success(true),随后第二个if判断不成立,又执行result.notImplemented(),造成重复回复
  • 调用off方法时,第二个if分支执行result.success(true),第一个if的else分支再次执行result.notImplemented(),同样触发重复回复

Flutter的MethodChannel要求每个方法调用只能回复一次结果,重复调用result.success/error/notImplemented就会抛出Reply already submitted异常。

修复方案

将onMethodCall中的独立if改为if-else if或Kotlinwhen表达式,确保每个方法调用只进入一个分支,仅回复一次结果:

修复后的Kotlin插件代码(使用when表达式)

package com.powermanager.powermanager
import android.content.Context
import android.os.PowerManager
import androidx.annotation.NonNull
import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import io.flutter.plugin.common.MethodChannel.Result

/** PowermanagerPlugin */
class PowermanagerPlugin: FlutterPlugin, MethodCallHandler {
  private lateinit var applicationContext: Context
  private lateinit var channel : MethodChannel
  private lateinit var powerManager: PowerManager
  private lateinit var lock: PowerManager.WakeLock

  override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
    applicationContext = flutterPluginBinding.getApplicationContext();
    channel = MethodChannel(flutterPluginBinding.binaryMessenger, "powermanager")
    channel.setMethodCallHandler(this)
    powerManager = applicationContext.getSystemService(Context.POWER_SERVICE) as PowerManager
    if(powerManager.isWakeLockLevelSupported(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK)) {
      lock = powerManager.newWakeLock(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK,"PROXIMITYSCREENOFFWAKELOCK")
      lock.setReferenceCounted(false)
    }
  }

  override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) {
    when(call.method) {
      "on" -> {
        if(powerManager.isWakeLockLevelSupported(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK)) {
          if(lock.isHeld) {
            lock.release(1)
          }
          lock.acquire()
          result.success(true)
        } else {
          result.error("notSupported", "PowerManager PROXIMITY_SCREEN_OFF_WAKE_LOCK is notSupported", null)
        }
      }
      "off" -> {
        if(powerManager.isWakeLockLevelSupported(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK)) {
          if(lock.isHeld) {
            lock.release(1)
          }
          result.success(true)
        } else {
          result.error("notSupported", "PowerManager PROXIMITY_SCREEN_OFF_WAKE_LOCK is notSupported", null)
        }
      }
      else -> result.notImplemented()
    }
  }

  override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {
    if(::lock.isInitialized) {
      if(lock.isHeld) {
        lock.release(1)
      }
    }
    channel.setMethodCallHandler(null)
  }
}

如果偏好传统if-else if结构,也可以替换为:

override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) {
  if (call.method == "on") {
    if(powerManager.isWakeLockLevelSupported(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK)) {
      if(lock.isHeld) {
        lock.release(1)
      }
      lock.acquire()
      result.success(true)
    } else {
      result.error("notSupported", "PowerManager PROXIMITY_SCREEN_OFF_WAKE_LOCK is notSupported", null)
    }
  } else if (call.method == "off") {
    if(powerManager.isWakeLockLevelSupported(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK)) {
      if(lock.isHeld) {
        lock.release(1)
      }
      result.success(true)
    } else {
      result.error("notSupported", "PowerManager PROXIMITY_SCREEN_OFF_WAKE_LOCK is notSupported", null)
    }
  } else {
    result.notImplemented()
  }
}

额外优化提示

  • 可在onAttachedToEngine中提前判断唤醒锁支持情况,避免每次方法调用重复判断
  • 若不需要返回结果,直接调用result.success(null)即可,不可省略回复步骤

内容的提问来源于stack exchange,提问作者Cenk YAGMUR

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 13:12:32