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.
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
Containerthat drives the Flutter
Containervia 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_moduledirectory 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
--androidxflag:
<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_moduleinto the native project:
Source dependency
AAR dependency
2.2.1 Source Dependency Integration
With source dependency you edit the native
settings.gradleand the
app/build.gradlefiles 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_modulefolder 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.yamladd
flutter_boostas 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_hotfixesinstead.
Run
flutter packages getto fetch the dependency.
2.4 Initialize Flutter Boost in Android
Add a BoostFlutterActivity to
AndroidManifest.xml:
<code><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>
</code>Also add the Flutter embedding version meta‑data:
<code><meta-data android:name="flutterEmbedding" android:value="2"/></code>Initialize Flutter Boost in the
Applicationclass (e.g.,
MyApplication) by implementing
INativeRouterand 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
onClickhandler 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
paramsmap, 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 attachfor 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><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>
</code>In the layout XML add a
FrameLayoutas a placeholder for the fragment:
<code><FrameLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:id="@+id/fragment_stub"/>
</code>In the Activity’s click handler create a
FlutterFragmentwith 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.registerPageBuilderswith 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> ContainerCoordinatorstores 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,
_createContainerSettingsbuilds a
BoostContainerSettingsobject. Inside the
buildercallback it looks up the page name in
_pageBuildersand 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
BoostContainerSettingsis 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
willShowPageContainermethod it extracts
pageName,
paramsand
uniqueId, then calls
_nativeContainerWillShowto 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
FlutterBoostPluginregisters a
MethodChannelhandler. When the
openPagemethod 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
openContainermethod 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
openPageand 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.
QQ Music Frontend Team
QQ Music Web Frontend Team
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.