Mobile Development 24 min read

How to Integrate Flutter Boost for Seamless Android‑Flutter Hybrid Development

This guide walks you through the complete process of adding Flutter Boost to an existing Android project, creating a Flutter module, registering pages in Dart, configuring native routing, handling communication between Dart and Java, and even embedding Flutter fragments, while also providing a concise source‑code analysis of the framework's core mechanisms.

QQ Music Frontend Team
QQ Music Frontend Team
QQ Music Frontend Team
How to Integrate Flutter Boost for Seamless Android‑Flutter Hybrid Development

1. Introduction

Flutter Boost is a Flutter hybrid development framework created by the Xianyu team. For background you can read the Xianyu article Code‑First Flutter Hybrid Development – FlutterBoost . The article explains why multiple engines cause practical problems, so Xianyu adopts a shared‑engine hybrid solution. Flutter Boost’s key features are:

Reusable generic hybrid solution

Supports complex hybrid patterns such as home‑tab navigation

Non‑intrusive: no need to modify the Flutter engine

Supports a unified page lifecycle

Clear design concept

Flutter Boost shares a single engine between native and Flutter containers. The native side creates a Container that drives the Flutter Container via messages, making the two containers synchronized. Think of it as a browser‑like experience: you provide a page address and the container renders the page.

Note: The version used in this article is Flutter Boost 1.12.13, which works with Flutter SDK 1.12.13‑hotfixes. Newer versions may change the integration API.

2. Integration

2.1 Create Flutter Module

Before starting, make sure your project directory looks like this:

--- flutter_hybrid
--- flutter_module
--- FlutterHybridAndroid
--- FlutterHybridiOS

In other words, the Android project, the iOS project and the flutter_module directory are at the same level, which simplifies path management.

Then create the Flutter module:

cd flutter_hybrid
flutter create -t module flutter_module

If you need an AndroidX‑compatible module, add the --androidx flag:

flutter create --androidx -t module flutter_module

When the dependency download is slow, you can switch to a domestic mirror:

export PUB_HOSTED_URL=https://pub.flutter-io.cn
export FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn

You can also create the module via Android Studio (3.6.1+ with Flutter and Dart plugins), but the command‑line method is more universal.

2.2 Integrate Flutter Module

There are two ways to integrate the flutter_module into the native project:

Source dependency

AAR dependency

2.2.1 Source Dependency Integration

With source dependency you edit the native settings.gradle and the app/build.gradle files to add the module as a project dependency.

// settings.gradle
include ':app'
setBinding(new Binding([gradle: this]))
evaluate(new File(rootProject.projectDir.parentFile, 'flutter_module/.android/include_flutter.groovy'))

// app/build.gradle (dependencies block)
implementation project(':flutter')

// Java version configuration
compileOptions {
    sourceCompatibility 1.8
    targetCompatibility 1.8
}

After editing, run a Gradle sync. If the sync succeeds you will see the flutter_module folder next to the native project.

2.2.2 AAR Dependency Integration

If the build machine does not have a Flutter environment, you can package the module as an AAR and use it as a binary dependency. Build the AAR with:

cd .android
./gradlew flutter:assembleDebug

Then add the generated AAR to the native project and declare it in app/build.gradle:

implementation project(':flutter')
implementation project(':flutter_boost')

2.3 Add Flutter Boost Dependency

In the Flutter module’s pubspec.yaml add flutter_boost as a dev_dependency:

dev_dependencies:
  flutter_boost:
    git:
      url: 'https://github.com/alibaba/flutter_boost.git'
      ref: '1.12.13'

If you need the old support‑library branch, switch the Git reference to task/task_v1.12.13_support_hotfixes instead.

Run flutter packages get to fetch the dependency.

2.4 Initialize Flutter Boost in Android

Add a BoostFlutterActivity to AndroidManifest.xml:

<activity
    android:name="com.idlefish.flutterboost.containers.BoostFlutterActivity"
    android:theme="@style/Theme.AppCompat"
    android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density"
    android:hardwareAccelerated="true"
    android:windowSoftInputMode="adjustResize"
    >
    <meta-data android:name="io.flutter.embedding.android.SplashScreenDrawable" android:resource="@drawable/page_loading"/>
</activity>

Also add the Flutter embedding version meta‑data:

<meta-data android:name="flutterEmbedding" android:value="2"/>

Initialize Flutter Boost in the Application class (e.g., MyApplication) by implementing INativeRouter and configuring the Boost instance:

