skip to Main Content

I need to host an embedded native view into my Flutter app,
I have an Android Fragment and me trying to add it to the View class that registered in FlutterEngine
but Fragments need to be added:

(context as FragmentActivity).supportFragmentManager

And that does not work due to the existing context is MutableContextWrapper

Any help, please?

MainActivity:

class MainActivity: FlutterActivity() {
    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        flutterEngine
            .platformViewsController
            .registry
            .registerViewFactory("EmbeddedNavigationView.kt", EmbeddedNavigationFactory(mapOf("text" to "hello!")))
    }


}

EmbeddedNavigationView:

class EmbeddedNavigationView(context: Context, val viewParams: Map<String, Any>) : View(context), PlatformView {

    private lateinit var fragmentMap: Fragment
    private val fragment: Fragment = FlutterFragment.createDefault()
    init {
        initObjects()
        initSubView()
    }
    private fun initObjects() {
        fragmentMap = MapFragment()
    }
    private fun initSubView() {
        addFragment(fragmentMap)
    }
    private fun addFragment(fragment: Fragment) {

        // thow error due to MutableContextWrapper is not a FragmentActivity

        val fragmentManager = (context as FragmentActivity).supportFragmentManager

        val transaction = fragmentManager.beginTransaction()
        transaction.add(R.id.fragment_map, fragment)
        transaction.commit()
    }

    private fun removeFragment(fragment: Fragment) {
        val fragmentManager = (context as FragmentActivity).supportFragmentManager

        val transaction = fragmentManager.beginTransaction()
        transaction.remove(fragment)
        transaction.commit()
    }


    override fun onDraw(canvas: Canvas) {
        // Draw the view's content
        super.onDraw(canvas)
    }

    override fun onDetachedFromWindow() {
        // Remove the fragment when the view is detached
        fragmentMap?.let {
            (context as AppCompatActivity).supportFragmentManager.beginTransaction().remove(it).commit()
        }
        super.onDetachedFromWindow()
    }

    class MyFragment : Fragment() {
        // Fragment code here
    }

    override fun getView(): View? {
        return this

        TODO("Not yet implemented")

    }

    override fun dispose() {
        // impl dispose



        TODO("Not yet implemented")
    }


}

EmbeddedNavigationFactory:

class EmbeddedNavigationFactory(private val createParams: Map<String, Any>?) : PlatformViewFactory(StandardMessageCodec.INSTANCE) {

    override fun create(context: Context, viewId: Int, args: Any?): PlatformView {
        val viewParams = createParams ?: args as? Map<String, Any> ?: mapOf()

        return EmbeddedNavigationView(context, viewParams)
    }

}

MapFragment:

class MapFragment : androidx.fragment.app.Fragment() { ... }

Logs:

