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

Flutter MethodChannel在Android Service的Release APK中无法工作的原因

问题

Debug模式下,从原生Android Service类调用Dart静态函数的代码运行正常,但用flutter build apk生成Release APK安装后,MethodChannel无法工作并报错。相关代码及错误日志如下,请问导致该问题的原因是什么?

Dart代码

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

const CHANNEL = "com.app/channel";

// Method channel for Android
void initializeAndroidWidgets() {
  if (Platform.isAndroid) {
    // Intialize flutter
    WidgetsFlutterBinding.ensureInitialized();

    const MethodChannel channel = MethodChannel(CHANNEL);

    final CallbackHandle callback = PluginUtilities.getCallbackHandle(rustMethodChannel)!;
    final handle = callback.toRawHandle();

    channel.invokeMethod('initialize', handle);
  }
}

void rustMethodChannel() async {
  // Initialize flutter
  WidgetsFlutterBinding.ensureInitialized();
  PreferenceRepository preferenceRepository = PreferenceRepository();
  // Create methodChannel
  const MethodChannel channel = MethodChannel(CHANNEL);
  channel.setMethodCallHandler(
            (call) async {
      final args = call.arguments;
      logDebug('on Dart ${call.method}!, args = ${args}');

      switch (call.method) {
        case 'isConnected':
          return await isConnected(preferenceRepository);
        case 'startConnect':
          var result = await startConnect(preferenceRepository);
          return result;
        case 'disconnect':
          return await disconnect();
        case 'getTestString':
          return getTestString();
        default:
          throw UnimplementedError("Unknow: ${call.method}");
      }
    },
  );
}

Android Service代码

companion object {
    private const val TAG = "MyApp";
    const val CHANNEL = "com.app/channel"

    private var channel: MethodChannel? = null;
}

private fun initializeFlutter() {
    if (channel == null) {
        try {
            FlutterMain.startInitialization(this)
            FlutterMain.ensureInitializationComplete(this, arrayOf())

            val handle = WidgetHelper.getRawHandle(this)
            if (handle == WidgetHelper.NO_HANDLE) {
                Log.e(TAG, "Couldn't update widget because there is no handle stored!")
                return
            }

            val callbackInfo = FlutterCallbackInformation.lookupCallbackInformation(handle)
            val entryPointFunctionName = callbackInfo.callbackName
            Log.e(
                TAG,
                "entryPointFunctionName = ${entryPointFunctionName}, FlutterMain.findAppBundlePath() = ${FlutterMain.findAppBundlePath()}"
            )
            // Instantiate a FlutterEngine.
            val engine = FlutterEngine(this.applicationContext)
            val entryPoint = DartExecutor.DartEntrypoint(FlutterMain.findAppBundlePath(), entryPointFunctionName)
            engine.dartExecutor.executeDartEntrypoint(entryPoint)

            GeneratedPluginRegistrant.registerWith(engine)
            channel = MethodChannel(engine.dartExecutor.binaryMessenger, CHANNEL)
        } catch (e: java.lang.Exception) {
            e.printStackTrace();
        }
    }
}

override fun onCreate() {
    super.onCreate()
    Log.e(TAG, "Starting service");
    initializeFlutter()
}

Release模式错误日志

