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:

<code>--- flutter_hybrid
--- flutter_module
--- FlutterHybridAndroid
--- FlutterHybridiOS</code>

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:

<code>cd flutter_hybrid
flutter create -t module flutter_module</code>

If you need an AndroidX‑compatible module, add the

--androidx

flag:

<code>flutter create --androidx -t module flutter_module</code>

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

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

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.

<code>// 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
}
</code>

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:

<code>cd .android
./gradlew flutter:assembleDebug</code>

Then add the generated AAR to the native project and declare it in

app/build.gradle

:

<code>implementation project(':flutter')
implementation project(':flutter_boost')
</code>

2.3 Add Flutter Boost Dependency

In the Flutter module’s

pubspec.yaml

add

flutter_boost

as a

dev_dependency

:

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

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

:

<code>&lt;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"
    &gt;
    &lt;meta-data android:name="io.flutter.embedding.android.SplashScreenDrawable" android:resource="@drawable/page_loading"/&gt;
&lt;/activity&gt;
</code>

Also add the Flutter embedding version meta‑data:

<code>&lt;meta-data android:name="flutterEmbedding" android:value="2"/&gt;</code>

Initialize Flutter Boost in the

Application

class (e.g.,

MyApplication

) by implementing

INativeRouter

and configuring the Boost instance:

<code>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);
    }
}
</code>

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:

<code>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;
    }
}
</code>

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:

<code>@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);
}
</code>

The registered builder in Flutter receives the

params

map, which you can log or use to build the widget:

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

2.7 Open a Native Page from Flutter

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

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

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:

<code>&lt;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"
    &gt;
    &lt;meta-data android:name="io.flutter.embedding.android.SplashScreenDrawable" android:resource="@drawable/page_loading"/&gt;
&lt;/activity&gt;
</code>

In the layout XML add a

FrameLayout

as a placeholder for the fragment:

<code>&lt;FrameLayout
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:layout_weight="1"
    android:id="@+id/fragment_stub"/&gt;
</code>

In the Activity’s click handler create a

FlutterFragment

with the desired URL and replace the placeholder:

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

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

:

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

stores the builders in a private map

_pageBuilders

:

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

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:

<code>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;
</code>

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:

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

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

:

<code>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);
}
</code>

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

:

<code>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;
}
</code>

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.

fluttermobile developmentHybrid 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

login 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.