public class MyApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        INativeRouter router = new INativeRouter() {
            @Override
            public void openContainer(Context context, String url, Map<String, Object> urlParams, int requestCode, Map<String, Object> exts) {
                // Build the intent for BoostFlutterActivity
                Intent intent = BoostFlutterActivity.withNewEngine()
                        .url(url)
                        .params(urlParams)
                        .backgroundMode(BoostFlutterActivity.BackgroundMode.opaque)
                        .build(context);
                if (context instanceof Activity) {
                    ((Activity) context).startActivityForResult(intent, requestCode);
                } else {
                    context.startActivity(intent);
                }
            }
            // other lifecycle callbacks omitted for brevity
        };
        Platform platform = FlutterBoost.ConfigBuilder(this, router)
                .isDebug(true)
                .whenEngineStart(FlutterBoost.ConfigBuilder.ANY_ACTIVITY_CREATED)
                .renderMode(FlutterView.RenderMode.texture)
                .lifecycleListener(new BoostLifecycleListener() { /* ... */ })
                .build();
        FlutterBoost.instance().init(platform);
    }
}

2.5 PageRouter Utility Class

The following Java class provides a simple routing helper used by the native side to open Flutter pages or native pages based on a URL:

public class PageRouter {
    public static final Map<String, String> pageName = new HashMap<String, String>() {{
        put("first", "first");
        put("second", "second");
        put("tab", "tab");
        put("sample://flutterPage", "flutterPage");
    }};
    public static final String NATIVE_PAGE_URL = "sample://nativePage";
    public static final String FLUTTER_PAGE_URL = "sample://flutterPage";
    public static final String FLUTTER_FRAGMENT_PAGE_URL = "sample://flutterFragmentPage";

    public static boolean openPageByUrl(Context context, String url, Map<String, Object> params) {
        return openPageByUrl(context, url, params, 0);
    }

    public static boolean openPageByUrl(Context context, String url, Map<String, Object> params, int requestCode) {
        String path = url.split("\\?")[0];
        Log.i("openPageByUrl", path);
        try {
            if (pageName.containsKey(path)) {
                Intent intent = BoostFlutterActivity.withNewEngine()
                        .url(pageName.get(path))
                        .params(params)
                        .backgroundMode(BoostFlutterActivity.BackgroundMode.opaque)
                        .build(context);
                if (context instanceof Activity) {
                    ((Activity) context).startActivityForResult(intent, requestCode);
                } else {
                    context.startActivity(intent);
                }
                return true;
            } else if (url.startsWith(FLUTTER_FRAGMENT_PAGE_URL)) {
                context.startActivity(new Intent(context, FlutterFragmentPageActivity.class));
                return true;
            } else if (url.startsWith(NATIVE_PAGE_URL)) {
                context.startActivity(new Intent(context, NativePageActivity.class));
                return true;
            }
        } catch (Throwable t) {
            return false;
        }
        return false;
    }
}

2.6 Open a Flutter Page from Native

In a native button’s onClick handler you can open a registered Flutter page and pass a map of parameters:

@Override
public void onClick(View v) {
    Map<String, Object> params = new HashMap<>();
    params.put("test1", "v_test1");
    params.put("test2", "v_test2");
    PageRouter.openPageByUrl(this, "first", params);
}

The registered builder in Flutter receives the params map, which you can log or use to build the widget:

FlutterBoost.singleton.registerPageBuilders({
  'first': (pageName, params, _) {
    print("flutterPage params:$params");
    return FirstRouteWidget(params: params);
  },
  'second': (pageName, params, _) => SecondRouteWidget(),
});

2.7 Open a Native Page from Flutter

From Flutter you can navigate back to a native page using the Boost API:

onTap: () => FlutterBoost.singleton.open(
    "sample://nativePage",
    urlParams: {
      "query": {"aaa": "bbb"}
    },
);

Because Flutter runs in JIT mode, you can use flutter attach for hot‑reload without rebuilding the whole app.

3. Hybrid Development 2: Flutter Fragment

Assume you have an Activity that will host a Flutter fragment. Declare the Activity in the manifest:

<activity
    android:name=".FlutterFragmentPageActivity"
    android:theme="@style/Theme.AppCompat"
    android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density"
    android:hardwareAccelerated="true"
    android:windowSoftInputMode="adjustResize"
    >
    <meta-data android:name="io.flutter.embedding.android.SplashScreenDrawable" android:resource="@drawable/page_loading"/>
</activity>

In the layout XML add a FrameLayout as a placeholder for the fragment:

