Search code examples
flutterflutter-dependenciesflutter-plugin

Flutter plugins fail to load in a fragment


The flutter plugins are not loading when used with FlutterFragment. However, they are working fine when used with FlutterActivity.

Ends up with the following exception for exception

E [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: PlatformException(channel-error, Unable to establish connection on channel., null, null) #0 InstanceManagerHostApi.clear (package:camera_android_camerax/src/camerax_library.g.dart:315:7)

I have 2 plugins and all are failing with the same exception.

flutter_native_barcode_scanner
fl_location

Solution

  • Usually problem like this happens when plugins are not registered. From this moment, I will treat your problem, as if you followed the official add-to-app guide for Android, meaning:

    1. You are using simple FragmentActivity or AppCompatActivity or something similar, not related to Flutter.
    2. You are not inherit or override FlutterFragment and create it with FlutterFragment.createDefault.

    This 2 points are crucial for understand, but even if your setup is a bit different, I will provide some universal advices.

    So, main issue here is that default flutter engine created with FlutterFragment is not automatically register plugins. proof

    There are several ways to change that. Here is some of them:

    1. Use FlutterFragmentActivity as host activity for your fragment. Unfortunately, will not work because of this issue

    2. (I prefer this) Register plugins yourself by overriding FlutterFragment. Take a look at example:

    First, create your own fragment (you can use any name):

    import io.flutter.embedding.android.FlutterFragment
    import io.flutter.embedding.engine.FlutterEngine
    import io.flutter.plugins.GeneratedPluginRegistrant
    
    class MyFlutterFragment : FlutterFragment() {
        override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
            super.configureFlutterEngine(flutterEngine)
            GeneratedPluginRegistrant.registerWith(flutterEngine)
        }
    }
    

    It is actually boilerplate code, sou you can just copy-paste it if you do not need another overrides.

    Then, you should create instance of your own Fragment, but with tools provided from Flutter. It's tricky part, at least for me:

    // This is how Flutter documentation advices to create fragment:
        if (flutterFragment == null) {
          // Main line is here
          var newFlutterFragment = FlutterFragment.createDefault()
          //
          flutterFragment = newFlutterFragment
          fragmentManager
            .beginTransaction()
            .add(
              R.id.fragment_container,
              newFlutterFragment,
              TAG_FLUTTER_FRAGMENT
            )
            .commit()
        }
      }
    
    // Instead, you will create your MyFlutterPlugin like this:
    var newFlutterFragment = FlutterFragment.NewEngineFragmentBuilder(MyFlutterFragment::class.java).build<MyFlutterFragment>()
    
    // Full example:
    val fragmentManager: FragmentManager = supportFragmentManager
            flutterFragment = fragmentManager
                .findFragmentByTag(TAG_FLUTTER_FRAGMENT) as FlutterFragment?
    
            if (flutterFragment == null) {
                var newFlutterFragment = FlutterFragment.NewEngineFragmentBuilder(MyFlutterFragment::class.java)
                    .build<MyFlutterFragment>()
                flutterFragment = newFlutterFragment
                fragmentManager
                    .beginTransaction()
                    .add(
                        binding.navHostFragmentContentMain.id,
                        newFlutterFragment,
                        TAG_FLUTTER_FRAGMENT
                    )
                    .commit()
            }
    

    This was an corrected example from official docs

    TLDR;

    So, main point here is that it is obligatory to register plugins manually when working with FlutterFragments

    I created a GitHub repo with reproduction of your problem and described solution: https://github.com/Sameri11/flutter-add-to-app-example.

    On main branch app works, on plugins_crash there are same errors in log as yours.

    You are free to use this code.