mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Updated background execution implementation for Android
This commit is contained in:
parent
5770cbd2a3
commit
bc885f319b
@ -133,8 +133,10 @@ java_library("flutter_shell_java") {
|
||||
"io/flutter/util/PathUtils.java",
|
||||
"io/flutter/util/Preconditions.java",
|
||||
"io/flutter/view/AccessibilityBridge.java",
|
||||
"io/flutter/view/FlutterCallbackInformation.java",
|
||||
"io/flutter/view/FlutterMain.java",
|
||||
"io/flutter/view/FlutterNativeView.java",
|
||||
"io/flutter/view/FlutterRunArguments.java",
|
||||
"io/flutter/view/FlutterView.java",
|
||||
"io/flutter/view/ResourceCleaner.java",
|
||||
"io/flutter/view/ResourceExtractor.java",
|
||||
|
||||
@ -23,7 +23,8 @@ namespace shell {
|
||||
|
||||
AndroidShellHolder::AndroidShellHolder(
|
||||
blink::Settings settings,
|
||||
fml::jni::JavaObjectWeakGlobalRef java_object)
|
||||
fml::jni::JavaObjectWeakGlobalRef java_object,
|
||||
bool is_background_view)
|
||||
: settings_(std::move(settings)), java_object_(java_object) {
|
||||
static size_t shell_count = 1;
|
||||
auto thread_label = std::to_string(shell_count++);
|
||||
@ -31,26 +32,42 @@ AndroidShellHolder::AndroidShellHolder(
|
||||
FML_CHECK(pthread_key_create(&thread_destruct_key_, ThreadDestructCallback) ==
|
||||
0);
|
||||
|
||||
thread_host_ = {thread_label, ThreadHost::Type::UI | ThreadHost::Type::GPU |
|
||||
ThreadHost::Type::IO};
|
||||
if (is_background_view) {
|
||||
thread_host_ = {thread_label, ThreadHost::Type::UI};
|
||||
} else {
|
||||
thread_host_ = {thread_label, ThreadHost::Type::UI | ThreadHost::Type::GPU |
|
||||
ThreadHost::Type::IO};
|
||||
}
|
||||
|
||||
// Detach from JNI when the UI and GPU threads exit.
|
||||
auto jni_exit_task([key = thread_destruct_key_]() {
|
||||
FML_CHECK(pthread_setspecific(key, reinterpret_cast<void*>(1)) == 0);
|
||||
});
|
||||
thread_host_.ui_thread->GetTaskRunner()->PostTask(jni_exit_task);
|
||||
thread_host_.gpu_thread->GetTaskRunner()->PostTask(jni_exit_task);
|
||||
if (!is_background_view) {
|
||||
thread_host_.gpu_thread->GetTaskRunner()->PostTask(jni_exit_task);
|
||||
}
|
||||
|
||||
fml::WeakPtr<PlatformViewAndroid> weak_platform_view;
|
||||
Shell::CreateCallback<PlatformView> on_create_platform_view =
|
||||
[java_object, &weak_platform_view](Shell& shell) {
|
||||
auto platform_view_android = std::make_unique<PlatformViewAndroid>(
|
||||
shell, // delegate
|
||||
shell.GetTaskRunners(), // task runners
|
||||
java_object, // java object handle for JNI interop
|
||||
shell.GetSettings()
|
||||
.enable_software_rendering // use software rendering
|
||||
);
|
||||
[is_background_view, java_object, &weak_platform_view](Shell& shell) {
|
||||
std::unique_ptr<PlatformViewAndroid> platform_view_android;
|
||||
if (is_background_view) {
|
||||
platform_view_android = std::make_unique<PlatformViewAndroid>(
|
||||
shell, // delegate
|
||||
shell.GetTaskRunners(), // task runners
|
||||
java_object // java object handle for JNI interop
|
||||
);
|
||||
|
||||
} else {
|
||||
platform_view_android = std::make_unique<PlatformViewAndroid>(
|
||||
shell, // delegate
|
||||
shell.GetTaskRunners(), // task runners
|
||||
java_object, // java object handle for JNI interop
|
||||
shell.GetSettings()
|
||||
.enable_software_rendering // use software rendering
|
||||
);
|
||||
}
|
||||
weak_platform_view = platform_view_android->GetWeakPtr();
|
||||
return platform_view_android;
|
||||
};
|
||||
@ -62,13 +79,26 @@ AndroidShellHolder::AndroidShellHolder(
|
||||
// The current thread will be used as the platform thread. Ensure that the
|
||||
// message loop is initialized.
|
||||
fml::MessageLoop::EnsureInitializedForCurrentThread();
|
||||
|
||||
blink::TaskRunners task_runners(
|
||||
thread_label, // label
|
||||
fml::MessageLoop::GetCurrent().GetTaskRunner(), // platform
|
||||
thread_host_.gpu_thread->GetTaskRunner(), // gpu
|
||||
thread_host_.ui_thread->GetTaskRunner(), // ui
|
||||
thread_host_.io_thread->GetTaskRunner() // io
|
||||
fml::RefPtr<fml::TaskRunner> gpu_runner;
|
||||
fml::RefPtr<fml::TaskRunner> ui_runner;
|
||||
fml::RefPtr<fml::TaskRunner> io_runner;
|
||||
fml::RefPtr<fml::TaskRunner> platform_runner =
|
||||
fml::MessageLoop::GetCurrent().GetTaskRunner();
|
||||
if (is_background_view) {
|
||||
auto single_task_runner = thread_host_.ui_thread->GetTaskRunner();
|
||||
gpu_runner = single_task_runner;
|
||||
ui_runner = single_task_runner;
|
||||
io_runner = single_task_runner;
|
||||
} else {
|
||||
gpu_runner = thread_host_.gpu_thread->GetTaskRunner();
|
||||
ui_runner = thread_host_.ui_thread->GetTaskRunner();
|
||||
io_runner = thread_host_.io_thread->GetTaskRunner();
|
||||
}
|
||||
blink::TaskRunners task_runners(thread_label, // label
|
||||
platform_runner, // platform
|
||||
gpu_runner, // gpu
|
||||
ui_runner, // ui
|
||||
io_runner // io
|
||||
);
|
||||
|
||||
shell_ =
|
||||
@ -131,10 +161,12 @@ void AndroidShellHolder::Launch(RunConfiguration config) {
|
||||
fml::MakeCopyable([engine = shell_->GetEngine(), //
|
||||
config = std::move(config) //
|
||||
]() mutable {
|
||||
if (engine) {
|
||||
if (!engine->Run(std::move(config))) {
|
||||
FML_LOG(ERROR) << "Could not launch engine in configuration.";
|
||||
}
|
||||
FML_LOG(INFO) << "Attempting to launch engine configuration...";
|
||||
if (!engine || !engine->Run(std::move(config))) {
|
||||
FML_LOG(ERROR) << "Could not launch engine in configuration.";
|
||||
} else {
|
||||
FML_LOG(INFO) << "Isolate for engine configuration successfully "
|
||||
"started and run.";
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
@ -21,7 +21,8 @@ namespace shell {
|
||||
class AndroidShellHolder {
|
||||
public:
|
||||
AndroidShellHolder(blink::Settings settings,
|
||||
fml::jni::JavaObjectWeakGlobalRef java_object);
|
||||
fml::jni::JavaObjectWeakGlobalRef java_object,
|
||||
bool is_background_view);
|
||||
|
||||
~AndroidShellHolder();
|
||||
|
||||
|
||||
@ -30,6 +30,7 @@ import io.flutter.plugin.platform.PlatformPlugin;
|
||||
import io.flutter.util.Preconditions;
|
||||
import io.flutter.view.FlutterMain;
|
||||
import io.flutter.view.FlutterNativeView;
|
||||
import io.flutter.view.FlutterRunArguments;
|
||||
import io.flutter.view.FlutterView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@ -162,19 +163,16 @@ public final class FlutterActivityDelegate
|
||||
}
|
||||
}
|
||||
|
||||
// When an activity is created for the first time, we direct the
|
||||
// FlutterView to re-use a pre-existing Isolate rather than create a new
|
||||
// one. This is so that an Isolate coming in from the ViewFactory is
|
||||
// used.
|
||||
final boolean reuseIsolate = true;
|
||||
|
||||
if (loadIntent(activity.getIntent(), reuseIsolate)) {
|
||||
if (loadIntent(activity.getIntent())) {
|
||||
return;
|
||||
}
|
||||
if (!flutterView.getFlutterNativeView().isApplicationRunning()) {
|
||||
String appBundlePath = FlutterMain.findAppBundlePath(activity.getApplicationContext());
|
||||
if (appBundlePath != null) {
|
||||
flutterView.runFromBundle(appBundlePath, null, "main", reuseIsolate);
|
||||
FlutterRunArguments arguments = new FlutterRunArguments();
|
||||
arguments.bundlePath = appBundlePath;
|
||||
arguments.entrypoint = "main";
|
||||
flutterView.runFromBundle(arguments);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -325,11 +323,6 @@ public final class FlutterActivityDelegate
|
||||
}
|
||||
|
||||
private boolean loadIntent(Intent intent) {
|
||||
final boolean reuseIsolate = false;
|
||||
return loadIntent(intent, reuseIsolate);
|
||||
}
|
||||
|
||||
private boolean loadIntent(Intent intent, boolean reuseIsolate) {
|
||||
String action = intent.getAction();
|
||||
if (Intent.ACTION_RUN.equals(action)) {
|
||||
String route = intent.getStringExtra("route");
|
||||
@ -343,7 +336,10 @@ public final class FlutterActivityDelegate
|
||||
flutterView.setInitialRoute(route);
|
||||
}
|
||||
if (!flutterView.getFlutterNativeView().isApplicationRunning()) {
|
||||
flutterView.runFromBundle(appBundlePath, null, "main", reuseIsolate);
|
||||
FlutterRunArguments args = new FlutterRunArguments();
|
||||
args.bundlePath = appBundlePath;
|
||||
args.entrypoint = "main";
|
||||
flutterView.runFromBundle(args);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -0,0 +1,34 @@
|
||||
// Copyright 2018 The Chromium 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.view;
|
||||
|
||||
/**
|
||||
* A class representing information for a callback registered using
|
||||
* `PluginUtilities` from `dart:ui`.
|
||||
*/
|
||||
public final class FlutterCallbackInformation {
|
||||
final public String callbackName;
|
||||
final public String callbackClassName;
|
||||
final public String callbackLibraryPath;
|
||||
|
||||
/**
|
||||
* Get callback information for a given handle.
|
||||
* @param handle the handle for the callback, generated by
|
||||
* `PluginUtilities.getCallbackHandle` in `dart:ui`.
|
||||
* @return an instance of FlutterCallbackInformation for the provided handle.
|
||||
*/
|
||||
public static FlutterCallbackInformation lookupCallbackInformation(long handle) {
|
||||
return nativeLookupCallbackInformation(handle);
|
||||
}
|
||||
|
||||
private FlutterCallbackInformation(String callbackName,
|
||||
String callbackClassName, String callbackLibraryPath) {
|
||||
this.callbackName = callbackName;
|
||||
this.callbackClassName = callbackClassName;
|
||||
this.callbackLibraryPath = callbackLibraryPath;
|
||||
}
|
||||
|
||||
private static native FlutterCallbackInformation nativeLookupCallbackInformation(long handle);
|
||||
}
|
||||
@ -29,9 +29,13 @@ public class FlutterNativeView implements BinaryMessenger {
|
||||
private boolean applicationIsRunning;
|
||||
|
||||
public FlutterNativeView(Context context) {
|
||||
this(context, false);
|
||||
}
|
||||
|
||||
public FlutterNativeView(Context context, boolean isBackgroundView) {
|
||||
mContext = context;
|
||||
mPluginRegistry = new FlutterPluginRegistry(this, context);
|
||||
attach(this);
|
||||
attach(this, isBackgroundView);
|
||||
assertAttached();
|
||||
mMessageHandlers = new HashMap<>();
|
||||
}
|
||||
@ -68,22 +72,43 @@ public class FlutterNativeView implements BinaryMessenger {
|
||||
}
|
||||
|
||||
public void assertAttached() {
|
||||
if (!isAttached())
|
||||
throw new AssertionError("Platform view is not attached");
|
||||
if (!isAttached()) throw new AssertionError("Platform view is not attached");
|
||||
}
|
||||
|
||||
public void runFromBundle(String bundlePath, String snapshotOverride, String entrypoint, boolean reuseRuntimeController) {
|
||||
public void runFromBundle(FlutterRunArguments args) {
|
||||
if (args.bundlePath == null) {
|
||||
throw new AssertionError("A bundlePath must be specified");
|
||||
} else if (args.entrypoint == null) {
|
||||
throw new AssertionError("An entrypoint must be specified");
|
||||
}
|
||||
runFromBundleInternal(args.bundlePath, args.entrypoint,
|
||||
args.libraryPath, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* Please use runFromBundle with `FlutterRunArguments`. Parameters
|
||||
* `snapshotOverride` and `reuseRuntimeController` have no effect.
|
||||
*/
|
||||
public void runFromBundle(String bundlePath, String snapshotOverride, String entrypoint,
|
||||
boolean reuseRuntimeController) {
|
||||
runFromBundleInternal(bundlePath, entrypoint, null, null);
|
||||
}
|
||||
|
||||
private void runFromBundleInternal(String bundlePath, String entrypoint,
|
||||
String libraryPath, String snapshotOverride) {
|
||||
assertAttached();
|
||||
if (applicationIsRunning)
|
||||
throw new AssertionError("This Flutter engine instance is already running an application");
|
||||
|
||||
nativeRunBundleAndSnapshot(mNativePlatformView, bundlePath, snapshotOverride, entrypoint, reuseRuntimeController, mContext.getResources().getAssets());
|
||||
throw new AssertionError(
|
||||
"This Flutter engine instance is already running an application");
|
||||
nativeRunBundleAndSnapshotFromLibrary(mNativePlatformView, bundlePath,
|
||||
entrypoint, libraryPath, mContext.getResources().getAssets());
|
||||
|
||||
applicationIsRunning = true;
|
||||
}
|
||||
|
||||
public boolean isApplicationRunning() {
|
||||
return applicationIsRunning;
|
||||
return applicationIsRunning;
|
||||
}
|
||||
|
||||
public static String getObservatoryUri() {
|
||||
@ -92,7 +117,7 @@ public class FlutterNativeView implements BinaryMessenger {
|
||||
|
||||
@Override
|
||||
public void send(String channel, ByteBuffer message) {
|
||||
send(channel, message, null);
|
||||
send(channel, message, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -110,8 +135,8 @@ public class FlutterNativeView implements BinaryMessenger {
|
||||
if (message == null) {
|
||||
nativeDispatchEmptyPlatformMessage(mNativePlatformView, channel, replyId);
|
||||
} else {
|
||||
nativeDispatchPlatformMessage(mNativePlatformView, channel, message,
|
||||
message.position(), replyId);
|
||||
nativeDispatchPlatformMessage(
|
||||
mNativePlatformView, channel, message, message.position(), replyId);
|
||||
}
|
||||
}
|
||||
|
||||
@ -124,8 +149,8 @@ public class FlutterNativeView implements BinaryMessenger {
|
||||
}
|
||||
}
|
||||
|
||||
private void attach(FlutterNativeView view) {
|
||||
mNativePlatformView = nativeAttach(view);
|
||||
private void attach(FlutterNativeView view, boolean isBackgroundView) {
|
||||
mNativePlatformView = nativeAttach(view, isBackgroundView);
|
||||
}
|
||||
|
||||
// Called by native to send us a platform message.
|
||||
@ -135,27 +160,28 @@ public class FlutterNativeView implements BinaryMessenger {
|
||||
if (handler != null) {
|
||||
try {
|
||||
final ByteBuffer buffer = (message == null ? null : ByteBuffer.wrap(message));
|
||||
handler.onMessage(buffer,
|
||||
new BinaryReply() {
|
||||
private final AtomicBoolean done = new AtomicBoolean(false);
|
||||
@Override
|
||||
public void reply(ByteBuffer reply) {
|
||||
if (!isAttached()) {
|
||||
Log.d(TAG, "handlePlatformMessage replying to a detached view, channel=" + channel);
|
||||
return;
|
||||
}
|
||||
if (done.getAndSet(true)) {
|
||||
throw new IllegalStateException("Reply already submitted");
|
||||
}
|
||||
if (reply == null) {
|
||||
nativeInvokePlatformMessageEmptyResponseCallback(mNativePlatformView,
|
||||
replyId);
|
||||
} else {
|
||||
nativeInvokePlatformMessageResponseCallback(mNativePlatformView,
|
||||
replyId, reply, reply.position());
|
||||
}
|
||||
handler.onMessage(buffer, new BinaryReply() {
|
||||
private final AtomicBoolean done = new AtomicBoolean(false);
|
||||
@Override
|
||||
public void reply(ByteBuffer reply) {
|
||||
if (!isAttached()) {
|
||||
Log.d(TAG,
|
||||
"handlePlatformMessage replying to a detached view, channel="
|
||||
+ channel);
|
||||
return;
|
||||
}
|
||||
});
|
||||
if (done.getAndSet(true)) {
|
||||
throw new IllegalStateException("Reply already submitted");
|
||||
}
|
||||
if (reply == null) {
|
||||
nativeInvokePlatformMessageEmptyResponseCallback(
|
||||
mNativePlatformView, replyId);
|
||||
} else {
|
||||
nativeInvokePlatformMessageResponseCallback(
|
||||
mNativePlatformView, replyId, reply, reply.position());
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (Exception ex) {
|
||||
Log.e(TAG, "Uncaught exception in binary message listener", ex);
|
||||
nativeInvokePlatformMessageEmptyResponseCallback(mNativePlatformView, replyId);
|
||||
@ -179,8 +205,7 @@ public class FlutterNativeView implements BinaryMessenger {
|
||||
|
||||
// Called by native to update the semantics/accessibility tree.
|
||||
private void updateSemantics(ByteBuffer buffer, String[] strings) {
|
||||
if (mFlutterView == null)
|
||||
return;
|
||||
if (mFlutterView == null) return;
|
||||
mFlutterView.updateSemantics(buffer, strings);
|
||||
}
|
||||
|
||||
@ -193,8 +218,7 @@ public class FlutterNativeView implements BinaryMessenger {
|
||||
|
||||
// Called by native to notify first Flutter frame rendered.
|
||||
private void onFirstFrame() {
|
||||
if (mFlutterView == null)
|
||||
return;
|
||||
if (mFlutterView == null) return;
|
||||
mFlutterView.onFirstFrame();
|
||||
}
|
||||
|
||||
@ -206,32 +230,29 @@ public class FlutterNativeView implements BinaryMessenger {
|
||||
mPluginRegistry.onPreEngineRestart();
|
||||
}
|
||||
|
||||
private static native long nativeAttach(FlutterNativeView view);
|
||||
private static native long nativeAttach(FlutterNativeView view, boolean isBackgroundView);
|
||||
private static native void nativeDestroy(long nativePlatformViewAndroid);
|
||||
private static native void nativeDetach(long nativePlatformViewAndroid);
|
||||
|
||||
private static native void nativeRunBundleAndSnapshot(long nativePlatformViewAndroid,
|
||||
String bundlePath,
|
||||
String snapshotOverride,
|
||||
String entrypoint,
|
||||
boolean reuseRuntimeController,
|
||||
AssetManager manager);
|
||||
private static native void nativeRunBundleAndSnapshotFromLibrary(
|
||||
long nativePlatformViewAndroid, String bundlePath,
|
||||
String entrypoint, String libraryUrl, AssetManager manager);
|
||||
|
||||
private static native String nativeGetObservatoryUri();
|
||||
|
||||
// Send an empty platform message to Dart.
|
||||
private static native void nativeDispatchEmptyPlatformMessage(long nativePlatformViewAndroid,
|
||||
String channel, int responseId);
|
||||
private static native void nativeDispatchEmptyPlatformMessage(
|
||||
long nativePlatformViewAndroid, String channel, int responseId);
|
||||
|
||||
// Send a data-carrying platform message to Dart.
|
||||
private static native void nativeDispatchPlatformMessage(long nativePlatformViewAndroid,
|
||||
String channel, ByteBuffer message, int position, int responseId);
|
||||
String channel, ByteBuffer message, int position, int responseId);
|
||||
|
||||
// Send an empty response to a platform message received from Dart.
|
||||
private static native void nativeInvokePlatformMessageEmptyResponseCallback(
|
||||
long nativePlatformViewAndroid, int responseId);
|
||||
long nativePlatformViewAndroid, int responseId);
|
||||
|
||||
// Send a data-carrying response to a platform message received from Dart.
|
||||
private static native void nativeInvokePlatformMessageResponseCallback(
|
||||
long nativePlatformViewAndroid, int responseId, ByteBuffer message, int position);
|
||||
long nativePlatformViewAndroid, int responseId, ByteBuffer message, int position);
|
||||
}
|
||||
|
||||
@ -0,0 +1,16 @@
|
||||
// Copyright 2018 The Chromium 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.view;
|
||||
|
||||
/**
|
||||
* A class containing arguments for entering a FlutterNativeView's isolate for
|
||||
* the first time.
|
||||
*/
|
||||
public class FlutterRunArguments {
|
||||
public String bundlePath;
|
||||
public String entrypoint;
|
||||
public String libraryPath;
|
||||
public String snapshotOverride;
|
||||
}
|
||||
@ -602,20 +602,41 @@ public class FlutterView extends SurfaceView
|
||||
private void postRun() {
|
||||
}
|
||||
|
||||
public void runFromBundle(FlutterRunArguments args) {
|
||||
assertAttached();
|
||||
preRun();
|
||||
mNativeView.runFromBundle(args);
|
||||
postRun();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* Please use runFromBundle with `FlutterRunArguments`. Parameter
|
||||
* `snapshotOverride` has no effect.
|
||||
*/
|
||||
public void runFromBundle(String bundlePath, String snapshotOverride) {
|
||||
runFromBundle(bundlePath, snapshotOverride, "main", false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* Please use runFromBundle with `FlutterRunArguments`. Parameter
|
||||
* `snapshotOverride` has no effect.
|
||||
*/
|
||||
public void runFromBundle(String bundlePath, String snapshotOverride, String entrypoint) {
|
||||
runFromBundle(bundlePath, snapshotOverride, entrypoint, false);
|
||||
}
|
||||
|
||||
public void runFromBundle(String bundlePath, String snapshotOverride, String entrypoint,
|
||||
boolean reuseRuntimeController) {
|
||||
assertAttached();
|
||||
preRun();
|
||||
mNativeView.runFromBundle(bundlePath, snapshotOverride, entrypoint, reuseRuntimeController);
|
||||
postRun();
|
||||
/**
|
||||
* @deprecated
|
||||
* Please use runFromBundle with `FlutterRunArguments`. Parameters
|
||||
* `snapshotOverride` and `reuseRuntimeController` have no effect.
|
||||
*/
|
||||
public void runFromBundle(String bundlePath, String snapshotOverride, String entrypoint, boolean reuseRuntimeController) {
|
||||
FlutterRunArguments args = new FlutterRunArguments();
|
||||
args.bundlePath = bundlePath;
|
||||
args.entrypoint = entrypoint;
|
||||
runFromBundle(args);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -30,21 +30,36 @@ PlatformViewAndroid::PlatformViewAndroid(
|
||||
"rendering.";
|
||||
}
|
||||
|
||||
PlatformViewAndroid::PlatformViewAndroid(
|
||||
PlatformView::Delegate& delegate,
|
||||
blink::TaskRunners task_runners,
|
||||
fml::jni::JavaObjectWeakGlobalRef java_object)
|
||||
: PlatformView(delegate, std::move(task_runners)),
|
||||
java_object_(java_object),
|
||||
android_surface_(nullptr) {}
|
||||
|
||||
PlatformViewAndroid::~PlatformViewAndroid() = default;
|
||||
|
||||
void PlatformViewAndroid::NotifyCreated(
|
||||
fml::RefPtr<AndroidNativeWindow> native_window) {
|
||||
InstallFirstFrameCallback();
|
||||
android_surface_->SetNativeWindow(native_window);
|
||||
if (android_surface_) {
|
||||
InstallFirstFrameCallback();
|
||||
android_surface_->SetNativeWindow(native_window);
|
||||
}
|
||||
PlatformView::NotifyCreated();
|
||||
}
|
||||
|
||||
void PlatformViewAndroid::NotifyDestroyed() {
|
||||
PlatformView::NotifyDestroyed();
|
||||
android_surface_->TeardownOnScreenContext();
|
||||
if (android_surface_) {
|
||||
android_surface_->TeardownOnScreenContext();
|
||||
}
|
||||
}
|
||||
|
||||
void PlatformViewAndroid::NotifyChanged(const SkISize& size) {
|
||||
if (!android_surface_) {
|
||||
return;
|
||||
}
|
||||
fml::AutoResetWaitableEvent latch;
|
||||
fml::TaskRunner::RunNowOrPostTask(
|
||||
task_runners_.GetGPUTaskRunner(), //
|
||||
@ -345,11 +360,17 @@ std::unique_ptr<VsyncWaiter> PlatformViewAndroid::CreateVSyncWaiter() {
|
||||
|
||||
// |shell::PlatformView|
|
||||
std::unique_ptr<Surface> PlatformViewAndroid::CreateRenderingSurface() {
|
||||
if (!android_surface_) {
|
||||
return nullptr;
|
||||
}
|
||||
return android_surface_->CreateGPUSurface();
|
||||
}
|
||||
|
||||
// |shell::PlatformView|
|
||||
sk_sp<GrContext> PlatformViewAndroid::CreateResourceContext() const {
|
||||
if (!android_surface_) {
|
||||
return nullptr;
|
||||
}
|
||||
sk_sp<GrContext> resource_context;
|
||||
if (android_surface_->ResourceContextMakeCurrent()) {
|
||||
// TODO(chinmaygarde): Currently, this code depends on the fact that only
|
||||
|
||||
@ -24,6 +24,13 @@ class PlatformViewAndroid final : public PlatformView {
|
||||
public:
|
||||
static bool Register(JNIEnv* env);
|
||||
|
||||
// Creates a PlatformViewAndroid with no rendering surface for use with
|
||||
// background execution.
|
||||
PlatformViewAndroid(PlatformView::Delegate& delegate,
|
||||
blink::TaskRunners task_runners,
|
||||
fml::jni::JavaObjectWeakGlobalRef java_object);
|
||||
|
||||
// Creates a PlatformViewAndroid with a rendering surface.
|
||||
PlatformViewAndroid(PlatformView::Delegate& delegate,
|
||||
blink::TaskRunners task_runners,
|
||||
fml::jni::JavaObjectWeakGlobalRef java_object,
|
||||
|
||||
@ -16,6 +16,7 @@
|
||||
#include "flutter/fml/platform/android/jni_util.h"
|
||||
#include "flutter/fml/platform/android/jni_weak_ref.h"
|
||||
#include "flutter/fml/platform/android/scoped_java_ref.h"
|
||||
#include "flutter/lib/ui/plugins/callback_cache.h"
|
||||
#include "flutter/runtime/dart_service_isolate.h"
|
||||
#include "flutter/shell/common/run_configuration.h"
|
||||
#include "flutter/shell/platform/android/android_external_texture_gl.h"
|
||||
@ -43,6 +44,8 @@ bool CheckException(JNIEnv* env) {
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
static fml::jni::ScopedJavaGlobalRef<jclass>* g_flutter_callback_info_class =
|
||||
nullptr;
|
||||
static fml::jni::ScopedJavaGlobalRef<jclass>* g_flutter_view_class = nullptr;
|
||||
static fml::jni::ScopedJavaGlobalRef<jclass>* g_flutter_native_view_class =
|
||||
nullptr;
|
||||
@ -50,6 +53,19 @@ static fml::jni::ScopedJavaGlobalRef<jclass>* g_surface_texture_class = nullptr;
|
||||
|
||||
// Called By Native
|
||||
|
||||
static jmethodID g_flutter_callback_info_constructor = nullptr;
|
||||
jobject CreateFlutterCallbackInformation(
|
||||
JNIEnv* env,
|
||||
const std::string& callbackName,
|
||||
const std::string& callbackClassName,
|
||||
const std::string& callbackLibraryPath) {
|
||||
return env->NewObject(g_flutter_callback_info_class->obj(),
|
||||
g_flutter_callback_info_constructor,
|
||||
env->NewStringUTF(callbackName.c_str()),
|
||||
env->NewStringUTF(callbackClassName.c_str()),
|
||||
env->NewStringUTF(callbackLibraryPath.c_str()));
|
||||
}
|
||||
|
||||
static jmethodID g_handle_platform_message_method = nullptr;
|
||||
void FlutterViewHandlePlatformMessage(JNIEnv* env,
|
||||
jobject obj,
|
||||
@ -130,10 +146,13 @@ void SurfaceTextureDetachFromGLContext(JNIEnv* env, jobject obj) {
|
||||
|
||||
// Called By Java
|
||||
|
||||
static jlong Attach(JNIEnv* env, jclass clazz, jobject flutterView) {
|
||||
static jlong Attach(JNIEnv* env,
|
||||
jclass clazz,
|
||||
jobject flutterView,
|
||||
jboolean is_background_view) {
|
||||
fml::jni::JavaObjectWeakGlobalRef java_object(env, flutterView);
|
||||
auto shell_holder = std::make_unique<AndroidShellHolder>(
|
||||
FlutterMain::Get().GetSettings(), java_object);
|
||||
FlutterMain::Get().GetSettings(), java_object, is_background_view);
|
||||
if (shell_holder->IsValid()) {
|
||||
return reinterpret_cast<jlong>(shell_holder.release());
|
||||
} else {
|
||||
@ -218,15 +237,14 @@ std::unique_ptr<IsolateConfiguration> CreateIsolateConfiguration(
|
||||
return IsolateConfiguration::CreateForAppSnapshot();
|
||||
}
|
||||
|
||||
static void RunBundleAndSnapshot(
|
||||
JNIEnv* env,
|
||||
jobject jcaller,
|
||||
jlong shell_holder,
|
||||
jstring jbundlepath,
|
||||
jstring jsnapshotOverride,
|
||||
jstring jEntrypoint,
|
||||
jboolean /* reuse runtime controller (unused) */,
|
||||
jobject jAssetManager) {
|
||||
static void RunBundleAndSnapshotFromLibrary(JNIEnv* env,
|
||||
jobject jcaller,
|
||||
jlong shell_holder,
|
||||
jstring jbundlepath,
|
||||
jstring jsnapshotOverride,
|
||||
jstring jEntrypoint,
|
||||
jstring jLibraryUrl,
|
||||
jobject jAssetManager) {
|
||||
auto asset_manager = fml::MakeRefCounted<blink::AssetManager>();
|
||||
|
||||
const auto bundlepath = fml::jni::JavaStringToString(env, jbundlepath);
|
||||
@ -275,7 +293,12 @@ static void RunBundleAndSnapshot(
|
||||
|
||||
{
|
||||
auto entrypoint = fml::jni::JavaStringToString(env, jEntrypoint);
|
||||
if (entrypoint.size() > 0) {
|
||||
auto libraryUrl = fml::jni::JavaStringToString(env, jLibraryUrl);
|
||||
|
||||
if ((entrypoint.size() > 0) && (libraryUrl.size() > 0)) {
|
||||
config.SetEntrypointAndLibrary(std::move(entrypoint),
|
||||
std::move(libraryUrl));
|
||||
} else if (entrypoint.size() > 0) {
|
||||
config.SetEntrypoint(std::move(entrypoint));
|
||||
}
|
||||
}
|
||||
@ -283,6 +306,17 @@ static void RunBundleAndSnapshot(
|
||||
ANDROID_SHELL_HOLDER->Launch(std::move(config));
|
||||
}
|
||||
|
||||
static jobject LookupCallbackInformation(JNIEnv* env,
|
||||
/* unused */ jobject,
|
||||
jlong handle) {
|
||||
auto cbInfo = blink::DartCallbackCache::GetCallbackInformation(handle);
|
||||
if (cbInfo == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
return CreateFlutterCallbackInformation(env, cbInfo->name, cbInfo->class_name,
|
||||
cbInfo->library_path);
|
||||
}
|
||||
|
||||
static void SetViewportMetrics(JNIEnv* env,
|
||||
jobject jcaller,
|
||||
jlong shell_holder,
|
||||
@ -516,6 +550,19 @@ bool PlatformViewAndroid::Register(JNIEnv* env) {
|
||||
return false;
|
||||
}
|
||||
|
||||
g_flutter_callback_info_class = new fml::jni::ScopedJavaGlobalRef<jclass>(
|
||||
env, env->FindClass("io/flutter/view/FlutterCallbackInformation"));
|
||||
if (g_flutter_callback_info_class->is_null()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
g_flutter_callback_info_constructor = env->GetMethodID(
|
||||
g_flutter_callback_info_class->obj(), "<init>",
|
||||
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
|
||||
if (g_flutter_callback_info_constructor == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
g_flutter_view_class = new fml::jni::ScopedJavaGlobalRef<jclass>(
|
||||
env, env->FindClass("io/flutter/view/FlutterView"));
|
||||
if (g_flutter_view_class->is_null()) {
|
||||
@ -537,7 +584,7 @@ bool PlatformViewAndroid::Register(JNIEnv* env) {
|
||||
static const JNINativeMethod native_view_methods[] = {
|
||||
{
|
||||
.name = "nativeAttach",
|
||||
.signature = "(Lio/flutter/view/FlutterNativeView;)J",
|
||||
.signature = "(Lio/flutter/view/FlutterNativeView;Z)J",
|
||||
.fnPtr = reinterpret_cast<void*>(&shell::Attach),
|
||||
},
|
||||
{
|
||||
@ -546,10 +593,11 @@ bool PlatformViewAndroid::Register(JNIEnv* env) {
|
||||
.fnPtr = reinterpret_cast<void*>(&shell::Destroy),
|
||||
},
|
||||
{
|
||||
.name = "nativeRunBundleAndSnapshot",
|
||||
.signature = "(JLjava/lang/String;Ljava/lang/String;Ljava/lang/"
|
||||
"String;ZLandroid/content/res/AssetManager;)V",
|
||||
.fnPtr = reinterpret_cast<void*>(&shell::RunBundleAndSnapshot),
|
||||
.name = "nativeRunBundleAndSnapshotFromLibrary",
|
||||
.signature = "(JLjava/lang/String;Ljava/lang/String;"
|
||||
"Ljava/lang/String;Landroid/content/res/AssetManager;)V",
|
||||
.fnPtr =
|
||||
reinterpret_cast<void*>(&shell::RunBundleAndSnapshotFromLibrary),
|
||||
},
|
||||
{
|
||||
.name = "nativeDetach",
|
||||
@ -654,6 +702,14 @@ bool PlatformViewAndroid::Register(JNIEnv* env) {
|
||||
},
|
||||
};
|
||||
|
||||
static const JNINativeMethod callback_info_methods[] = {
|
||||
{
|
||||
.name = "nativeLookupCallbackInformation",
|
||||
.signature = "(J)Lio/flutter/view/FlutterCallbackInformation;",
|
||||
.fnPtr = reinterpret_cast<void*>(&shell::LookupCallbackInformation),
|
||||
},
|
||||
};
|
||||
|
||||
if (env->RegisterNatives(g_flutter_native_view_class->obj(),
|
||||
native_view_methods,
|
||||
arraysize(native_view_methods)) != 0) {
|
||||
@ -665,6 +721,12 @@ bool PlatformViewAndroid::Register(JNIEnv* env) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (env->RegisterNatives(g_flutter_callback_info_class->obj(),
|
||||
callback_info_methods,
|
||||
arraysize(callback_info_methods)) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
g_handle_platform_message_method =
|
||||
env->GetMethodID(g_flutter_native_view_class->obj(),
|
||||
"handlePlatformMessage", "(Ljava/lang/String;[BI)V");
|
||||
|
||||
@ -35,4 +35,4 @@ class HeadlessPlatformViewIOS : public PlatformView {
|
||||
|
||||
} // namespace shell
|
||||
|
||||
#endif // SHELL_PLATFORM_IOS_HEADLESS_PLATFORM_VIEW_IOS_H_
|
||||
#endif // SHELL_PLATFORM_IOS_HEADLESS_PLATFORM_VIEW_IOS_H_
|
||||
|
||||
@ -17,4 +17,4 @@ PlatformMessageRouter& HeadlessPlatformViewIOS::GetPlatformMessageRouter() {
|
||||
void HeadlessPlatformViewIOS::HandlePlatformMessage(fml::RefPtr<blink::PlatformMessage> message) {
|
||||
platform_message_router_.HandlePlatformMessage(std::move(message));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -500,6 +500,8 @@ FILE: ../../../flutter/shell/platform/android/io/flutter/plugin/platform/Platfor
|
||||
FILE: ../../../flutter/shell/platform/android/io/flutter/plugin/platform/PlatformViewsController.java
|
||||
FILE: ../../../flutter/shell/platform/android/io/flutter/plugin/platform/SingleViewPresentation.java
|
||||
FILE: ../../../flutter/shell/platform/android/io/flutter/plugin/platform/VirtualDisplayController.java
|
||||
FILE: ../../../flutter/shell/platform/android/io/flutter/view/FlutterCallbackInformation.java
|
||||
FILE: ../../../flutter/shell/platform/android/io/flutter/view/FlutterRunArguments.java
|
||||
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Headers/FlutterCallbackCache.h
|
||||
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Headers/FlutterPluginAppLifeCycleDelegate.h
|
||||
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterCallbackCache.mm
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user