Launching lib/main.dart on 2201117TG in debug mode...
Running Gradle task 'assembleDebug'...
✓  Built build/app/outputs/flutter-apk/app-debug.apk.
Installing build/app/outputs/flutter-apk/app-debug.apk...
Debug service listening on ws://127.0.0.1:50805/JtPxjixFiC4=/ws
Syncing files to device 2201117TG...
E/MethodChannel#flutter/platform_views(15059): Failed to handle method call
E/MethodChannel#flutter/platform_views(15059): java.lang.ClassCastException: android.content.MutableContextWrapper cannot be cast to androidx.fragment.app.FragmentActivity
E/MethodChannel#flutter/platform_views(15059):  at com.example.mapbox_android_update.EmbeddedNavigationView.addFragment(EmbeddedNavigationView.kt:29)
E/MethodChannel#flutter/platform_views(15059):  at com.example.mapbox_android_update.EmbeddedNavigationView.initSubView(EmbeddedNavigationView.kt:26)
E/MethodChannel#flutter/platform_views(15059):  at com.example.mapbox_android_update.EmbeddedNavigationView.<init>(EmbeddedNavigationView.kt:20)
E/MethodChannel#flutter/platform_views(15059):  at com.example.mapbox_android_update.EmbeddedNavigationFactory.create(EmbeddedNavigationFactory.kt:19)
E/MethodChannel#flutter/platform_views(15059):  at io.flutter.plugin.platform.PlatformViewsController$1.createPlatformView(PlatformViewsController.java:503)
E/MethodChannel#flutter/platform_views(15059):  at io.flutter.plugin.platform.PlatformViewsController$1.createForTextureLayer(PlatformViewsController.java:191)
E/MethodChannel#flutter/platform_views(15059):  at io.flutter.embedding.engine.systemchannels.PlatformViewsChannel$1.create(PlatformViewsChannel.java:128)
E/MethodChannel#flutter/platform_views(15059):  at io.flutter.embedding.engine.systemchannels.PlatformViewsChannel$1.onMethodCall(PlatformViewsChannel.java:55)
E/MethodChannel#flutter/platform_views(15059):  at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.onMessage(MethodChannel.java:258)
E/MethodChannel#flutter/platform_views(15059):  at io.flutter.embedding.engine.dart.DartMessenger.invokeHandler(DartMessenger.java:295)
E/MethodChannel#flutter/platform_views(15059):  at io.flutter.embedding.engine.dart.DartMessenger.lambda$dispatchMessageToQueue$0$io-flutter-embedding-engine-dart-DartMessenger(DartMessenger.java:322)
E/MethodChannel#flutter/platform_views(15059):  at io.flutter.embedding.engine.dart.DartMessenger$$ExternalSyntheticLambda0.run(Unknown Source:12)
E/MethodChannel#flutter/platform_views(15059):  at android.os.Handler.handleCallback(Handler.java:938)
E/MethodChannel#flutter/platform_views(15059):  at android.os.Handler.dispatchMessage(Handler.java:99)
E/MethodChannel#flutter/platform_views(15059):  at android.os.Looper.loopOnce(Looper.java:210)
E/MethodChannel#flutter/platform_views(15059):  at android.os.Looper.loop(Looper.java:299)
E/MethodChannel#flutter/platform_views(15059):  at android.app.ActivityThread.main(ActivityThread.java:8309)
E/MethodChannel#flutter/platform_views(15059):  at java.lang.reflect.Method.invoke(Native Method)
E/MethodChannel#flutter/platform_views(15059):  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:556)
E/MethodChannel#flutter/platform_views(15059):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1038)
E/flutter (15059): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: PlatformException(error, android.content.MutableContextWrapper cannot be cast to androidx.fragment.app.FragmentActivity, null, java.lang.ClassCastException: android.content.MutableContextWrapper cannot be cast to androidx.fragment.app.FragmentActivity
E/flutter (15059):  at com.example.mapbox_android_update.EmbeddedNavigationView.addFragment(EmbeddedNavigationView.kt:29)
E/flutter (15059):  at com.example.mapbox_android_update.EmbeddedNavigationView.initSubView(EmbeddedNavigationView.kt:26)
E/flutter (15059):  at com.example.mapbox_android_update.EmbeddedNavigationView.<init>(EmbeddedNavigationView.kt:20)
E/flutter (15059):  at com.example.mapbox_android_update.EmbeddedNavigationFactory.create(EmbeddedNavigationFactory.kt:19)
E/flutter (15059):  at io.flutter.plugin.platform.PlatformViewsController$1.createPlatformView(PlatformViewsController.java:503)
E/flutter (15059):  at io.flutter.plugin.platform.PlatformViewsController$1.createForTextureLayer(PlatformViewsController.java:191)
E/flutter (15059):  at io.flutter.embedding.engine.systemchannels.PlatformViewsChannel$1.create(PlatformViewsChannel.java:128)
E/flutter (15059):  at io.flutter.embedding.engine.systemchannels.PlatformViewsChannel$1.onMethodCall(PlatformViewsChannel.java:55)
E/flutter (15059):  at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.onMessage(MethodChannel.java:258)
E/flutter (15059):  at io.flutter.embedding.engine.dart.DartMessenger.invokeHandler(DartMessenger.java:295)
E/flutter (15059):  at io.flutter.embedding.engine.dart.DartMessenger.lambda$dispatchMessageToQueue$0$io-flutter-embedding-engine-dart-DartMessenger(DartMessenger.java:322)
E/flutter (15059):  at io.flutter.embedding.engine.dart.DartMessenger$$ExternalSyntheticLambda0.run(Unknown Source:12)
E/flutter (15059):  at android.os.Handler.handleCallback(Handler.java:938)
E/flutter (15059):  at android.os.Handler.dispatchMessage(Handler.java:99)
E/flutter (15059):  at android.os.Looper.loopOnce(Looper.java:210)
E/flutter (15059):  at android.os.Looper.loop(Looper.java:299)
E/flutter (15059):  at android.app.ActivityThread.main(ActivityThread.java:8309)
E/flutter (15059):  at java.lang.reflect.Method.invoke(Native Method)
E/flutter (15059):  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:556)
E/flutter (15059):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1038)
E/flutter (15059): )
E/flutter (15059): #0      StandardMethodCodec.decodeEnvelope (package:flutter/src/services/message_codecs.dart:653:7)
E/flutter (15059): #1      MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart:315:18)
E/flutter (15059): <asynchronous suspension>
E/flutter (15059): #2      TextureAndroidViewController._sendCreateMessage (package:flutter/src/services/platform_views.dart:1141:28)
E/flutter (15059): <asynchronous suspension>
E/flutter (15059): #3      AndroidViewController.create (package:flutter/src/services/platform_views.dart:801:5)
E/flutter (15059): <asynchronous suspension>
E/flutter (15059): #4      AndroidViewController.setSize (package:flutter/src/services/platform_views.dart:828:7)
E/flutter (15059): <asynchronous suspension>
E/flutter (15059): #5      RenderAndroidView._sizePlatformView (package:flutter/src/rendering/platform_view.dart:182:29)
E/flutter (15059): <asynchronous suspension>
E/flutter (15059): 
E/_android_updat(15059): open libmigui.so failed! dlopen - dlopen failed: library "libmigui.so" not found
D/DecorView[](15059): onWindowFocusChanged hasWindowFocus true

