@@ -66,6 +66,7 @@ public class FlutterFragment extends Fragment {
66
66
protected static final String ARG_FLUTTER_INITIALIZATION_ARGS = "initialization_args" ;
67
67
protected static final String ARG_FLUTTERVIEW_RENDER_MODE = "flutterview_render_mode" ;
68
68
protected static final String ARG_FLUTTERVIEW_TRANSPARENCY_MODE = "flutterview_transparency_mode" ;
69
+ protected static final String ARG_SHOULD_ATTACH_ENGINE_TO_ACTIVITY = "should_attach_engine_to_activity" ;
69
70
70
71
/**
71
72
* Builder that creates a new {@code FlutterFragment} with {@code arguments} that correspond
@@ -118,6 +119,7 @@ public static class Builder {
118
119
private FlutterShellArgs shellArgs = null ;
119
120
private FlutterView .RenderMode renderMode = FlutterView .RenderMode .surface ;
120
121
private FlutterView .TransparencyMode transparencyMode = FlutterView .TransparencyMode .transparent ;
122
+ private boolean shouldAttachEngineToActivity = true ;
121
123
122
124
/**
123
125
* Constructs a {@code Builder} that is configured to construct an instance of
@@ -199,6 +201,46 @@ public Builder transparencyMode(@NonNull FlutterView.TransparencyMode transparen
199
201
return this ;
200
202
}
201
203
204
+ /**
205
+ * Whether or not this {@code FlutterFragment} should automatically attach its
206
+ * {@code Activity} as a control surface for its {@link FlutterEngine}.
207
+ * <p>
208
+ * Control surfaces are used to provide Android resources and lifecycle events to
209
+ * plugins that are attached to the {@link FlutterEngine}. If {@code shouldAttachEngineToActivity}
210
+ * is true then this {@code FlutterFragment} will connect its {@link FlutterEngine} to the
211
+ * surrounding {@code Activity}, along with any plugins that are registered with that
212
+ * {@link FlutterEngine}. This allows plugins to access the {@code Activity}, as well as
213
+ * receive {@code Activity}-specific calls, e.g., {@link android.app.Activity#onNewIntent(Intent)}.
214
+ * If {@code shouldAttachEngineToActivity} is false, then this {@code FlutterFragment} will not
215
+ * automatically manage the connection between its {@link FlutterEngine} and the surrounding
216
+ * {@code Activity}. The {@code Activity} will need to be manually connected to this
217
+ * {@code FlutterFragment}'s {@link FlutterEngine} by the app developer. See
218
+ * {@link FlutterEngine#getActivityControlSurface()}.
219
+ * <p>
220
+ * One reason that a developer might choose to manually manage the relationship between the
221
+ * {@code Activity} and {@link FlutterEngine} is if the developer wants to move the
222
+ * {@link FlutterEngine} somewhere else. For example, a developer might want the
223
+ * {@link FlutterEngine} to outlive the surrounding {@code Activity} so that it can be used
224
+ * later in a different {@code Activity}. To accomplish this, the {@link FlutterEngine} will
225
+ * need to be disconnected from the surrounding {@code Activity} at an unusual time, preventing
226
+ * this {@code FlutterFragment} from correctly managing the relationship between the
227
+ * {@link FlutterEngine} and the surrounding {@code Activity}.
228
+ * <p>
229
+ * Another reason that a developer might choose to manually manage the relationship between the
230
+ * {@code Activity} and {@link FlutterEngine} is if the developer wants to prevent, or explicitly
231
+ * control when the {@link FlutterEngine}'s plugins have access to the surrounding {@code Activity}.
232
+ * For example, imagine that this {@code FlutterFragment} only takes up part of the screen and
233
+ * the app developer wants to ensure that none of the Flutter plugins are able to manipulate
234
+ * the surrounding {@code Activity}. In this case, the developer would not want the
235
+ * {@link FlutterEngine} to have access to the {@code Activity}, which can be accomplished by
236
+ * setting {@code shouldAttachEngineToActivity} to {@code false}.
237
+ */
238
+ @ NonNull
239
+ public Builder shouldAttachEngineToActivity (boolean shouldAttachEngineToActivity ) {
240
+ this .shouldAttachEngineToActivity = shouldAttachEngineToActivity ;
241
+ return this ;
242
+ }
243
+
202
244
/**
203
245
* Creates a {@link Bundle} of arguments that are assigned to the new {@code FlutterFragment}.
204
246
* <p>
@@ -217,6 +259,7 @@ protected Bundle createArgs() {
217
259
}
218
260
args .putString (ARG_FLUTTERVIEW_RENDER_MODE , renderMode != null ? renderMode .name () : FlutterView .RenderMode .surface .name ());
219
261
args .putString (ARG_FLUTTERVIEW_TRANSPARENCY_MODE , transparencyMode != null ? transparencyMode .name () : FlutterView .TransparencyMode .transparent .name ());
262
+ args .putBoolean (ARG_SHOULD_ATTACH_ENGINE_TO_ACTIVITY , shouldAttachEngineToActivity );
220
263
return args ;
221
264
}
222
265
@@ -303,10 +346,12 @@ public void onAttach(Context context) {
303
346
// use-cases.
304
347
platformPlugin = new PlatformPlugin (getActivity (), flutterEngine .getPlatformChannel ());
305
348
306
- // Notify any plugins that are currently attached to our FlutterEngine that they
307
- // are now attached to an Activity.
308
- // TODO(mattcarroll): send in a real lifecycle.
309
- flutterEngine .getActivityControlSurface ().attachToActivity (getActivity (), null );
349
+ if (shouldAttachEngineToActivity ()) {
350
+ // Notify any plugins that are currently attached to our FlutterEngine that they
351
+ // are now attached to an Activity.
352
+ // TODO(mattcarroll): send in a real lifecycle.
353
+ flutterEngine .getActivityControlSurface ().attachToActivity (getActivity (), null );
354
+ }
310
355
}
311
356
312
357
private void initializeFlutter (@ NonNull Context context ) {
@@ -543,9 +588,11 @@ public void onDetach() {
543
588
super .onDetach ();
544
589
Log .d (TAG , "onDetach()" );
545
590
546
- // Notify plugins that they are no longer attached to an Activity.
547
- // TODO(mattcarroll): differentiate between detaching for config changes and otherwise.
548
- flutterEngine .getActivityControlSurface ().detachFromActivity ();
591
+ if (shouldAttachEngineToActivity ()) {
592
+ // Notify plugins that they are no longer attached to an Activity.
593
+ // TODO(mattcarroll): differentiate between detaching for config changes and otherwise.
594
+ flutterEngine .getActivityControlSurface ().detachFromActivity ();
595
+ }
549
596
550
597
// Null out the platformPlugin to avoid a possible retain cycle between the plugin, this Fragment,
551
598
// and this Fragment's Activity.
@@ -572,6 +619,10 @@ protected boolean retainFlutterEngineAfterFragmentDestruction() {
572
619
return false ;
573
620
}
574
621
622
+ protected boolean shouldAttachEngineToActivity () {
623
+ return getArguments ().getBoolean (ARG_SHOULD_ATTACH_ENGINE_TO_ACTIVITY );
624
+ }
625
+
575
626
/**
576
627
* The hardware back button was pressed.
577
628
*
0 commit comments