Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions shell/platform/android/io/flutter/FlutterInjector.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public final class FlutterInjector {
* <p>This can only be called at the beginning of the program before the {@link #instance()} is
* accessed.
*/
@VisibleForTesting
public static void setInstance(@NonNull FlutterInjector injector) {
if (accessed) {
throw new IllegalStateException(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@
import io.flutter.embedding.engine.plugins.activity.ActivityControlSurface;
import io.flutter.embedding.engine.plugins.util.GeneratedPluginRegister;
import io.flutter.plugin.platform.PlatformPlugin;
import io.flutter.view.FlutterMain;

/**
* {@code Activity} which displays a fullscreen Flutter UI.
Expand Down Expand Up @@ -754,12 +753,14 @@ public String getInitialRoute() {
}

/**
* The path to the bundle that contains this Flutter app's resources, e.g., Dart code snapshots.
* A custom path to the bundle that contains this Flutter app's resources, e.g., Dart code
* snapshots.
*
* <p>When this {@code FlutterActivity} is run by Flutter tooling and a data String is included in
* the launching {@code Intent}, that data String is interpreted as an app bundle path.
*
* <p>By default, the app bundle path is obtained from {@link FlutterMain#findAppBundlePath()}.
* <p>When otherwise unspecified, the value is null, which defaults to the app bundle path defined
* in {@link FlutterLoader#findAppBundlePath()}.
*
* <p>Subclasses may override this method to return a custom app bundle path.
*/
Expand All @@ -776,9 +777,7 @@ public String getAppBundlePath() {
}
}

// Return the default app bundle path.
// TODO(mattcarroll): move app bundle resolution into an appropriately named class.
return FlutterMain.findAppBundlePath();
return null;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import androidx.lifecycle.Lifecycle;
import io.flutter.FlutterInjector;
import io.flutter.Log;
import io.flutter.app.FlutterActivity;
import io.flutter.embedding.engine.FlutterEngine;
Expand Down Expand Up @@ -366,10 +367,15 @@ private void doInitialFlutterViewRun() {
flutterEngine.getNavigationChannel().setInitialRoute(host.getInitialRoute());
}

String appBundlePathOverride = host.getAppBundlePath();
if (appBundlePathOverride == null || appBundlePathOverride.isEmpty()) {
appBundlePathOverride = FlutterInjector.instance().flutterLoader().findAppBundlePath();
}

// Configure the Dart entrypoint and execute it.
DartExecutor.DartEntrypoint entrypoint =
new DartExecutor.DartEntrypoint(
host.getAppBundlePath(), host.getDartEntrypointFunctionName());
appBundlePathOverride, host.getDartEntrypointFunctionName());
flutterEngine.getDartExecutor().executeDartEntrypoint(entrypoint);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import io.flutter.embedding.engine.FlutterShellArgs;
import io.flutter.embedding.engine.renderer.FlutterUiDisplayListener;
import io.flutter.plugin.platform.PlatformPlugin;
import io.flutter.view.FlutterMain;

/**
* {@code Fragment} which displays a Flutter UI that takes up all available {@code Fragment} space.
Expand Down Expand Up @@ -226,8 +225,8 @@ public NewEngineFragmentBuilder initialRoute(@NonNull String initialRoute) {
}

/**
* The path to the app bundle which contains the Dart app to execute, defaults to {@link
* FlutterMain#findAppBundlePath()}
* The path to the app bundle which contains the Dart app to execute. Null when unspecified,
* which defaults to {@link FlutterLoader#findAppBundlePath()}
*/
@NonNull
public NewEngineFragmentBuilder appBundlePath(@NonNull String appBundlePath) {
Expand Down Expand Up @@ -800,16 +799,18 @@ public String getDartEntrypointFunctionName() {
}

/**
* Returns the file path to the desired Flutter app's bundle of code.
* A custom path to the bundle that contains this Flutter app's resources, e.g., Dart code
* snapshots.
*
* <p>Defaults to {@link FlutterMain#findAppBundlePath()}.
* <p>When unspecified, the value is null, which defaults to the app bundle path defined in {@link
* FlutterLoader#findAppBundlePath()}.
*
* <p>Used by this {@code FlutterFragment}'s {@link FlutterActivityAndFragmentDelegate.Host}
*/
@Override
@NonNull
public String getAppBundlePath() {
return getArguments().getString(ARG_APP_BUNDLE_PATH, FlutterMain.findAppBundlePath());
return getArguments().getString(ARG_APP_BUNDLE_PATH);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@
import io.flutter.embedding.engine.FlutterShellArgs;
import io.flutter.embedding.engine.plugins.util.GeneratedPluginRegister;
import io.flutter.plugin.platform.PlatformPlugin;
import io.flutter.view.FlutterMain;

/**
* A Flutter {@code Activity} that is based upon {@link FragmentActivity}.
Expand Down Expand Up @@ -581,14 +580,15 @@ public void cleanUpFlutterEngine(@NonNull FlutterEngine flutterEngine) {
}

/**
* The path to the bundle that contains this Flutter app's resources, e.g., Dart code snapshots.
* A custom path to the bundle that contains this Flutter app's resources, e.g., Dart code
* snapshots.
*
* <p>When this {@code FlutterFragmentActivity} is run by Flutter tooling and a data String is
* included in the launching {@code Intent}, that data String is interpreted as an app bundle
* path.
*
* <p>By default, the app bundle path is obtained from {@link
* FlutterMain#findAppBundlePath(Context)}.
* <p>When otherwise unspecified, the value is null, which defaults to the app bundle path defined
* in {@link FlutterLoader#findAppBundlePath()}.
*
* <p>Subclasses may override this method to return a custom app bundle path.
*/
Expand All @@ -605,9 +605,7 @@ protected String getAppBundlePath() {
}
}

// Return the default app bundle path.
// TODO(mattcarroll): move app bundle resolution into an appropriately named class.
return FlutterMain.findAppBundlePath();
return null;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,13 @@
import android.content.Intent;
import androidx.annotation.NonNull;
import androidx.lifecycle.Lifecycle;
import io.flutter.FlutterInjector;
import io.flutter.embedding.android.FlutterActivityAndFragmentDelegate.Host;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.embedding.engine.FlutterEngineCache;
import io.flutter.embedding.engine.FlutterShellArgs;
import io.flutter.embedding.engine.dart.DartExecutor;
import io.flutter.embedding.engine.loader.FlutterLoader;
import io.flutter.embedding.engine.plugins.activity.ActivityControlSurface;
import io.flutter.embedding.engine.renderer.FlutterRenderer;
import io.flutter.embedding.engine.systemchannels.AccessibilityChannel;
Expand Down Expand Up @@ -51,6 +53,7 @@ public class FlutterActivityAndFragmentDelegateTest {

@Before
public void setup() {
FlutterInjector.reset();
// Create a mocked FlutterEngine for the various interactions required by the delegate
// being tested.
mockFlutterEngine = mockFlutterEngine();
Expand Down Expand Up @@ -307,6 +310,35 @@ public void itExecutesDartEntrypointProvidedByHost() {
verify(mockFlutterEngine.getDartExecutor(), times(1)).executeDartEntrypoint(eq(dartEntrypoint));
}

@Test
public void itUsesDefaultFlutterLoaderAppBundlePathWhenUnspecified() {
// ---- Test setup ----
FlutterLoader mockFlutterLoader = mock(FlutterLoader.class);
when(mockFlutterLoader.findAppBundlePath()).thenReturn("default_flutter_assets/path");
FlutterInjector.setInstance(
new FlutterInjector.Builder().setFlutterLoader(mockFlutterLoader).build());
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that other episode's so I can add this


// Set Dart entrypoint parameters on fake host.
when(mockHost.getAppBundlePath()).thenReturn(null);
when(mockHost.getDartEntrypointFunctionName()).thenReturn("myEntrypoint");

// Create the DartEntrypoint that we expect to be executed.
DartExecutor.DartEntrypoint dartEntrypoint =
new DartExecutor.DartEntrypoint("default_flutter_assets/path", "myEntrypoint");

// Create the real object that we're testing.
FlutterActivityAndFragmentDelegate delegate = new FlutterActivityAndFragmentDelegate(mockHost);

// --- Execute the behavior under test ---
// Dart is executed in onStart().
delegate.onAttach(RuntimeEnvironment.application);
delegate.onCreateView(null, null, null);
delegate.onStart();

// Verify that the host's Dart entrypoint was used.
verify(mockFlutterEngine.getDartExecutor(), times(1)).executeDartEntrypoint(eq(dartEntrypoint));
}

// "Attaching" to the surrounding Activity refers to Flutter being able to control
// system chrome and other Activity-level details. If Flutter is not attached to the
// surrounding Activity, it cannot control those details. This includes plugins.
Expand Down