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

Add plugin shim to facilitate old plugins in new embedding (#33478). (#9120)

上级 e8c2b178
......@@ -533,6 +533,8 @@ FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/plugin
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/plugins/service/ServiceAware.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/plugins/service/ServiceControlSurface.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/plugins/service/ServicePluginBinding.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/plugins/shim/ShimPluginRegistry.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/plugins/shim/ShimRegistrar.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/renderer/FlutterRenderer.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/renderer/OnFirstFrameRenderedListener.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/systemchannels/AccessibilityChannel.java
......
......@@ -149,6 +149,8 @@ action("flutter_shell_java") {
"io/flutter/embedding/engine/plugins/service/ServiceAware.java",
"io/flutter/embedding/engine/plugins/service/ServiceControlSurface.java",
"io/flutter/embedding/engine/plugins/service/ServicePluginBinding.java",
"io/flutter/embedding/engine/plugins/shim/ShimPluginRegistry.java",
"io/flutter/embedding/engine/plugins/shim/ShimRegistrar.java",
"io/flutter/embedding/engine/renderer/FlutterRenderer.java",
"io/flutter/embedding/engine/renderer/OnFirstFrameRenderedListener.java",
"io/flutter/embedding/engine/systemchannels/AccessibilityChannel.java",
......
......@@ -178,7 +178,7 @@ public class FlutterActivity extends FragmentActivity implements OnFirstFrameRen
}
@Override
public void onCreate(Bundle savedInstanceState) {
protected void onCreate(Bundle savedInstanceState) {
Log.d(TAG, "onCreate()");
super.onCreate(savedInstanceState);
configureWindowForTransparency();
......
......@@ -9,6 +9,9 @@ import android.arch.lifecycle.LifecycleOwner;
import android.content.Context;
import android.support.annotation.NonNull;
import java.util.HashSet;
import java.util.Set;
import io.flutter.embedding.engine.dart.DartExecutor;
import io.flutter.embedding.engine.plugins.PluginRegistry;
import io.flutter.embedding.engine.plugins.activity.ActivityControlSurface;
......@@ -84,11 +87,13 @@ public class FlutterEngine implements LifecycleOwner {
@NonNull
private final TextInputChannel textInputChannel;
private final Set<EngineLifecycleListener> engineLifecycleListeners = new HashSet<>();
private final EngineLifecycleListener engineLifecycleListener = new EngineLifecycleListener() {
@SuppressWarnings("unused")
public void onPreEngineRestart() {
// TODO(mattcarroll): work into plugin API. should probably loop through each plugin.
// pluginRegistry.onPreEngineRestart();
for (EngineLifecycleListener lifecycleListener : engineLifecycleListeners) {
lifecycleListener.onPreEngineRestart();
}
}
};
......@@ -165,6 +170,22 @@ public class FlutterEngine implements LifecycleOwner {
flutterJNI.detachFromNativeAndReleaseResources();
}
/**
* Adds a {@code listener} to be notified of Flutter engine lifecycle events, e.g.,
* {@code onPreEngineStart()}.
*/
public void addEngineLifecycleListener(@NonNull EngineLifecycleListener listener) {
engineLifecycleListeners.add(listener);
}
/**
* Removes a {@code listener} that was previously added with
* {@link #addEngineLifecycleListener(EngineLifecycleListener)}.
*/
public void removeEngineLifecycleListener(@NonNull EngineLifecycleListener listener) {
engineLifecycleListeners.remove(listener);
}
/**
* The Dart execution context associated with this {@code 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.engine.plugins.shim;
import android.app.Activity;
import android.support.annotation.NonNull;
import java.util.HashMap;
import java.util.Map;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.plugin.common.PluginRegistry;
import io.flutter.plugin.platform.PlatformViewsController;
import io.flutter.view.FlutterView;
/**
* A {@link PluginRegistry} that is shimmed to use the new Android embedding and plugin API behind
* the scenes.
* <p>
* The following is an example usage of {@code ShimPluginRegistry} within a {@code FlutterActivity}:
* {@code
* // Create the FlutterEngine that will back the Flutter UI.
* FlutterEngine flutterEngine = new FlutterEngine(context);
*
* // Create a ShimPluginRegistry and wrap the FlutterEngine with the shim.
* ShimPluginRegistry shimPluginRegistry = new ShimPluginRegistry(flutterEngine, platformViewsController);
*
* // Use the GeneratedPluginRegistrant to add every plugin that's in the pubspec.
* GeneratedPluginRegistrant.registerWith(shimPluginRegistry);
* }
*/
public class ShimPluginRegistry implements PluginRegistry {
private final FlutterEngine flutterEngine;
private final PlatformViewsController platformViewsController;
private final Map<String, Object> pluginMap = new HashMap<>();
private final FlutterEngine.EngineLifecycleListener engineLifecycleListener = new FlutterEngine.EngineLifecycleListener() {
@Override
public void onPreEngineRestart() {
ShimPluginRegistry.this.onPreEngineRestart();
}
};
public ShimPluginRegistry(
@NonNull FlutterEngine flutterEngine,
@NonNull PlatformViewsController platformViewsController
) {
this.flutterEngine = flutterEngine;
this.flutterEngine.addEngineLifecycleListener(engineLifecycleListener);
this.platformViewsController = platformViewsController;
}
@Override
public Registrar registrarFor(String pluginKey) {
if (pluginMap.containsKey(pluginKey)) {
throw new IllegalStateException("Plugin key " + pluginKey + " is already in use");
}
pluginMap.put(pluginKey, null);
ShimRegistrar registrar = new ShimRegistrar(pluginKey, pluginMap);
flutterEngine.getPlugins().add(registrar);
return registrar;
}
@Override
public boolean hasPlugin(String pluginKey) {
return pluginMap.containsKey(pluginKey);
}
@Override
public <T> T valuePublishedByPlugin(String pluginKey) {
return (T) pluginMap.get(pluginKey);
}
//----- From FlutterPluginRegistry that aren't in the PluginRegistry interface ----//
public void attach(FlutterView flutterView, Activity activity) {
platformViewsController.attach(activity, flutterEngine.getRenderer(), flutterEngine.getDartExecutor());
}
public void detach() {
platformViewsController.detach();
platformViewsController.onFlutterViewDestroyed();
}
private void onPreEngineRestart() {
platformViewsController.onPreEngineRestart();
}
public PlatformViewsController getPlatformViewsController() {
return platformViewsController;
}
}
// 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.engine.plugins.shim;
import android.app.Activity;
import android.content.Context;
import android.support.annotation.NonNull;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.embedding.engine.plugins.activity.ActivityAware;
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.PluginRegistry;
import io.flutter.plugin.platform.PlatformViewRegistry;
import io.flutter.view.FlutterMain;
import io.flutter.view.FlutterView;
import io.flutter.view.TextureRegistry;
/**
* A {@link PluginRegistry.Registrar} that is shimmed to use the new Android embedding and plugin
* API behind the scenes.
* <p>
* Instances of {@code ShimRegistrar}s are vended internally by a {@link ShimPluginRegistry}.
*/
class ShimRegistrar implements PluginRegistry.Registrar, FlutterPlugin, ActivityAware {
private static final String TAG = "ShimRegistrar";
private final Map<String, Object> globalRegistrarMap;
private final String pluginId;
private final Set<PluginRegistry.ViewDestroyListener> viewDestroyListeners = new HashSet<>();
private final Set<PluginRegistry.RequestPermissionsResultListener> requestPermissionsResultListeners = new HashSet<>();
private final Set<PluginRegistry.ActivityResultListener> activityResultListeners = new HashSet<>();
private final Set<PluginRegistry.NewIntentListener> newIntentListeners = new HashSet<>();
private final Set<PluginRegistry.UserLeaveHintListener> userLeaveHintListeners = new HashSet<>();
private FlutterPlugin.FlutterPluginBinding pluginBinding;
private ActivityPluginBinding activityPluginBinding;
public ShimRegistrar(@NonNull String pluginId, @NonNull Map<String, Object> globalRegistrarMap) {
this.pluginId = pluginId;
this.globalRegistrarMap = globalRegistrarMap;
}
@Override
public Activity activity() {
return activityPluginBinding != null ? activityPluginBinding.getActivity() : null;
}
@Override
public Context context() {
return pluginBinding != null ? pluginBinding.getApplicationContext() : null;
}
@Override
public Context activeContext() {
return activityPluginBinding == null ? context() : activity();
}
@Override
public BinaryMessenger messenger() {
return pluginBinding != null ? pluginBinding.getFlutterEngine().getDartExecutor() : null;
}
@Override
public TextureRegistry textures() {
return pluginBinding != null ? pluginBinding.getFlutterEngine().getRenderer() : null;
}
@Override
public PlatformViewRegistry platformViewRegistry() {
return null;
}
@Override
public FlutterView view() {
throw new UnsupportedOperationException("The new embedding does not support the old FlutterView.");
}
@Override
public String lookupKeyForAsset(String asset) {
return FlutterMain.getLookupKeyForAsset(asset);
}
@Override
public String lookupKeyForAsset(String asset, String packageName) {
return FlutterMain.getLookupKeyForAsset(asset, packageName);
}
@Override
public PluginRegistry.Registrar publish(Object value) {
globalRegistrarMap.put(pluginId, value);
return this;
}
@Override
public PluginRegistry.Registrar addRequestPermissionsResultListener(PluginRegistry.RequestPermissionsResultListener listener) {
requestPermissionsResultListeners.add(listener);
if (activityPluginBinding != null) {
activityPluginBinding.addRequestPermissionsResultListener(listener);
}
return this;
}
@Override
public PluginRegistry.Registrar addActivityResultListener(PluginRegistry.ActivityResultListener listener) {
activityResultListeners.add(listener);
if (activityPluginBinding != null) {
activityPluginBinding.addActivityResultListener(listener);
}
return this;
}
@Override
public PluginRegistry.Registrar addNewIntentListener(PluginRegistry.NewIntentListener listener) {
newIntentListeners.add(listener);
if (activityPluginBinding != null) {
activityPluginBinding.addOnNewIntentListener(listener);
}
return this;
}
@Override
public PluginRegistry.Registrar addUserLeaveHintListener(PluginRegistry.UserLeaveHintListener listener) {
userLeaveHintListeners.add(listener);
if (activityPluginBinding != null) {
activityPluginBinding.addOnUserLeaveHintListener(listener);
}
return this;
}
@Override
@NonNull
public PluginRegistry.Registrar addViewDestroyListener(@NonNull PluginRegistry.ViewDestroyListener listener) {
viewDestroyListeners.add(listener);
return this;
}
@Override
public void onAttachedToEngine(@NonNull FlutterPluginBinding binding) {
pluginBinding = binding;
}
@Override
public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
for (PluginRegistry.ViewDestroyListener listener : viewDestroyListeners) {
// The following invocation might produce unexpected behavior in old plugins because
// we have no FlutterNativeView to pass to onViewDestroy(). This is a limitation of this shim.
listener.onViewDestroy(null);
}
pluginBinding = null;
}
@Override
public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) {
activityPluginBinding = binding;
addExistingListenersToActivityPluginBinding();
}
@Override
public void onDetachedFromActivityForConfigChanges() {
activityPluginBinding = null;
}
@Override
public void onReattachedToActivityForConfigChanges(@NonNull ActivityPluginBinding binding) {
activityPluginBinding = binding;
addExistingListenersToActivityPluginBinding();
}
@Override
public void onDetachedFromActivity() {
activityPluginBinding = null;
}
private void addExistingListenersToActivityPluginBinding() {
for (PluginRegistry.RequestPermissionsResultListener listener : requestPermissionsResultListeners) {
activityPluginBinding.addRequestPermissionsResultListener(listener);
}
for (PluginRegistry.ActivityResultListener listener : activityResultListeners) {
activityPluginBinding.addActivityResultListener(listener);
}
for (PluginRegistry.NewIntentListener listener : newIntentListeners) {
activityPluginBinding.addOnNewIntentListener(listener);
}
for (PluginRegistry.UserLeaveHintListener listener : userLeaveHintListeners) {
activityPluginBinding.addOnUserLeaveHintListener(listener);
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册