未验证 提交 619f452e 编写于 作者: Z Zachary Anderson 提交者: GitHub

[Android] Extract the PluginRegistry from the FlutterActivity (#4393)

上级 77d8acb9
......@@ -89,6 +89,7 @@ java_library("flutter_shell_java") {
"io/flutter/app/FlutterActivityEvents.java",
"io/flutter/app/FlutterApplication.java",
"io/flutter/app/FlutterFragmentActivity.java",
"io/flutter/app/FlutterPluginRegistry.java",
"io/flutter/plugin/common/ActivityLifecycleListener.java",
"io/flutter/plugin/common/BasicMessageChannel.java",
"io/flutter/plugin/common/BinaryCodec.java",
......
......@@ -91,13 +91,6 @@ public final class FlutterActivityDelegate
private final Activity activity;
private final ViewFactory viewFactory;
private final Map<String, Object> pluginMap = new LinkedHashMap<>(0);
private final List<RequestPermissionResultListener> requestPermissionResultListeners = new ArrayList<>(0);
private final List<ActivityResultListener> activityResultListeners = new ArrayList<>(0);
private final List<NewIntentListener> newIntentListeners = new ArrayList<>(0);
private final List<UserLeaveHintListener> userLeaveHintListeners = new ArrayList<>(0);
private final List<ViewDestroyListener> viewDestroyListeners = new ArrayList<>(0);
private FlutterView flutterView;
private View launchView;
......@@ -111,45 +104,32 @@ public final class FlutterActivityDelegate
return flutterView;
}
// The implementation of PluginRegistry forwards to flutterView.
@Override
public boolean hasPlugin(String key) {
return pluginMap.containsKey(key);
return flutterView.getPluginRegistry().hasPlugin(key);
}
@Override
@SuppressWarnings("unchecked")
public <T> T valuePublishedByPlugin(String pluginKey) {
return (T) pluginMap.get(pluginKey);
return (T) flutterView.getPluginRegistry().valuePublishedByPlugin(pluginKey);
}
@Override
public Registrar registrarFor(String pluginKey) {
if (pluginMap.containsKey(pluginKey)) {
throw new IllegalStateException("Plugin key " + pluginKey + " is already in use");
}
pluginMap.put(pluginKey, null);
return new FlutterRegistrar(pluginKey);
return flutterView.getPluginRegistry().registrarFor(pluginKey);
}
@Override
public boolean onRequestPermissionResult(
int requestCode, String[] permissions, int[] grantResults) {
for (RequestPermissionResultListener listener : requestPermissionResultListeners) {
if (listener.onRequestPermissionResult(requestCode, permissions, grantResults)) {
return true;
}
}
return false;
return flutterView.getPluginRegistry().onRequestPermissionResult(requestCode, permissions, grantResults);
}
@Override
public boolean onActivityResult(int requestCode, int resultCode, Intent data) {
for (ActivityResultListener listener : activityResultListeners) {
if (listener.onActivityResult(requestCode, resultCode, data)) {
return true;
}
}
return false;
return flutterView.getPluginRegistry().onActivityResult(requestCode, resultCode, data);
}
@Override
......@@ -196,11 +176,7 @@ public final class FlutterActivityDelegate
// Only attempt to reload the Flutter Dart code during development. Use
// the debuggable flag as an indicator that we are in development mode.
if (!isDebuggable() || !loadIntent(intent)) {
for (NewIntentListener listener : newIntentListeners) {
if (listener.onNewIntent(intent)) {
return;
}
}
flutterView.getPluginRegistry().onNewIntent(intent);
}
}
......@@ -253,18 +229,14 @@ public final class FlutterActivityDelegate
}
}
if (flutterView != null) {
boolean destroy = true;
for (ViewDestroyListener listener : viewDestroyListeners) {
if (listener.onViewDestroy(flutterView.getFlutterNativeView())) {
destroy = false;
}
}
if (destroy) {
flutterView.destroy();
} else {
final boolean detach =
flutterView.getPluginRegistry().onViewDestroy(flutterView.getFlutterNativeView());
if (detach) {
// Detach, but do not destroy the FlutterView if a plugin
// expressed interest in its FlutterNativeView.
flutterView.detach();
} else {
flutterView.destroy();
}
}
}
......@@ -280,6 +252,7 @@ public final class FlutterActivityDelegate
@Override
public void onUserLeaveHint() {
flutterView.getPluginRegistry().onUserLeaveHint();
}
@Override
......@@ -463,82 +436,4 @@ public final class FlutterActivityDelegate
// We can make this configurable if users want it.
activity.setTheme(android.R.style.Theme_Black_NoTitleBar);
}
private class FlutterRegistrar implements Registrar {
private final String pluginKey;
FlutterRegistrar(String pluginKey) {
this.pluginKey = pluginKey;
}
@Override
public Activity activity() {
return activity;
}
@Override
public BinaryMessenger messenger() {
return flutterView;
}
@Override
public TextureRegistry textures() {
return flutterView;
}
@Override
public FlutterView view() {
return flutterView;
}
/**
* Publishes a value associated with the plugin being registered.
*
* <p>The published value is available to interested clients via
* {@link PluginRegistry#valuePublishedByPlugin(String)}.</p>
*
* <p>Publication should be done only when there is an interesting value
* to be shared with other code. This would typically be an instance of
* the plugin's main class itself that must be wired up to receive
* notifications or events from an Android API.
*
* <p>Overwrites any previously published value.</p>
*/
@Override
public Registrar publish(Object value) {
pluginMap.put(pluginKey, value);
return this;
}
@Override
public Registrar addRequestPermissionResultListener(
RequestPermissionResultListener listener) {
requestPermissionResultListeners.add(listener);
return this;
}
@Override
public Registrar addActivityResultListener(ActivityResultListener listener) {
activityResultListeners.add(listener);
return this;
}
@Override
public Registrar addNewIntentListener(NewIntentListener listener) {
newIntentListeners.add(listener);
return this;
}
@Override
public Registrar addUserLeaveHintListener(UserLeaveHintListener listener) {
userLeaveHintListeners.add(listener);
return this;
}
@Override
public Registrar addViewDestroyListener(ViewDestroyListener listener) {
viewDestroyListeners.add(listener);
return this;
}
}
}
// Copyright 2017 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.app;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import io.flutter.plugin.common.*;
import io.flutter.view.FlutterNativeView;
import io.flutter.view.FlutterView;
import io.flutter.view.TextureRegistry;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
public class FlutterPluginRegistry
implements PluginRegistry,
PluginRegistry.RequestPermissionResultListener,
PluginRegistry.ActivityResultListener,
PluginRegistry.NewIntentListener,
PluginRegistry.UserLeaveHintListener,
PluginRegistry.ViewDestroyListener {
private static final String TAG = "FlutterPluginRegistry";
private Activity mActivity;
private Context mAppContext;
private FlutterNativeView mNativeView;
private FlutterView mFlutterView;
private final Map<String, Object> mPluginMap = new LinkedHashMap<>(0);
private final List<RequestPermissionResultListener> mRequestPermissionResultListeners = new ArrayList<>(0);
private final List<ActivityResultListener> mActivityResultListeners = new ArrayList<>(0);
private final List<NewIntentListener> mNewIntentListeners = new ArrayList<>(0);
private final List<UserLeaveHintListener> mUserLeaveHintListeners = new ArrayList<>(0);
private final List<ViewDestroyListener> mViewDestroyListeners = new ArrayList<>(0);
public FlutterPluginRegistry(FlutterNativeView nativeView, Context context) {
mNativeView = nativeView;
mAppContext = context;
}
@Override
public boolean hasPlugin(String key) {
return mPluginMap.containsKey(key);
}
@Override
@SuppressWarnings("unchecked")
public <T> T valuePublishedByPlugin(String pluginKey) {
return (T) mPluginMap.get(pluginKey);
}
@Override
public Registrar registrarFor(String pluginKey) {
if (mPluginMap.containsKey(pluginKey)) {
throw new IllegalStateException("Plugin key " + pluginKey + " is already in use");
}
mPluginMap.put(pluginKey, null);
return new FlutterRegistrar(pluginKey);
}
public void attach(FlutterView flutterView, Activity activity) {
mFlutterView = flutterView;
mActivity = activity;
}
public void detach() {
mFlutterView = null;
mActivity = null;
}
private class FlutterRegistrar implements Registrar {
private final String pluginKey;
FlutterRegistrar(String pluginKey) {
this.pluginKey = pluginKey;
}
@Override
public Activity activity() {
return mActivity;
}
@Override
public Context context() {
return mAppContext;
}
@Override
public BinaryMessenger messenger() {
return mNativeView;
}
@Override
public TextureRegistry textures() {
return mFlutterView;
}
@Override
public FlutterView view() {
return mFlutterView;
}
@Override
public Registrar publish(Object value) {
mPluginMap.put(pluginKey, value);
return this;
}
@Override
public Registrar addRequestPermissionResultListener(
RequestPermissionResultListener listener) {
mRequestPermissionResultListeners.add(listener);
return this;
}
@Override
public Registrar addActivityResultListener(ActivityResultListener listener) {
mActivityResultListeners.add(listener);
return this;
}
@Override
public Registrar addNewIntentListener(NewIntentListener listener) {
mNewIntentListeners.add(listener);
return this;
}
@Override
public Registrar addUserLeaveHintListener(UserLeaveHintListener listener) {
mUserLeaveHintListeners.add(listener);
return this;
}
@Override
public Registrar addViewDestroyListener(ViewDestroyListener listener) {
mViewDestroyListeners.add(listener);
return this;
}
}
@Override
public boolean onRequestPermissionResult(int requestCode, String[] permissions, int[] grantResults) {
for (RequestPermissionResultListener listener : mRequestPermissionResultListeners) {
if (listener.onRequestPermissionResult(requestCode, permissions, grantResults)) {
return true;
}
}
return false;
}
@Override
public boolean onActivityResult(int requestCode, int resultCode, Intent data) {
for (ActivityResultListener listener : mActivityResultListeners) {
if (listener.onActivityResult(requestCode, resultCode, data)) {
return true;
}
}
return false;
}
@Override
public boolean onNewIntent(Intent intent) {
for (NewIntentListener listener : mNewIntentListeners) {
if (listener.onNewIntent(intent)) {
return true;
}
}
return false;
}
@Override
public void onUserLeaveHint() {
for (UserLeaveHintListener listener : mUserLeaveHintListeners) {
listener.onUserLeaveHint();
}
}
@Override
public boolean onViewDestroy(FlutterNativeView view) {
boolean handled = false;
for (ViewDestroyListener listener : mViewDestroyListeners) {
if (listener.onViewDestroy(view)) {
handled = true;
}
}
return handled;
}
}
......@@ -5,6 +5,7 @@
package io.flutter.plugin.common;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import io.flutter.view.FlutterNativeView;
import io.flutter.view.FlutterView;
......@@ -67,9 +68,18 @@ public interface PluginRegistry {
* {@link io.flutter.app.FlutterActivity} or
* {@link io.flutter.app.FlutterFragmentActivity}), as applications
* are free to use any activity subclass.</p>
*
* <p>When there is no foreground activity in the application, this
* will return null. If a {@link Context} is needed, use context() to
* get the application's context.</p>
*/
Activity activity();
/**
* Returns the {@link Application}'s {@link Context}.
*/
Context context();
/**
* Returns a {@link BinaryMessenger} which the plugin can use for
* creating channels for communicating with the Dart side.
......@@ -201,4 +211,15 @@ public interface PluginRegistry {
interface ViewDestroyListener {
boolean onViewDestroy(FlutterNativeView view);
}
/**
* Callback interface for registering plugins with a plugin registry.
*
* <p>For example, an Application may use this callback interface to
* provide a background service with a callback for calling its
* GeneratedPluginRegistrant.registerWith method.</p>
*/
interface PluginRegistrantCallback {
void registerWith(PluginRegistry registry);
}
}
......@@ -4,7 +4,10 @@
package io.flutter.view;
import android.app.Activity;
import android.content.Context;
import android.util.Log;
import io.flutter.app.FlutterPluginRegistry;
import io.flutter.plugin.common.*;
import java.nio.ByteBuffer;
import java.util.concurrent.atomic.AtomicBoolean;
......@@ -18,21 +21,19 @@ public class FlutterNativeView implements BinaryMessenger {
private int mNextReplyId = 1;
private final Map<Integer, BinaryReply> mPendingReplies = new HashMap<>();
private final FlutterPluginRegistry mPluginRegistry;
private long mNativePlatformView;
private FlutterView mFlutterView;
public FlutterNativeView(FlutterView flutterView) {
mFlutterView = flutterView;
public FlutterNativeView(Context context) {
mPluginRegistry = new FlutterPluginRegistry(this, context);
attach(this);
assertAttached();
mMessageHandlers = new HashMap<>();
}
public FlutterNativeView() {
this(null);
}
public void detach() {
mPluginRegistry.detach();
mFlutterView = null;
nativeDetach(mNativePlatformView);
}
......@@ -43,8 +44,13 @@ public class FlutterNativeView implements BinaryMessenger {
mNativePlatformView = 0;
}
public void setFlutterView(FlutterView flutterView) {
public FlutterPluginRegistry getPluginRegistry() {
return mPluginRegistry;
}
public void attachViewAndActivity(FlutterView flutterView, Activity activity) {
mFlutterView = flutterView;
mPluginRegistry.attach(flutterView, activity);
}
public boolean isAttached() {
......
......@@ -34,6 +34,7 @@ import android.view.accessibility.AccessibilityNodeProvider;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import io.flutter.app.FlutterActivity;
import io.flutter.app.FlutterPluginRegistry;
import io.flutter.plugin.common.*;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.editing.TextInputPlugin;
......@@ -132,12 +133,13 @@ public class FlutterView extends SurfaceView
setFocusable(true);
setFocusableInTouchMode(true);
Activity activity = (Activity) getContext();
if (nativeView == null) {
mNativeView = new FlutterNativeView(this);
mNativeView = new FlutterNativeView(activity.getApplicationContext());
} else {
mNativeView = nativeView;
mNativeView.setFlutterView(this);
}
mNativeView.attachViewAndActivity(this, activity);
int color = 0xFF000000;
TypedValue typedValue = new TypedValue();
......@@ -190,15 +192,11 @@ public class FlutterView extends SurfaceView
mFlutterSettingsChannel = new BasicMessageChannel<>(this, "flutter/settings",
JSONMessageCodec.INSTANCE);
// TODO(plugins): Change PlatformPlugin to accept a Context. Disable the
// operations that require an Activity when a Context is passed.
if (getContext() instanceof Activity) {
PlatformPlugin platformPlugin = new PlatformPlugin((Activity) getContext());
MethodChannel flutterPlatformChannel = new MethodChannel(this,
"flutter/platform", JSONMethodCodec.INSTANCE);
flutterPlatformChannel.setMethodCallHandler(platformPlugin);
addActivityLifecycleListener(platformPlugin);
}
PlatformPlugin platformPlugin = new PlatformPlugin(activity);
MethodChannel flutterPlatformChannel = new MethodChannel(this,
"flutter/platform", JSONMethodCodec.INSTANCE);
flutterPlatformChannel.setMethodCallHandler(platformPlugin);
addActivityLifecycleListener(platformPlugin);
mTextInputPlugin = new TextInputPlugin(this);
setLocale(getResources().getConfiguration().locale);
......@@ -252,6 +250,10 @@ public class FlutterView extends SurfaceView
return mNativeView;
}
public FlutterPluginRegistry getPluginRegistry() {
return mNativeView.getPluginRegistry();
}
public void addActivityLifecycleListener(ActivityLifecycleListener listener) {
mActivityLifecycleListeners.add(listener);
}
......
......@@ -1157,6 +1157,7 @@ FILE: ../../../flutter/shell/platform/android/android_surface_software.h
FILE: ../../../flutter/shell/platform/android/io/flutter/app/FlutterActivityDelegate.java
FILE: ../../../flutter/shell/platform/android/io/flutter/app/FlutterActivityEvents.java
FILE: ../../../flutter/shell/platform/android/io/flutter/app/FlutterFragmentActivity.java
FILE: ../../../flutter/shell/platform/android/io/flutter/app/FlutterPluginRegistry.java
FILE: ../../../flutter/shell/platform/android/io/flutter/plugin/common/BasicMessageChannel.java
FILE: ../../../flutter/shell/platform/android/io/flutter/plugin/common/BinaryCodec.java
FILE: ../../../flutter/shell/platform/android/io/flutter/plugin/common/BinaryMessenger.java
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册