adding this android native fragment to flutter app

2

Answers


  1. Chosen as BEST ANSWER

    solved you can use the data binding method to access the fragment


  2. To add an Android Fragment into your Flutter app, you need to follow a few steps:

    Create a platform channel between Flutter and Android to communicate with each other.

    In your Android project, create a new class that extends PlatformView and implements OnCreate and OnDestroy methods.

    In the OnCreate method, create an instance of your Fragment and add it to your ViewGroup.

    In the build method of your Flutter widget, add your platform view using the AndroidView widget.

    Here’s some sample code to help you get started:

    In your Android project, create a new class that extends PlatformView:

    public class MyPlatformView implements PlatformView, OnCreateListener, OnDestroyListener {
      private final FrameLayout layout;
      private final FragmentActivity activity;
    
      public MyPlatformView(Context context, int id, Map<String, Object> creationParams) {
        activity = (FragmentActivity) context;
        layout = new FrameLayout(context);
        activity.getSupportFragmentManager()
            .beginTransaction()
            .add(id, MyFragment.newInstance(), "MyFragment")
            .commit();
      }
    
      @Override
      public View getView() {
        return layout;
      }
    
      @Override
      public void onCreate() {
      }
    
      @Override
      public void onDestroy() {
      }
    }
    

    In your Flutter widget, use the AndroidView widget to add your platform view:

    class MyFlutterWidget extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: Center(
            child: AndroidView(
              viewType: 'myViewType',
              creationParams: {'myParam': 'myValue'},
              creationParamsCodec: const StandardMessageCodec(),
            ),
          ),
        );
      }
    }
    

    Note that in the AndroidView widget, viewType must match the name you used to register your MyPlatformView class in your FlutterEngine. You can register your MyPlatformView class by calling FlutterEngine.getPlugins().add(new MyPlugin()); where MyPlugin is a FlutterPlugin that implements registerWith.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search