5package io.flutter.embedding.android;
8import android.content.ComponentCallbacks2;
12import android.view.LayoutInflater;
15import android.view.ViewTreeObserver.OnWindowFocusChangeListener;
16import androidx.activity.OnBackPressedCallback;
17import androidx.annotation.NonNull;
18import androidx.annotation.Nullable;
19import androidx.annotation.VisibleForTesting;
20import androidx.fragment.app.Fragment;
21import androidx.fragment.app.FragmentActivity;
22import androidx.lifecycle.Lifecycle;
24import io.flutter.embedding.engine.FlutterEngine;
25import io.flutter.embedding.engine.FlutterShellArgs;
26import io.flutter.embedding.engine.renderer.FlutterUiDisplayListener;
27import io.flutter.plugin.platform.PlatformPlugin;
28import java.util.ArrayList;
109 private static final String TAG =
"FlutterFragment";
125 "should_delay_first_android_view_draw";
141 "should_attach_engine_to_activity";
168 "should_automatically_handle_on_back_pressed";
170 private final OnWindowFocusChangeListener onWindowFocusChangeListener =
171 new OnWindowFocusChangeListener() {
173 public void onWindowFocusChanged(
boolean hasFocus) {
174 if (stillAttachedForEvent(
"onWindowFocusChanged")) {
246 private final Class<? extends FlutterFragment> fragmentClass;
247 private String dartEntrypoint =
"main";
248 private String dartLibraryUri =
null;
250 private String initialRoute =
"/";
251 private boolean handleDeeplinking =
false;
252 private String appBundlePath =
null;
253 private FlutterShellArgs shellArgs =
null;
256 private boolean shouldAttachEngineToActivity =
true;
257 private boolean shouldAutomaticallyHandleOnBackPressed =
false;
258 private boolean shouldDelayFirstAndroidViewDraw =
false;
273 fragmentClass = subclass;
279 this.dartEntrypoint = dartEntrypoint;
285 this.dartLibraryUri = dartLibraryUri;
292 this.dartEntrypointArgs = dartEntrypointArgs;
302 this.initialRoute = initialRoute;
312 this.handleDeeplinking = handleDeeplinking;
323 this.appBundlePath = appBundlePath;
330 this.shellArgs = shellArgs;
342 this.renderMode = renderMode;
355 this.transparencyMode = transparencyMode;
398 boolean shouldAttachEngineToActivity) {
399 this.shouldAttachEngineToActivity = shouldAttachEngineToActivity;
420 boolean shouldAutomaticallyHandleOnBackPressed) {
421 this.shouldAutomaticallyHandleOnBackPressed = shouldAutomaticallyHandleOnBackPressed;
432 boolean shouldDelayFirstAndroidViewDraw) {
433 this.shouldDelayFirstAndroidViewDraw = shouldDelayFirstAndroidViewDraw;
445 Bundle
args =
new Bundle();
451 args.putStringArrayList(
453 dartEntrypointArgs !=
null ?
new ArrayList(dartEntrypointArgs) :
null);
456 if (
null != shellArgs) {
478 public <T extends FlutterFragment>
T build() {
480 @SuppressWarnings(
"unchecked")
481 T frag = (
T) fragmentClass.getDeclaredConstructor().newInstance();
483 throw new RuntimeException(
484 "The FlutterFragment subclass sent in the constructor ("
485 + fragmentClass.getCanonicalName()
486 +
") does not match the expected return type.");
490 frag.setArguments(
args);
493 }
catch (Exception e) {
494 throw new RuntimeException(
495 "Could not instantiate FlutterFragment subclass (" + fragmentClass.getName() +
")", e);
548 private final Class<? extends FlutterFragment> fragmentClass;
549 private final String engineId;
550 private boolean destroyEngineWithFragment =
false;
551 private boolean handleDeeplinking =
false;
554 private boolean shouldAttachEngineToActivity =
true;
555 private boolean shouldAutomaticallyHandleOnBackPressed =
false;
556 private boolean shouldDelayFirstAndroidViewDraw =
false;
563 @NonNull Class<? extends FlutterFragment> subclass, @NonNull String engineId) {
564 this.fragmentClass = subclass;
565 this.engineId = engineId;
575 boolean destroyEngineWithFragment) {
576 this.destroyEngineWithFragment = destroyEngineWithFragment;
588 this.renderMode = renderMode;
602 this.transparencyMode = transparencyMode;
612 this.handleDeeplinking = handleDeeplinking;
655 boolean shouldAttachEngineToActivity) {
656 this.shouldAttachEngineToActivity = shouldAttachEngineToActivity;
677 boolean shouldAutomaticallyHandleOnBackPressed) {
678 this.shouldAutomaticallyHandleOnBackPressed = shouldAutomaticallyHandleOnBackPressed;
689 @NonNull
boolean shouldDelayFirstAndroidViewDraw) {
690 this.shouldDelayFirstAndroidViewDraw = shouldDelayFirstAndroidViewDraw;
702 Bundle
args =
new Bundle();
724 public <T extends FlutterFragment>
T build() {
726 @SuppressWarnings(
"unchecked")
727 T frag = (
T) fragmentClass.getDeclaredConstructor().newInstance();
729 throw new RuntimeException(
730 "The FlutterFragment subclass sent in the constructor ("
731 + fragmentClass.getCanonicalName()
732 +
") does not match the expected return type.");
736 frag.setArguments(
args);
739 }
catch (Exception e) {
740 throw new RuntimeException(
741 "Could not instantiate FlutterFragment subclass (" + fragmentClass.getName() +
")", e);
758 @NonNull String engineGroupId) {
793 private final Class<? extends FlutterFragment> fragmentClass;
794 private final String cachedEngineGroupId;
795 private @NonNull String dartEntrypoint =
"main";
796 private @NonNull String initialRoute =
"/";
797 private @NonNull
boolean handleDeeplinking =
false;
800 private boolean shouldAttachEngineToActivity =
true;
801 private boolean shouldAutomaticallyHandleOnBackPressed =
false;
802 private boolean shouldDelayFirstAndroidViewDraw =
false;
809 @NonNull Class<? extends FlutterFragment> fragmentClass, @NonNull String engineGroupId) {
810 this.fragmentClass = fragmentClass;
811 this.cachedEngineGroupId = engineGroupId;
817 this.dartEntrypoint = dartEntrypoint;
827 this.initialRoute = initialRoute;
837 this.handleDeeplinking = handleDeeplinking;
849 this.renderMode = renderMode;
863 this.transparencyMode = transparencyMode;
906 boolean shouldAttachEngineToActivity) {
907 this.shouldAttachEngineToActivity = shouldAttachEngineToActivity;
928 boolean shouldAutomaticallyHandleOnBackPressed) {
929 this.shouldAutomaticallyHandleOnBackPressed = shouldAutomaticallyHandleOnBackPressed;
940 @NonNull
boolean shouldDelayFirstAndroidViewDraw) {
941 this.shouldDelayFirstAndroidViewDraw = shouldDelayFirstAndroidViewDraw;
953 Bundle
args =
new Bundle();
977 public <T extends FlutterFragment>
T build() {
979 @SuppressWarnings(
"unchecked")
980 T frag = (
T) fragmentClass.getDeclaredConstructor().newInstance();
982 throw new RuntimeException(
983 "The FlutterFragment subclass sent in the constructor ("
984 + fragmentClass.getCanonicalName()
985 +
") does not match the expected return type.");
989 frag.setArguments(
args);
992 }
catch (Exception e) {
993 throw new RuntimeException(
994 "Could not instantiate FlutterFragment subclass (" + fragmentClass.getName() +
")", e);
1004 @NonNull
private FlutterActivityAndFragmentDelegate.DelegateFactory delegateFactory =
this;
1012 private final OnBackPressedCallback onBackPressedCallback =
1013 new OnBackPressedCallback(
true) {
1015 public void handleOnBackPressed() {
1023 setArguments(
new Bundle());
1039 this.delegateFactory = delegateFactory;
1040 delegate = delegateFactory.createDelegate(
this);
1054 super.onAttach(context);
1055 delegate = delegateFactory.createDelegate(
this);
1058 requireActivity().getOnBackPressedDispatcher().addCallback(
this, onBackPressedCallback);
1060 context.registerComponentCallbacks(
this);
1064 public void onCreate(@Nullable Bundle savedInstanceState) {
1065 super.onCreate(savedInstanceState);
1072 LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
1084 if (stillAttachedForEvent(
"onStart")) {
1092 if (stillAttachedForEvent(
"onResume")) {
1099 @ActivityCallThrough
1101 if (stillAttachedForEvent(
"onPostResume")) {
1109 if (stillAttachedForEvent(
"onPause")) {
1117 if (stillAttachedForEvent(
"onStop")) {
1124 super.onViewCreated(view, savedInstanceState);
1125 view.getViewTreeObserver().addOnWindowFocusChangeListener(onWindowFocusChangeListener);
1130 super.onDestroyView();
1132 .getViewTreeObserver()
1133 .removeOnWindowFocusChangeListener(onWindowFocusChangeListener);
1134 if (stillAttachedForEvent(
"onDestroyView")) {
1141 super.onSaveInstanceState(outState);
1142 if (stillAttachedForEvent(
"onSaveInstanceState")) {
1153 +
" connection to the engine "
1155 +
" evicted by another attaching activity");
1165 getContext().unregisterComponentCallbacks(
this);
1172 Log.
v(
TAG,
"FlutterFragment " +
this +
" onDetach called after release.");
1187 @ActivityCallThrough
1189 int requestCode, @NonNull String[] permissions, @NonNull
int[] grantResults) {
1190 if (stillAttachedForEvent(
"onRequestPermissionsResult")) {
1205 @ActivityCallThrough
1207 if (stillAttachedForEvent(
"onNewIntent")) {
1220 @ActivityCallThrough
1222 if (stillAttachedForEvent(
"onBackPressed")) {
1239 if (stillAttachedForEvent(
"onActivityResult")) {
1250 @ActivityCallThrough
1252 if (stillAttachedForEvent(
"onUserLeaveHint")) {
1268 if (stillAttachedForEvent(
"onTrimMemory")) {
1282 return new FlutterShellArgs(
1283 flutterShellArgsArray !=
null ? flutterShellArgsArray :
new String[] {});
1313 return delegate.isFlutterEngineFromHost();
1325 boolean explicitDestructionRequested =
1329 return explicitDestructionRequested;
1417 String renderModeName =
1433 String transparencyModeName =
1465 FragmentActivity attachedActivity =
getActivity();
1468 Log.
v(
TAG,
"Deferring to attached Activity to provide a FlutterEngine.");
1473 return flutterEngine;
1488 @Nullable Activity activity, @NonNull
FlutterEngine flutterEngine) {
1489 if (activity !=
null) {
1490 return new PlatformPlugin(
getActivity(), flutterEngine.getPlatformChannel(),
this);
1518 FragmentActivity attachedActivity =
getActivity();
1532 FragmentActivity attachedActivity =
getActivity();
1581 FragmentActivity attachedActivity =
getActivity();
1582 if (attachedActivity instanceof FlutterUiDisplayListener) {
1583 ((FlutterUiDisplayListener) attachedActivity).onFlutterUiDisplayed();
1600 FragmentActivity attachedActivity =
getActivity();
1601 if (attachedActivity instanceof FlutterUiDisplayListener) {
1602 ((FlutterUiDisplayListener) attachedActivity).onFlutterUiNoLongerDisplayed();
1662 if (activity !=
null) {
1666 onBackPressedCallback.setEnabled(
false);
1667 activity.getOnBackPressedDispatcher().onBackPressed();
1668 onBackPressedCallback.setEnabled(
true);
1682 private boolean stillAttachedForEvent(String
event) {
1684 Log.
w(TAG,
"FlutterFragment " + hashCode() +
" " +
event +
" called after release.");
1688 Log.
w(TAG,
"FlutterFragment " + hashCode() +
" " +
event +
" called after detach.");
static void v(@NonNull String tag, @NonNull String message)
static void w(@NonNull String tag, @NonNull String message)
View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState, int flutterViewId, boolean shouldDelayFirstAndroidViewDraw)
void onActivityResult(int requestCode, int resultCode, Intent data)
void updateSystemUiOverlays()
void onAttach(@NonNull Context context)
void onTrimMemory(int level)
void onSaveInstanceState(@Nullable Bundle bundle)
void onRestoreInstanceState(@Nullable Bundle bundle)
void onWindowFocusChanged(boolean hasFocus)
void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults)
void onNewIntent(@NonNull Intent intent)
FlutterEngine getFlutterEngine()
CachedEngineFragmentBuilder shouldAutomaticallyHandleOnBackPressed(boolean shouldAutomaticallyHandleOnBackPressed)
CachedEngineFragmentBuilder destroyEngineWithFragment(boolean destroyEngineWithFragment)
CachedEngineFragmentBuilder renderMode(@NonNull RenderMode renderMode)
CachedEngineFragmentBuilder shouldDelayFirstAndroidViewDraw( @NonNull boolean shouldDelayFirstAndroidViewDraw)
CachedEngineFragmentBuilder( @NonNull Class<? extends FlutterFragment > subclass, @NonNull String engineId)
CachedEngineFragmentBuilder transparencyMode( @NonNull TransparencyMode transparencyMode)
CachedEngineFragmentBuilder shouldAttachEngineToActivity(boolean shouldAttachEngineToActivity)
public< T extends FlutterFragment > T build()
CachedEngineFragmentBuilder handleDeeplinking(@NonNull Boolean handleDeeplinking)
public< T extends FlutterFragment > T build()
NewEngineFragmentBuilder renderMode(@NonNull RenderMode renderMode)
NewEngineFragmentBuilder initialRoute(@NonNull String initialRoute)
NewEngineFragmentBuilder shouldDelayFirstAndroidViewDraw(boolean shouldDelayFirstAndroidViewDraw)
NewEngineFragmentBuilder()
NewEngineFragmentBuilder transparencyMode(@NonNull TransparencyMode transparencyMode)
NewEngineFragmentBuilder(@NonNull Class<? extends FlutterFragment > subclass)
NewEngineFragmentBuilder handleDeeplinking(@NonNull Boolean handleDeeplinking)
NewEngineFragmentBuilder dartEntrypointArgs(@NonNull List< String > dartEntrypointArgs)
NewEngineFragmentBuilder dartEntrypoint(@NonNull String dartEntrypoint)
NewEngineFragmentBuilder flutterShellArgs(@NonNull FlutterShellArgs shellArgs)
NewEngineFragmentBuilder shouldAutomaticallyHandleOnBackPressed(boolean shouldAutomaticallyHandleOnBackPressed)
NewEngineFragmentBuilder shouldAttachEngineToActivity(boolean shouldAttachEngineToActivity)
NewEngineFragmentBuilder dartLibraryUri(@NonNull String dartLibraryUri)
NewEngineFragmentBuilder appBundlePath(@NonNull String appBundlePath)
public< T extends FlutterFragment > T build()
NewEngineInGroupFragmentBuilder handleDeeplinking(@NonNull boolean handleDeeplinking)
NewEngineInGroupFragmentBuilder initialRoute(@NonNull String initialRoute)
NewEngineInGroupFragmentBuilder(@NonNull String engineGroupId)
NewEngineInGroupFragmentBuilder( @NonNull Class<? extends FlutterFragment > fragmentClass, @NonNull String engineGroupId)
NewEngineInGroupFragmentBuilder shouldDelayFirstAndroidViewDraw( @NonNull boolean shouldDelayFirstAndroidViewDraw)
NewEngineInGroupFragmentBuilder renderMode(@NonNull RenderMode renderMode)
NewEngineInGroupFragmentBuilder shouldAutomaticallyHandleOnBackPressed(boolean shouldAutomaticallyHandleOnBackPressed)
NewEngineInGroupFragmentBuilder transparencyMode( @NonNull TransparencyMode transparencyMode)
NewEngineInGroupFragmentBuilder dartEntrypoint(@NonNull String dartEntrypoint)
NewEngineInGroupFragmentBuilder shouldAttachEngineToActivity(boolean shouldAttachEngineToActivity)
static final String ARG_DART_ENTRYPOINT_ARGS
void onSaveInstanceState(Bundle outState)
void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults)
String getCachedEngineGroupId()
View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState)
void onFlutterSurfaceViewCreated(@NonNull FlutterSurfaceView flutterSurfaceView)
static final String ARG_ENABLE_STATE_RESTORATION
List< String > getDartEntrypointArgs()
static final String ARG_APP_BUNDLE_PATH
void onFlutterTextureViewCreated(@NonNull FlutterTextureView flutterTextureView)
String getAppBundlePath()
FlutterShellArgs getFlutterShellArgs()
static final String ARG_FLUTTERVIEW_RENDER_MODE
boolean popSystemNavigator()
static NewEngineFragmentBuilder withNewEngine()
static final int FLUTTER_VIEW_ID
void onViewCreated(View view, Bundle savedInstanceState)
FlutterEngine getFlutterEngine()
static final String ARG_DART_ENTRYPOINT_URI
static final String ARG_INITIAL_ROUTE
void onCreate(@Nullable Bundle savedInstanceState)
boolean shouldHandleDeeplinking()
static final String ARG_DART_ENTRYPOINT
static FlutterFragment createDefault()
String getDartEntrypointFunctionName()
static final String ARG_DESTROY_ENGINE_WITH_FRAGMENT
boolean shouldDelayFirstAndroidViewDraw()
static NewEngineInGroupFragmentBuilder withNewEngineInGroup( @NonNull String engineGroupId)
void detachFromFlutterEngine()
static final String ARG_SHOULD_AUTOMATICALLY_HANDLE_ON_BACK_PRESSED
FlutterActivityAndFragmentDelegate createDelegate(FlutterActivityAndFragmentDelegate.Host host)
void configureFlutterEngine(@NonNull FlutterEngine flutterEngine)
boolean shouldAttachEngineToActivity()
void onActivityResult(int requestCode, int resultCode, Intent data)
static CachedEngineFragmentBuilder withCachedEngine(@NonNull String engineId)
boolean attachToEngineAutomatically()
void onTrimMemory(int level)
String getDartEntrypointLibraryUri()
PlatformPlugin providePlatformPlugin( @Nullable Activity activity, @NonNull FlutterEngine flutterEngine)
boolean shouldDispatchAppLifecycleState()
static final String ARG_HANDLE_DEEPLINKING
static final String ARG_CACHED_ENGINE_ID
TransparencyMode getTransparencyMode()
void onFlutterUiDisplayed()
void updateSystemUiOverlays()
static final String ARG_FLUTTERVIEW_TRANSPARENCY_MODE
RenderMode getRenderMode()
ExclusiveAppComponent< Activity > getExclusiveAppComponent()
boolean shouldDestroyEngineWithHost()
FlutterEngine provideFlutterEngine(@NonNull Context context)
static final String ARG_SHOULD_ATTACH_ENGINE_TO_ACTIVITY
static final String ARG_FLUTTER_INITIALIZATION_ARGS
String getCachedEngineId()
void setDelegateFactory( @NonNull FlutterActivityAndFragmentDelegate.DelegateFactory delegateFactory)
static final String ARG_CACHED_ENGINE_GROUP_ID
static final String ARG_SHOULD_DELAY_FIRST_ANDROID_VIEW_DRAW
void cleanUpFlutterEngine(@NonNull FlutterEngine flutterEngine)
void onAttach(@NonNull Context context)
void onNewIntent(@NonNull Intent intent)
boolean isFlutterEngineInjected()
void onFlutterUiNoLongerDisplayed()
boolean shouldRestoreAndSaveState()
FlutterActivityAndFragmentDelegate delegate
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
FlutterEngine provideFlutterEngine(@NonNull Context context)