2022-11-10 15:43:54.448 10736-10736/? E/MyApp: entryPointFunctionName = rustMethodChannel, FlutterMain.findAppBundlePath() = flutter_assets
2022-11-10 15:43:54.466 10736-10736/? W/FlutterEngineCxnRegstry: Attempted to register plugin (k1.a@1df89c) but it was already registered with this FlutterEngine (io.flutter.embedding.engine.a@32a92a5).
2022-11-10 15:43:54.466 10736-10736/? W/FlutterEngineCxnRegstry: Attempted to register plugin (u3.a@26ce67a) but it was already registered with this FlutterEngine (io.flutter.embedding.engine.a@32a92a5).
2022-11-10 15:43:54.466 10736-10736/? W/FlutterEngineCxnRegstry: Attempted to register plugin (l1.a@2f37e2b) but it was already registered with this FlutterEngine (io.flutter.embedding.engine.a@32a92a5).
2022-11-10 15:43:54.466 10736-10736/? W/FlutterEngineCxnRegstry: Attempted to register plugin (d2.c@2600288) but it was already registered with this FlutterEngine (io.flutter.embedding.engine.a@32a92a5).
2022-11-10 15:43:54.466 10736-10736/? W/FlutterEngineCxnRegstry: Attempted to register plugin (g0.m@d6b421) but it was already registered with this FlutterEngine (io.flutter.embedding.engine.a@32a92a5).
2022-11-10 15:43:54.466 10736-10736/? W/FlutterEngineCxnRegstry: Attempted to register plugin (e2.b@8d2f046) but it was already registered with this FlutterEngine (io.flutter.embedding.engine.a@32a92a5).
2022-11-10 15:43:54.466 10736-10736/? W/FlutterEngineCxnRegstry: Attempted to register plugin (f2.c@329d207) but it was already registered with this FlutterEngine (io.flutter.embedding.engine.a@32a92a5).
2022-11-10 15:43:54.466 10736-10736/? W/FlutterEngineCxnRegstry: Attempted to register plugin (f0.t@f36bf34) but it was already registered with this FlutterEngine (io.flutter.embedding.engine.a@32a92a5).
2022-11-10 15:43:54.467 10736-10736/? E/MyApp: startWakeLock
2022-11-10 15:43:54.469 10736-10736/? E/MyApp: Starting service
2022-11-10 15:43:54.469 766-774/? E/statsd: Predicate 5980654721335871649 dropping data for dimension key (10)0x2010101->10327[I] (10)0x30000->com.anv3.proxy:wakelock[S] 
2022-11-10 15:43:54.477 10736-13937/? E/flutter: [ERROR:flutter/runtime/dart_isolate.cc(668)] Could not resolve main entrypoint function.
2022-11-10 15:43:54.477 10736-13937/? E/flutter: [ERROR:flutter/runtime/dart_isolate.cc(167)] Could not run the run main Dart entrypoint.
2022-11-10 15:43:54.479 10736-13937/? E/flutter: [ERROR:flutter/runtime/runtime_controller.cc(385)] Could not create root isolate.
2022-11-10 15:43:54.479 10736-13937/? E/flutter: [ERROR:flutter/shell/common/shell.cc(604)] Could not launch engine with configuration.

问题原因

核心问题是Release模式下Dart的Tree Shaking(摇树优化)机制把rustMethodChannel函数移除了:

  • Debug模式下不会启用摇树优化,编译器会保留所有代码,所以rustMethodChannel能被正常找到并执行;
  • Release模式中,Dart编译器会扫描代码,发现rustMethodChannel没有被Dart代码直接调用,只通过Native侧的CallbackHandle引用,就会将其判定为未使用代码并剔除,导致Flutter Engine启动时找不到该入口函数,抛出Could not resolve main entrypoint function错误。

日志里的插件重复注册警告是次要问题,是Service多次初始化FlutterEngine导致的,但不是崩溃的直接原因。


解决方案

  1. 阻止摇树优化移除目标函数:在rustMethodChannel函数上添加@pragma('vm:entry-point')注解,明确告诉编译器这个函数是Native侧的入口点,不能被优化删除。修改后的函数如下:
@pragma('vm:entry-point')
void rustMethodChannel() async {
  // 原函数逻辑保持不变
  WidgetsFlutterBinding.ensureInitialized();
  PreferenceRepository preferenceRepository = PreferenceRepository();
  const MethodChannel channel = MethodChannel(CHANNEL);
  channel.setMethodCallHandler(
    (call) async {
      final args = call.arguments;
      logDebug('on Dart ${call.method}!, args = ${args}');

      switch (call.method) {
        case 'isConnected':
          return await isConnected(preferenceRepository);
        case 'startConnect':
          var result = await startConnect(preferenceRepository);
          return result;
        case 'disconnect':
          return await disconnect();
        case 'getTestString':
          return getTestString();
        default:
          throw UnimplementedError("Unknow: ${call.method}");
      }
    },
  );
}
  1. 优化FlutterEngine初始化逻辑:确保Service中只初始化一次FlutterEngine,避免插件重复注册的警告。可以通过全局单例或者在Service内部判断Engine是否已创建来实现。

内容的提问来源于stack exchange,提问作者Kingfisher Phuoc

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 03:40:35