Open matthew-carroll opened 4 years ago
CC @xster
Is it currently possible to embed flutter in a native app that is using jetpack navigation?
Any update on this?
I got a workaround for this. This is how you can use FlutterFragment(Add-to-app) with NavGraph/Jetpack Navigation Component:
class FlutterRootFragment : FlutterFragment() {
@Inject
lateinit var flutterManager: FlutterManager
// this does the trick
override fun getCachedEngineId(): String {
return FlutterManager.ENGINE_NAME;
}
override fun onDestroy() {
super.onDestroy()
// clear route when user goes back
flutterManager.pushRoute("/");
}
}
Then add FlutterFragment to navigation graph XML.
<fragment
android:id="@+id/flutterRootFragment"
android:name=".view.screens.flutter.FlutterRootFragment"
android:label="FlutterRootFragment" />
To navigate to a Flutter page use a method channel to update the route in your Flutter module, and use NavController
flutterManager.pushRoute("/profile-page")
navController.navigate(R.id.flutterRootFragment)
In Flutter main.dart:
channel.setMethodCallHandler((MethodCall call) async {
if (call.method == 'pushRoute') {
appRouter.replaceNamed(call.arguments);
if (call.arguments == "/") {
appRouter.popUntilRouteWithPath("/");
}
}
});
Hope it helps.
@hm-tamim above method you provided doesn't work. here's why.
By traditional navigation method, when we create a flutterFragment instance it calls createArgs()
below which does some ads-on work like creating input args for newly created flutterFragment but the problem seems like Navigation component
has got some different implementation for fragment creation which flutter doesn't support yet.
protected Bundle createArgs() {
Bundle args = new Bundle();
args.putString(ARG_INITIAL_ROUTE, initialRoute);
args.putBoolean(ARG_HANDLE_DEEPLINKING, handleDeeplinking);
args.putString(ARG_APP_BUNDLE_PATH, appBundlePath);
args.putString(ARG_DART_ENTRYPOINT, dartEntrypoint);
args.putString(ARG_DART_ENTRYPOINT_URI, dartLibraryUri);
args.putStringArrayList(
ARG_DART_ENTRYPOINT_ARGS,
dartEntrypointArgs != null ? new ArrayList(dartEntrypointArgs) : null);
// TODO(mattcarroll): determine if we should have an explicit FlutterTestFragment instead of
// conflating.
if (null != shellArgs) {
args.putStringArray(ARG_FLUTTER_INITIALIZATION_ARGS, shellArgs.toArray());
}
args.putString(
ARG_FLUTTERVIEW_RENDER_MODE,
renderMode != null ? renderMode.name() : RenderMode.surface.name());
args.putString(
ARG_FLUTTERVIEW_TRANSPARENCY_MODE,
transparencyMode != null ? transparencyMode.name() : TransparencyMode.transparent.name());
args.putBoolean(ARG_SHOULD_ATTACH_ENGINE_TO_ACTIVITY, shouldAttachEngineToActivity);
args.putBoolean(ARG_DESTROY_ENGINE_WITH_FRAGMENT, true);
args.putBoolean(
ARG_SHOULD_AUTOMATICALLY_HANDLE_ON_BACK_PRESSED, shouldAutomaticallyHandleOnBackPressed);
args.putBoolean(ARG_SHOULD_DELAY_FIRST_ANDROID_VIEW_DRAW, shouldDelayFirstAndroidViewDraw);
return args;
}
this is what i found out but not sure if something else is going on under the hood.
@hm-tamim above method you provided doesn't work. here's why.
By traditional navigation method, when we create a flutterFragment instance it calls
createArgs()
below which does some ads-on work like creating input args for newly created flutterFragment but the problem seems likeNavigation component
has got some different implementation for fragment creation which flutter doesn't support yet.protected Bundle createArgs() { Bundle args = new Bundle(); args.putString(ARG_INITIAL_ROUTE, initialRoute); args.putBoolean(ARG_HANDLE_DEEPLINKING, handleDeeplinking); args.putString(ARG_APP_BUNDLE_PATH, appBundlePath); args.putString(ARG_DART_ENTRYPOINT, dartEntrypoint); args.putString(ARG_DART_ENTRYPOINT_URI, dartLibraryUri); args.putStringArrayList( ARG_DART_ENTRYPOINT_ARGS, dartEntrypointArgs != null ? new ArrayList(dartEntrypointArgs) : null); // TODO(mattcarroll): determine if we should have an explicit FlutterTestFragment instead of // conflating. if (null != shellArgs) { args.putStringArray(ARG_FLUTTER_INITIALIZATION_ARGS, shellArgs.toArray()); } args.putString( ARG_FLUTTERVIEW_RENDER_MODE, renderMode != null ? renderMode.name() : RenderMode.surface.name()); args.putString( ARG_FLUTTERVIEW_TRANSPARENCY_MODE, transparencyMode != null ? transparencyMode.name() : TransparencyMode.transparent.name()); args.putBoolean(ARG_SHOULD_ATTACH_ENGINE_TO_ACTIVITY, shouldAttachEngineToActivity); args.putBoolean(ARG_DESTROY_ENGINE_WITH_FRAGMENT, true); args.putBoolean( ARG_SHOULD_AUTOMATICALLY_HANDLE_ON_BACK_PRESSED, shouldAutomaticallyHandleOnBackPressed); args.putBoolean(ARG_SHOULD_DELAY_FIRST_ANDROID_VIEW_DRAW, shouldDelayFirstAndroidViewDraw); return args; }
this is what i found out but not sure if something else is going on under the hood.
I have faced the same issue, any updates on it?
Jetpack has introduced a Navigation component: https://developer.android.com/guide/navigation/navigation-getting-started
This ticket is to ensure that
FlutterFragment
can work with the Navigation component, and to produce any relevant docs/guides for add-to-app developers to do so.