| // 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(), | |
| null); | |
| applicationIsRunning = true; | |
| } | |
| public boolean isApplicationRunning() { | |
| return applicationIsRunning; | |
| } | |
| public static String getObservatoryUri() { | |
| return FlutterJNI.getObservatoryUri(); | |
| } | |
| @Override | |
| @UiThread | |
| public TaskQueue makeBackgroundTaskQueue(TaskQueueOptions options) { | |
| return dartExecutor.getBinaryMessenger().makeBackgroundTaskQueue(options); | |
| } | |
| @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) { | |
| dartExecutor.getBinaryMessenger().setMessageHandler(channel, handler); | |
| } | |
| @Override | |
| @UiThread | |
| public void setMessageHandler(String channel, BinaryMessageHandler handler, TaskQueue taskQueue) { | |
| dartExecutor.getBinaryMessenger().setMessageHandler(channel, handler, taskQueue); | |
| } | |
| @Override | |
| public void enableBufferingIncomingMessages() {} | |
| @Override | |
| public void disableBufferingIncomingMessages() {} | |
| /*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 right before 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. | |
| } | |
| } | |
| } |