<FrameLayout
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:layout_weight="1"
    android:id="@+id/fragment_stub"/>

In the Activity’s click handler create a FlutterFragment with the desired URL and replace the placeholder:

@Override
public void onClick(View v) {
    FlutterFragment mFragment = new FlutterFragment.NewEngineFragmentBuilder()
            .url("flutterFragment")
            .build();
    getSupportFragmentManager()
            .beginTransaction()
            .replace(R.id.fragment_stub, mFragment)
            .commit();
}

4. Flutter Boost Source Code Analysis

This section briefly explains the core implementation of Flutter Boost so you can understand how it works under the hood.

4.1 Registering Pages (Dart Side)

In Dart you call FlutterBoost.singleton.registerPageBuilders with a map of page names to widget builders. The call forwards the map to the singleton ContainerCoordinator:

void registerPageBuilders(Map<String, PageBuilder> builders) {
    ContainerCoordinator.singleton.registerPageBuilders(builders);
}
ContainerCoordinator

stores the builders in a private map _pageBuilders:

final Map<String, PageBuilder> _pageBuilders = {};
void registerPageBuilder(String pageName, PageBuilder builder) {
    if (pageName != null && builder != null) {
        _pageBuilders[pageName] = builder;
    }
}

When a native request arrives, _createContainerSettings builds a BoostContainerSettings object. Inside the builder callback it looks up the page name in _pageBuilders and creates the widget:

Widget page;
if (_pageBuilders[name] != null) {
    page = _pageBuilders[name](name, params, pageId);
} else if (_defaultPageBuilder != null) {
    page = _defaultPageBuilder(name, params, pageId);
}
assert(page != null);
return page;

The resulting BoostContainerSettings is returned to the native side via _nativeContainerWillShow, which pushes the container through FlutterBoost.containerManager?.pushContainer.

4.2 Communication Channel

Flutter Boost uses a BoostChannel (a thin wrapper around MethodChannel) to exchange messages. The channel registers a lifecycle event listener and a method call handler:

channel.addEventListener("lifecycle", (name, arguments) => _onChannelEvent(arguments));
channel.addMethodHandler((call) => _onMethodCall(call));

The method handler logs the incoming method name and dispatches it via a switch. For the willShowPageContainer method it extracts pageName, params and uniqueId, then calls _nativeContainerWillShow to create and push the container.

4.3 Opening a Page from Dart

When you call FlutterBoost.singleton.open, the Dart side packages the URL, parameters and extensions into a map and invokes the native method openPage:

Future<Map<dynamic, dynamic>> open(String url, {Map<dynamic, dynamic> urlParams, Map<dynamic, dynamic> exts}) {
  final properties = {};
  properties["url"] = url;
  properties["urlParams"] = urlParams;
  properties["exts"] = exts;
  return channel.invokeMethod<Map<dynamic, dynamic>>('openPage', properties);
}

4.4 Native Side Handling (Android)

On Android the FlutterBoostPlugin registers a MethodChannel handler. When the openPage method is received, it extracts the arguments and calls FlutterViewContainerManager.openContainer:

case "openPage": {
    try {
        Map<String, Object> params = (Map<String, Object>) call.argument("urlParams");
        Map<String, Object> exts = (Map<String, Object>) call.argument("exts");
        String url = (String) call.argument("url");
        mManager.openContainer(url, params, exts, new FlutterViewContainerManager.OnResult() {
            @Override
            public void onResult(Map<String, Object> rlt) {
                if (result != null) {
                    result.success(rlt);
                }
            }
        });
    } catch (Throwable t) {
        result.error("open page error", t.getMessage(), t);
    }
    break;
}

The openContainer method is abstract; the developer implements it (e.g., in PageRouter) to start the appropriate Activity with the supplied URL and parameters.

4.5 Summary of the Flow

1. Dart registers page builders. 2. Native sends willShowPageContainer → Dart builds the widget and returns a container setting. 3. Native receives the setting and pushes a new container. 4. When Dart calls open, the native plugin receives openPage and starts the requested Activity or fragment. 5. Communication is performed via the BoostChannel (MethodChannel) on both sides.

5. Conclusion

Following the steps above you can embed Flutter pages into an existing Android project, navigate between native and Flutter screens, embed Flutter fragments, and understand the core mechanisms of Flutter Boost. The article provides a practical reference for hybrid development and a brief look at the underlying source code.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Hybrid Developmentandroid integrationFlutter Boost
QQ Music Frontend Team
Written by

QQ Music Frontend Team

QQ Music Web Frontend Team

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.