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

Android集成FlutterFragment时Image Picker插件不工作问题求解

Android原生集成Flutter模块Image Picker库运行异常问题解决

问题现象

集成过程中首先抛出插件缺失异常:

Unhandled Exception: MissingPluginException(No implementation found for method pickImage on channel plugins.flutter.io/image_picker_android)

初步定位为GeneratedPluginRegistrant未完成注册,需要重写configureFlutterEngine方法完成插件注册。但业务场景需要在Fragment中打开Flutter模块,无法直接让Activity继承FlutterActivity,该类不支持getSupportFragmentManager调用。

尝试将Activity改为继承FlutterFragmentActivity后,虽然可以重写configureFlutterEngine方法,但又抛出视图找不到的错误:

java.lang.IllegalArgumentException: No view found for id 0x245a3c5c (unknown) for fragment FlutterFragment{647abea (0b17a247-4e8e-42bc-b5f3-6ab0796e458b) id=0x245a3c5c flutter_fragment}

原有问题代码

MainActivity.java

package com.mch.testplugin;

import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.FrameLayout;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import io.flutter.embedding.android.FlutterActivity;
import io.flutter.embedding.android.FlutterFragment;
import io.flutter.embedding.android.FlutterFragmentActivity;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.embedding.engine.FlutterEngineCache;
import io.flutter.embedding.engine.dart.DartExecutor;
import io.flutter.plugins.GeneratedPluginRegistrant;

public class MainActivity extends AppCompatActivity {

Context mContext;
FlutterFragment flutterFragment;
private static final String TAG_FLUTTER_FRAGMENT = "flutter_fragment";
FlutterEngine mFlutterEngine;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    mContext = this;
    setContentView(R.layout.activity_main);

    Button myButton = findViewById(R.id.myButton);
    myButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            flutterFragment = (FlutterFragment) getSupportFragmentManager()
                    .findFragmentByTag(TAG_FLUTTER_FRAGMENT);

            // Create and attach a FlutterFragment if one does not exist.
            if (flutterFragment == null) {
                flutterFragment = FlutterFragment.createDefault();

                flutterFragment = FlutterFragment.withNewEngine()
                        .initialRoute("/")
                        .build();

                getSupportFragmentManager()
                        .beginTransaction()
                        .add(
                                R.id.frame_layout,
                                flutterFragment,
                                TAG_FLUTTER_FRAGMENT
                        )
                        .commit();


            }
    });

}


//    @Override
//    public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
////        super.configureFlutterEngine(flutterEngine);
//        mFlutterEngine = flutterEngine;
//        GeneratedPluginRegistrant.registerWith(new FlutterEngine(this));
//    }
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout       xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">

<Button
    android:id="@+id/myButton"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Hello World!" />

<FrameLayout
    android:id="@+id/frame_layout"
    android:layout_width="match_parent"
    android:layout_height="200dp" />

</androidx.constraintlayout.widget.ConstraintLayout>

修复方案

问题根源有三点:

  1. 继承AppCompatActivity时configureFlutterEngine不会被系统回调,插件注册逻辑根本没有执行;注释里的注册代码还错误地新建了FlutterEngine实例,和FlutterFragment实际绑定的Engine不是同一个,就算执行也不会生效。
  2. 布局使用ConstraintLayout但没有给子控件添加约束,FrameLayout没有被正确加载到视图树,导致Fragment事务执行时找不到对应id的容器。
  3. 代码里冗余调用了FlutterFragment.createDefault(),后续又重新构建了Fragment实例,属于无效代码。

按如下修改即可正常运行:

修改后的MainActivity.java

package com.mch.testplugin;

import android.os.Bundle;
import android.view.View;
import android.widget.Button;

import androidx.annotation.NonNull;
import io.flutter.embedding.android.FlutterFragment;
import io.flutter.embedding.android.FlutterFragmentActivity;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.plugins.GeneratedPluginRegistrant;

public class MainActivity extends FlutterFragmentActivity {

    private FlutterFragment flutterFragment;
    private static final String TAG_FLUTTER_FRAGMENT = "flutter_fragment";
    private FlutterEngine mFlutterEngine;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button myButton = findViewById(R.id.myButton);
        myButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                flutterFragment = (FlutterFragment) getSupportFragmentManager()
                        .findFragmentByTag(TAG_FLUTTER_FRAGMENT);

                if (flutterFragment == null) {
                    flutterFragment = FlutterFragment.withNewEngine()
                            .initialRoute("/")
                            .build();

                    getSupportFragmentManager()
                            .beginTransaction()
                            .add(
                                    R.id.frame_layout,
                                    flutterFragment,
                                    TAG_FLUTTER_FRAGMENT
                            )
                            .commit();
                }
            }
        });
    }

    @Override
    public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
        super.configureFlutterEngine(flutterEngine);
        mFlutterEngine = flutterEngine;
        GeneratedPluginRegistrant.registerWith(flutterEngine);
    }
}

修改后的activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/myButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="打开Flutter模块"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        android:layout_marginTop="20dp"/>

    <FrameLayout
        android:id="@+id/frame_layout"
        android:layout_width="match_parent"
        android:layout_height="200dp"
        app:layout_constraintTop_toBottomOf="@id/myButton"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        android:layout_marginTop="20dp"/>

</androidx.constraintlayout.widget.ConstraintLayout>

补充说明

  • FlutterFragmentActivity本身是AppCompatActivity的子类,完全兼容原生Fragment的所有API,不存在无法调用getSupportFragmentManager的问题。
  • 如果对Flutter模块启动速度有要求,可以提前在Application类中初始化FlutterEngine并缓存,构建FlutterFragment时使用withCachedEngine()方法传入缓存的Engine ID,能大幅降低页面打开耗时。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 23:45:54