1010import static io .flutter .embedding .android .FlutterActivityLaunchConfigs .DEFAULT_DART_ENTRYPOINT ;
1111import static io .flutter .embedding .android .FlutterActivityLaunchConfigs .DEFAULT_INITIAL_ROUTE ;
1212import static io .flutter .embedding .android .FlutterActivityLaunchConfigs .EXTRA_BACKGROUND_MODE ;
13+ import static io .flutter .embedding .android .FlutterActivityLaunchConfigs .EXTRA_CACHED_ENGINE_GROUP_ID ;
1314import static io .flutter .embedding .android .FlutterActivityLaunchConfigs .EXTRA_CACHED_ENGINE_ID ;
15+ import static io .flutter .embedding .android .FlutterActivityLaunchConfigs .EXTRA_DART_ENTRYPOINT ;
1416import static io .flutter .embedding .android .FlutterActivityLaunchConfigs .EXTRA_DART_ENTRYPOINT_ARGS ;
1517import static io .flutter .embedding .android .FlutterActivityLaunchConfigs .EXTRA_DESTROY_ENGINE_WITH_ACTIVITY ;
1618import static io .flutter .embedding .android .FlutterActivityLaunchConfigs .EXTRA_ENABLE_STATE_RESTORATION ;
@@ -276,7 +278,7 @@ public NewEngineIntentBuilder(@NonNull Class<? extends FlutterActivity> activity
276278 }
277279
278280 /**
279- * The initial route that a Flutter app will render in this {@link FlutterFragment }, defaults to
281+ * The initial route that a Flutter app will render in this {@link FlutterActivity }, defaults to
280282 * "/".
281283 *
282284 * @param initialRoute The route.
@@ -448,6 +450,149 @@ public Intent build(@NonNull Context context) {
448450 }
449451 }
450452
453+ /**
454+ * Creates a {@link NewEngineInGroupIntentBuilder}, which can be used to configure an {@link
455+ * Intent} to launch a {@code FlutterActivity} by internally creating a FlutterEngine from an
456+ * existing {@link io.flutter.embedding.engine.FlutterEngineGroup} cached in a specified {@link
457+ * io.flutter.embedding.engine.FlutterEngineGroupCache}.
458+ *
459+ * <pre>{@code
460+ * // Create a FlutterEngineGroup, such as in the onCreate method of the Application.
461+ * FlutterEngineGroup engineGroup = new FlutterEngineGroup(this);
462+ * FlutterEngineGroupCache.getInstance().put("my_cached_engine_group_id", engineGroup);
463+ *
464+ * // Start a FlutterActivity with the FlutterEngineGroup by creating an intent with withNewEngineInGroup
465+ * Intent intent = FlutterActivity.withNewEngineInGroup("my_cached_engine_group_id")
466+ * .dartEntrypoint("custom_entrypoint")
467+ * .initialRoute("/custom/route")
468+ * .backgroundMode(BackgroundMode.transparent)
469+ * .build(context);
470+ * startActivity(intent);
471+ * }</pre>
472+ *
473+ * @param engineGroupId A cached engine group ID.
474+ * @return The builder.
475+ */
476+ public static NewEngineInGroupIntentBuilder withNewEngineInGroup (@ NonNull String engineGroupId ) {
477+ return new NewEngineInGroupIntentBuilder (FlutterActivity .class , engineGroupId );
478+ }
479+
480+ /**
481+ * Builder to create an {@code Intent} that launches a {@code FlutterActivity} with a new {@link
482+ * FlutterEngine} created by FlutterEngineGroup#createAndRunEngine.
483+ */
484+ public static class NewEngineInGroupIntentBuilder {
485+ private final Class <? extends FlutterActivity > activityClass ;
486+ private final String cachedEngineGroupId ;
487+ private String dartEntrypoint = DEFAULT_DART_ENTRYPOINT ;
488+ private String initialRoute = DEFAULT_INITIAL_ROUTE ;
489+ private String backgroundMode = DEFAULT_BACKGROUND_MODE ;
490+
491+ /**
492+ * Constructor that allows this {@code NewEngineInGroupIntentBuilder} to be used by subclasses
493+ * of {@code FlutterActivity}.
494+ *
495+ * <p>Subclasses of {@code FlutterActivity} should provide their own static version of {@link
496+ * #withNewEngineInGroup}, which returns an instance of {@code NewEngineInGroupIntentBuilder}
497+ * constructed with a {@code Class} reference to the {@code FlutterActivity} subclass, e.g.:
498+ *
499+ * <p>{@code return new NewEngineInGroupIntentBuilder(MyFlutterActivity.class,
500+ * cacheedEngineGroupId); }
501+ *
502+ * <pre>{@code
503+ * // Create a FlutterEngineGroup, such as in the onCreate method of the Application.
504+ * FlutterEngineGroup engineGroup = new FlutterEngineGroup(this);
505+ * FlutterEngineGroupCache.getInstance().put("my_cached_engine_group_id", engineGroup);
506+ *
507+ * // Create a NewEngineInGroupIntentBuilder that would build an intent to start my custom FlutterActivity subclass.
508+ * FlutterActivity.NewEngineInGroupIntentBuilder intentBuilder =
509+ * new FlutterActivity.NewEngineInGroupIntentBuilder(
510+ * MyFlutterActivity.class,
511+ * app.engineGroupId);
512+ * intentBuilder.dartEntrypoint("main")
513+ * .initialRoute("/custom/route")
514+ * .backgroundMode(BackgroundMode.transparent);
515+ * startActivity(intentBuilder.build(context));
516+ * }</pre>
517+ *
518+ * @param activityClass A subclass of {@code FlutterActivity}.
519+ * @param engineGroupId The engine group id.
520+ */
521+ public NewEngineInGroupIntentBuilder (
522+ @ NonNull Class <? extends FlutterActivity > activityClass , @ NonNull String engineGroupId ) {
523+ this .activityClass = activityClass ;
524+ this .cachedEngineGroupId = engineGroupId ;
525+ }
526+
527+ /**
528+ * The Dart entrypoint that will be executed in the newly created FlutterEngine as soon as the
529+ * Dart snapshot is loaded. Default to "main".
530+ *
531+ * @param dartEntrypoint The dart entrypoint's name
532+ * @return The engine group intent builder
533+ */
534+ @ NonNull
535+ public NewEngineInGroupIntentBuilder dartEntrypoint (@ NonNull String dartEntrypoint ) {
536+ this .dartEntrypoint = dartEntrypoint ;
537+ return this ;
538+ }
539+
540+ /**
541+ * The initial route that a Flutter app will render in this {@link FlutterActivity}, defaults to
542+ * "/".
543+ *
544+ * @param initialRoute The route.
545+ * @return The engine group intent builder.
546+ */
547+ @ NonNull
548+ public NewEngineInGroupIntentBuilder initialRoute (@ NonNull String initialRoute ) {
549+ this .initialRoute = initialRoute ;
550+ return this ;
551+ }
552+
553+ /**
554+ * The mode of {@code FlutterActivity}'s background, either {@link BackgroundMode#opaque} or
555+ * {@link BackgroundMode#transparent}.
556+ *
557+ * <p>The default background mode is {@link BackgroundMode#opaque}.
558+ *
559+ * <p>Choosing a background mode of {@link BackgroundMode#transparent} will configure the inner
560+ * {@link FlutterView} of this {@code FlutterActivity} to be configured with a {@link
561+ * FlutterTextureView} to support transparency. This choice has a non-trivial performance
562+ * impact. A transparent background should only be used if it is necessary for the app design
563+ * being implemented.
564+ *
565+ * <p>A {@code FlutterActivity} that is configured with a background mode of {@link
566+ * BackgroundMode#transparent} must have a theme applied to it that includes the following
567+ * property: {@code <item name="android:windowIsTranslucent">true</item>}.
568+ *
569+ * @param backgroundMode The background mode.
570+ * @return The engine group intent builder.
571+ */
572+ @ NonNull
573+ public NewEngineInGroupIntentBuilder backgroundMode (@ NonNull BackgroundMode backgroundMode ) {
574+ this .backgroundMode = backgroundMode .name ();
575+ return this ;
576+ }
577+
578+ /**
579+ * Creates and returns an {@link Intent} that will launch a {@code FlutterActivity} with the
580+ * desired configuration.
581+ *
582+ * @param context The context. e.g. An Activity.
583+ * @return The intent.
584+ */
585+ @ NonNull
586+ public Intent build (@ NonNull Context context ) {
587+ return new Intent (context , activityClass )
588+ .putExtra (EXTRA_DART_ENTRYPOINT , dartEntrypoint )
589+ .putExtra (EXTRA_INITIAL_ROUTE , initialRoute )
590+ .putExtra (EXTRA_CACHED_ENGINE_GROUP_ID , cachedEngineGroupId )
591+ .putExtra (EXTRA_BACKGROUND_MODE , backgroundMode )
592+ .putExtra (EXTRA_DESTROY_ENGINE_WITH_ACTIVITY , true );
593+ }
594+ }
595+
451596 // Delegate that runs all lifecycle and OS hook logic that is common between
452597 // FlutterActivity and FlutterFragment. See the FlutterActivityAndFragmentDelegate
453598 // implementation for details about why it exists.
@@ -866,6 +1011,17 @@ public String getCachedEngineId() {
8661011 return getIntent ().getStringExtra (EXTRA_CACHED_ENGINE_ID );
8671012 }
8681013
1014+ /**
1015+ * Returns the ID of a statically cached {@link io.flutter.embedding.engine.FlutterEngineGroup} to
1016+ * use within this {@code FlutterActivity}, or {@code null} if this {@code FlutterActivity} does
1017+ * not want to use a cached {@link io.flutter.embedding.engine.FlutterEngineGroup}.
1018+ */
1019+ @ Override
1020+ @ Nullable
1021+ public String getCachedEngineGroupId () {
1022+ return getIntent ().getStringExtra (EXTRA_CACHED_ENGINE_GROUP_ID );
1023+ }
1024+
8691025 /**
8701026 * Returns false if the {@link io.flutter.embedding.engine.FlutterEngine} backing this {@code
8711027 * FlutterActivity} should outlive this {@code FlutterActivity}, or true to be destroyed when the
@@ -892,14 +1048,26 @@ public boolean shouldDestroyEngineWithHost() {
8921048 /**
8931049 * The Dart entrypoint that will be executed as soon as the Dart snapshot is loaded.
8941050 *
895- * <p>This preference can be controlled by setting a {@code <meta-data>} called {@link
896- * FlutterActivityLaunchConfigs#DART_ENTRYPOINT_META_DATA_KEY} within the Android manifest
897- * definition for this {@code FlutterActivity}.
1051+ * <p>This preference can be controlled with 2 methods:
1052+ *
1053+ * <ol>
1054+ * <li>Pass a boolean as {@link FlutterActivityLaunchConfigs#EXTRA_DART_ENTRYPOINT} with the
1055+ * launching {@code Intent}, or
1056+ * <li>Set a {@code <meta-data>} called {@link
1057+ * FlutterActivityLaunchConfigs#DART_ENTRYPOINT_META_DATA_KEY} within the Android manifest
1058+ * definition for this {@code FlutterActivity}
1059+ * </ol>
1060+ *
1061+ * If both preferences are set, the {@code Intent} preference takes priority.
8981062 *
8991063 * <p>Subclasses may override this method to directly control the Dart entrypoint.
9001064 */
9011065 @ NonNull
9021066 public String getDartEntrypointFunctionName () {
1067+ if (getIntent ().hasExtra (EXTRA_DART_ENTRYPOINT )) {
1068+ return getIntent ().getStringExtra (EXTRA_DART_ENTRYPOINT );
1069+ }
1070+
9031071 try {
9041072 Bundle metaData = getMetaData ();
9051073 String desiredDartEntrypoint =
0 commit comments