blob: 6e6ca763a0111edbab00cae0da1919833838c72a [file] [log] [blame]
// 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.view;
import android.app.Activity;
import android.content.Context;
import androidx.annotation.NonNull;
import androidx.annotation.UiThread;
import io.flutter.Log;
import io.flutter.app.FlutterPluginRegistry;
import io.flutter.embedding.engine.FlutterEngine.EngineLifecycleListener;
import io.flutter.embedding.engine.FlutterJNI;
import io.flutter.embedding.engine.dart.DartExecutor;
import io.flutter.embedding.engine.renderer.FlutterUiDisplayListener;
import io.flutter.plugin.common.*;
import java.nio.ByteBuffer;
/**
* @deprecated {@link io.flutter.embedding.android.FlutterView} is the new API that now replaces
* this class. See https://flutter.dev/go/android-project-migration for more migration details.
*/
@Deprecated
public class FlutterNativeView implements BinaryMessenger {
private static final String TAG = "FlutterNativeView";
private final FlutterPluginRegistry mPluginRegistry;
private final DartExecutor dartExecutor;
private FlutterView mFlutterView;
private final FlutterJNI mFlutterJNI;
private final Context mContext;
private boolean applicationIsRunning;
private final FlutterUiDisplayListener flutterUiDisplayListener =
new FlutterUiDisplayListener() {
@Override
public void onFlutterUiDisplayed() {
if (mFlutterView == null) {
return;
}
mFlutterView.onFirstFrame();
}
@Override
public void onFlutterUiNoLongerDisplayed() {
// no-op
}
};
public FlutterNativeView(@NonNull Context context) {
this(context, false);
}
public FlutterNativeView(@NonNull Context context, boolean isBackgroundView) {
if (isBackgroundView) {
Log.w(TAG, "'isBackgroundView' is no longer supported and will be ignored");
}
mContext = context;
mPluginRegistry = new FlutterPluginRegistry(this, context);
mFlutterJNI = new FlutterJNI();
mFlutterJNI.addIsDisplayingFlutterUiListener(flutterUiDisplayListener);
this.dartExecutor = new DartExecutor(mFlutterJNI, context.getAssets());
mFlutterJNI.addEngineLifecycleListener(new EngineLifecycleListenerImpl());
attach(this);
assertAttached();
}
public void detachFromFlutterView() {
mPluginRegistry.detach();
mFlutterView = null;
}
public void destroy() {
mPluginRegistry.destroy();
dartExecutor.onDetachedFromJNI();
mFlutterView = null;
mFlutterJNI.removeIsDisplayingFlutterUiListener(flutterUiDisplayListener);
mFlutterJNI.detachFromNativeAndReleaseResources();
applicationIsRunning = false;
}
@NonNull
public DartExecutor getDartExecutor() {
return dartExecutor;
}
@NonNull
public FlutterPluginRegistry getPluginRegistry() {
return mPluginRegistry;
}
public void attachViewAndActivity(FlutterView flutterView, Activity activity) {
mFlutterView = flutterView;
mPluginRegistry.attach(flutterView, activity);
}
public boolean isAttached() {
return mFlutterJNI.isAttached();
}
public void assertAttached() {
if (!isAttached()) throw new AssertionError("Platform view is not attached");
}
public void runFromBundle(FlutterRunArguments args) {
if (args.entrypoint == null) {
throw new AssertionError("An entrypoint must be specified");
}
assertAttached();
if (applicationIsRunning)
throw new AssertionError("This Flutter engine instance is already running an application");
mFlutterJNI.runBundleAndSnapshotFromLibrary(
args.bundlePath, args.entrypoint, args.libraryPath, mContext.getResources().getAssets());
applicationIsRunning = true;
}
public boolean isApplicationRunning() {
return applicationIsRunning;
}
public static String getObservatoryUri() {
return FlutterJNI.getObservatoryUri();
}
@Override
@UiThread
public TaskQueue makeBackgroundTaskQueue() {
return dartExecutor.getBinaryMessenger().makeBackgroundTaskQueue();
}
@Override
@UiThread
public void send(String channel, ByteBuffer message) {
dartExecutor.getBinaryMessenger().send(channel, message);
}
@Override
@UiThread
public void send(String channel, ByteBuffer message, BinaryReply callback) {
if (!isAttached()) {
Log.d(TAG, "FlutterView.send called on a detached view, channel=" + channel);
return;
}
dartExecutor.getBinaryMessenger().send(channel, message, callback);
}
@Override
@UiThread
public void setMessageHandler(String channel, BinaryMessageHandler handler, TaskQueue taskQueue) {
dartExecutor.getBinaryMessenger().setMessageHandler(channel, handler, taskQueue);
}
/*package*/ FlutterJNI getFlutterJNI() {
return mFlutterJNI;
}
private void attach(FlutterNativeView view) {
mFlutterJNI.attachToNative();
dartExecutor.onAttachedToJNI();
}
private final class EngineLifecycleListenerImpl implements EngineLifecycleListener {
// Called by native to notify when the engine is restarted (cold reload).
@SuppressWarnings("unused")
public void onPreEngineRestart() {
if (mFlutterView != null) {
mFlutterView.resetAccessibilityTree();
}
if (mPluginRegistry == null) {
return;
}
mPluginRegistry.onPreEngineRestart();
}
public void onEngineWillDestroy() {
// The old embedding doesn't actually have a FlutterEngine. It interacts with the JNI
// directly.
}
}
}