未验证 提交 f336e05a 编写于 作者: M Matt Carroll 提交者: GitHub

Android Embedding PR37: Separated FlutterActivity and FlutterFragment via...

Android Embedding PR37: Separated FlutterActivity and FlutterFragment via FlutterActivityAndFragmentDelegate (#9895)

上级 98b13abc
......@@ -474,7 +474,7 @@ deps = {
'packages': [
{
'package': 'flutter/android/robolectric_bundle',
'version': 'last_updated:2019-07-22@11:16:04-07:00'
'version': 'last_updated:2019-07-29T15:27:42-0700'
}
],
'condition': 'download_android_deps',
......
......@@ -551,12 +551,16 @@ FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/android/Andro
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/android/AndroidTouchProcessor.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/android/DrawableSplashScreen.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/android/FlutterActivityAndFragmentDelegate.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/android/FlutterEngineConfigurator.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/android/FlutterEngineProvider.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/android/FlutterFragment.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/android/FlutterSplashView.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/android/FlutterSurfaceView.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/android/FlutterTextureView.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/android/FlutterView.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/android/SplashScreen.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/android/SplashScreenProvider.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/FlutterEngine.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/FlutterEngineAndroidLifecycle.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/FlutterEnginePluginRegistry.java
......
......@@ -127,12 +127,16 @@ action("flutter_shell_java") {
"io/flutter/embedding/android/AndroidTouchProcessor.java",
"io/flutter/embedding/android/DrawableSplashScreen.java",
"io/flutter/embedding/android/FlutterActivity.java",
"io/flutter/embedding/android/FlutterActivityAndFragmentDelegate.java",
"io/flutter/embedding/android/FlutterEngineConfigurator.java",
"io/flutter/embedding/android/FlutterEngineProvider.java",
"io/flutter/embedding/android/FlutterFragment.java",
"io/flutter/embedding/android/FlutterSplashView.java",
"io/flutter/embedding/android/FlutterSurfaceView.java",
"io/flutter/embedding/android/FlutterTextureView.java",
"io/flutter/embedding/android/FlutterView.java",
"io/flutter/embedding/android/SplashScreen.java",
"io/flutter/embedding/android/SplashScreenProvider.java",
"io/flutter/embedding/engine/FlutterEngine.java",
"io/flutter/embedding/engine/FlutterEngineAndroidLifecycle.java",
"io/flutter/embedding/engine/FlutterEnginePluginRegistry.java",
......@@ -325,6 +329,7 @@ action("robolectric_tests") {
sources = [
"test/io/flutter/FlutterTestSuite.java",
"test/io/flutter/SmokeTest.java",
"test/io/flutter/embedding/android/FlutterActivityAndFragmentDelegateTest.java",
"test/io/flutter/util/PreconditionsTest.java",
]
......@@ -340,7 +345,13 @@ action("robolectric_tests") {
"//third_party/robolectric/lib/junit-3.8.jar",
"//third_party/robolectric/lib/junit-4.13-beta-3.jar",
"//third_party/robolectric/lib/robolectric-3.8.jar",
"//third_party/robolectric/lib/shadows-framework-3.8.jar",
"//third_party/robolectric/lib/annotations-3.8.jar",
"//third_party/robolectric/lib/runtime-1.1.1.jar",
"//third_party/robolectric/lib/common-1.1.1.jar",
"//third_party/robolectric/lib/common-java8-1.1.1.jar",
"//third_party/robolectric/lib/support-annotations-28.0.0.jar",
"//third_party/robolectric/lib/mockito-all-1.10.19.jar",
]
inputs = _jar_dependencies
......
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package io.flutter.embedding.android;
import android.app.Activity;
import android.arch.lifecycle.Lifecycle;
import android.support.annotation.NonNull;
import android.support.v4.app.FragmentActivity;
import io.flutter.embedding.engine.FlutterEngine;
/**
* Configures a {@link FlutterEngine} after it is created, e.g., adds plugins.
* <p>
* This interface may be applied to a {@link FragmentActivity} that owns a {@code FlutterFragment}.
*/
public interface FlutterEngineConfigurator {
/**
* Configures the given {@link FlutterEngine}.
* <p>
* This method is called after the given {@link FlutterEngine} has been attached to the
* owning {@code FragmentActivity}. See
* {@link io.flutter.embedding.engine.plugins.activity.ActivityControlSurface#attachToActivity(Activity, Lifecycle)}.
* <p>
* It is possible that the owning {@code FragmentActivity} opted not to connect itself as
* an {@link io.flutter.embedding.engine.plugins.activity.ActivityControlSurface}. In that
* case, any configuration, e.g., plugins, must not expect or depend upon an available
* {@code Activity} at the time that this method is invoked.
*/
void configureFlutterEngine(@NonNull FlutterEngine flutterEngine);
}
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package io.flutter.embedding.android;
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.FragmentActivity;
import io.flutter.embedding.engine.FlutterEngine;
/**
* Provides a {@link FlutterEngine} instance to be used by a {@code FlutterActivity} or
* {@code FlutterFragment}.
* <p>
* {@link FlutterEngine} instances require significant time to warm up. Therefore, a developer
* might choose to hold onto an existing {@link FlutterEngine} and connect it to various
* {@link FlutterActivity}s and/or {@code FlutterFragment}s. This interface facilitates providing
* a cached, pre-warmed {@link FlutterEngine}.
*/
public interface FlutterEngineProvider {
/**
* Returns the {@link FlutterEngine} that should be used by a child {@code FlutterFragment}.
* <p>
* This method may return a new {@link FlutterEngine}, an existing, cached {@link FlutterEngine},
* or null to express that the {@code FlutterEngineProvider} would like the {@code FlutterFragment}
* to provide its own {@code FlutterEngine} instance.
*/
@Nullable
FlutterEngine provideFlutterEngine(@NonNull Context context);
}
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package io.flutter.embedding.android;
import android.support.annotation.Nullable;
/**
* Provides a {@link SplashScreen} to display while Flutter initializes and renders its first
* frame.
*/
public interface SplashScreenProvider {
/**
* Provides a {@link SplashScreen} to display while Flutter initializes and renders its first
* frame.
*/
@Nullable
SplashScreen provideSplashScreen();
}
......@@ -10,6 +10,7 @@ import android.support.annotation.Nullable;
import android.support.annotation.UiThread;
import java.nio.ByteBuffer;
import java.util.Objects;
import io.flutter.Log;
import io.flutter.embedding.engine.FlutterJNI;
......@@ -283,6 +284,24 @@ public class DartExecutor implements BinaryMessenger {
public String toString() {
return "DartEntrypoint( bundle path: " + pathToBundle + ", function: " + dartEntrypointFunctionName + " )";
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
DartEntrypoint that = (DartEntrypoint) o;
if (!pathToBundle.equals(that.pathToBundle)) return false;
return dartEntrypointFunctionName.equals(that.dartEntrypointFunctionName);
}
@Override
public int hashCode() {
int result = pathToBundle.hashCode();
result = 31 * result + dartEntrypointFunctionName.hashCode();
return result;
}
}
/**
......
......@@ -25,7 +25,7 @@ import io.flutter.plugin.common.ActivityLifecycleListener;
/**
* Android implementation of the platform plugin.
*/
public class PlatformPlugin implements ActivityLifecycleListener {
public class PlatformPlugin {
public static final int DEFAULT_SYSTEM_UI = View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
......@@ -181,7 +181,15 @@ public class PlatformPlugin implements ActivityLifecycleListener {
updateSystemUiOverlays();
}
private void updateSystemUiOverlays(){
/**
* Refreshes Android's window system UI (AKA system chrome) to match Flutter's desired
* {@link PlatformChannel.SystemChromeStyle}.
* <p>
* Updating the system UI Overlays is accomplished by altering the decor view of the
* {@link Window} associated with the {@link Activity} that was provided to this
* {@code PlatformPlugin}.
*/
public void updateSystemUiOverlays(){
activity.getWindow().getDecorView().setSystemUiVisibility(mEnabledOverlays);
if (currentTheme != null) {
setSystemChromeSystemUIOverlayStyle(currentTheme);
......@@ -263,9 +271,4 @@ public class PlatformPlugin implements ActivityLifecycleListener {
ClipData clip = ClipData.newPlainText("text label?", text);
clipboard.setPrimaryClip(clip);
}
@Override
public void onPostResume() {
updateSystemUiOverlays();
}
}
......@@ -14,6 +14,7 @@ import android.os.Looper;
import android.os.SystemClock;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.VisibleForTesting;
import android.util.Log;
import android.view.WindowManager;
......@@ -22,7 +23,6 @@ import io.flutter.embedding.engine.FlutterJNI;
import io.flutter.util.PathUtils;
import java.io.File;
import java.io.IOException;
import java.util.*;
/**
......@@ -56,6 +56,13 @@ public class FlutterMain {
private static final String DEFAULT_KERNEL_BLOB = "kernel_blob.bin";
private static final String DEFAULT_FLUTTER_ASSETS_DIR = "flutter_assets";
private static boolean isRunningInRobolectricTest = false;
@VisibleForTesting
public static void setIsRunningInRobolectricTest(boolean isRunningInRobolectricTest) {
FlutterMain.isRunningInRobolectricTest = isRunningInRobolectricTest;
}
@NonNull
private static String fromFlutterAssets(@NonNull String filePath) {
return sFlutterAssetsDir + File.separator + filePath;
......@@ -96,6 +103,10 @@ public class FlutterMain {
* @param applicationContext The Android application context.
*/
public static void startInitialization(@NonNull Context applicationContext) {
// Do nothing if we're running this in a Robolectric test.
if (isRunningInRobolectricTest) {
return;
}
startInitialization(applicationContext, new Settings());
}
......@@ -105,6 +116,11 @@ public class FlutterMain {
* @param settings Configuration settings.
*/
public static void startInitialization(@NonNull Context applicationContext, @NonNull Settings settings) {
// Do nothing if we're running this in a Robolectric test.
if (isRunningInRobolectricTest) {
return;
}
if (Looper.myLooper() != Looper.getMainLooper()) {
throw new IllegalStateException("startInitialization must be called on the main thread");
}
......@@ -140,6 +156,11 @@ public class FlutterMain {
* @param args Flags sent to the Flutter runtime.
*/
public static void ensureInitializationComplete(@NonNull Context applicationContext, @Nullable String[] args) {
// Do nothing if we're running this in a Robolectric test.
if (isRunningInRobolectricTest) {
return;
}
if (Looper.myLooper() != Looper.getMainLooper()) {
throw new IllegalStateException("ensureInitializationComplete must be called on the main thread");
}
......@@ -207,6 +228,11 @@ public class FlutterMain {
@NonNull Handler callbackHandler,
@NonNull Runnable callback
) {
// Do nothing if we're running this in a Robolectric test.
if (isRunningInRobolectricTest) {
return;
}
if (Looper.myLooper() != Looper.getMainLooper()) {
throw new IllegalStateException("ensureInitializationComplete must be called on the main thread");
}
......
......@@ -199,7 +199,12 @@ public class FlutterView extends SurfaceView implements BinaryMessenger, Texture
// Create and setup plugins
PlatformPlugin platformPlugin = new PlatformPlugin(activity, platformChannel);
addActivityLifecycleListener(platformPlugin);
addActivityLifecycleListener(new ActivityLifecycleListener() {
@Override
public void onPostResume() {
platformPlugin.updateSystemUiOverlays();
}
});
mImm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
PlatformViewsController platformViewsController = mNativeView.getPluginRegistry().getPlatformViewsController();
mTextInputPlugin = new TextInputPlugin(this, dartExecutor, platformViewsController);
......
......@@ -62,10 +62,15 @@ to use as the base for the pre-existing package. Add new dependencies to `lib/`.
Once you've uploaded the new version, also make sure to tag it with the updated
timestamp and robolectric version (most likely still 3.8, unless you've migrated
all the packges to 4+).
all the packages to 4+).
$ cipd set-tag --version=<new_version_hash> -tag "last_updated:<timestamp>"
$ cipd set-tag --version=<new_version_hash> -tag "robolectric_version:<robolectric_version>"
$ cipd set-tag flutter/android/robolectric --version=<new_version_hash> -tag=last_updated:<timestamp>
Example of a last-updated timestamp: 2019-07-29T15:27:42-0700
You can generate the same date format with `date +%Y-%m-%dT%T%z`.
$ cipd set-tag flutter/android/robolectric --version=<new_version_hash> -tag=robolectric_version:<robolectric_version>
You can run `cipd describe flutter/android/robolectric_bundle
--version=<new_version_hash>` to verify. You should see:
......@@ -79,8 +84,8 @@ Tags:
robolectric_version:<robolectric_version>
```
Then update the `DEPS` file to use the new version by pointing to your new
`last_updated_at` tag.
Then update the `DEPS` file (located at /src/flutter/DEPS) to use the new version by pointing to
your new `last_updated_at` tag.
```
'src/third_party/robolectric': {
......
......@@ -6,6 +6,7 @@ package io.flutter;
import io.flutter.SmokeTest;
import io.flutter.util.PreconditionsTest;
import io.flutter.embedding.android.FlutterActivityAndFragmentDelegateTest;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
......@@ -14,7 +15,8 @@ import org.junit.runners.Suite.SuiteClasses;
@RunWith(Suite.class)
@SuiteClasses({
PreconditionsTest.class,
SmokeTest.class
SmokeTest.class,
FlutterActivityAndFragmentDelegateTest.class,
})
/** Runs all of the unit tests listed in the {@code @SuiteClasses} annotation. */
public class FlutterTestSuite {}
......@@ -45,7 +45,9 @@ public class MainActivity extends FlutterActivity implements OnFirstFrameRendere
}
}
private FlutterShellArgs getFlutterShellArgs() {
@Override
@NonNull
public FlutterShellArgs getFlutterShellArgs() {
FlutterShellArgs args = FlutterShellArgs.fromIntent(getIntent());
args.add(FlutterShellArgs.ARG_TRACE_STARTUP);
args.add(FlutterShellArgs.ARG_ENABLE_DART_PROFILING);
......@@ -54,20 +56,6 @@ public class MainActivity extends FlutterActivity implements OnFirstFrameRendere
return args;
}
@Override
@NonNull
protected FlutterFragment createFlutterFragment() {
return new FlutterFragment.Builder()
.dartEntrypoint(getDartEntrypoint())
.initialRoute(getInitialRoute())
.appBundlePath(getAppBundlePath())
.flutterShellArgs(getFlutterShellArgs())
.renderMode(FlutterView.RenderMode.surface)
.transparencyMode(FlutterView.TransparencyMode.opaque)
.shouldAttachEngineToActivity(true)
.build();
}
private void writeTimelineData(Uri logFile) {
if (logFile == null) {
throw new IllegalArgumentException();
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册