mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
New Plugin API PR3: Introduces Service, BroadcastReceiver, and ContentProvider awareness, control surfaces, and plugin bindings. (flutter/engine#8962)
This commit is contained in:
parent
751367a83f
commit
443edceabb
@ -543,6 +543,7 @@ FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/android/Flutt
|
||||
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/android/FlutterTextureView.java
|
||||
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/android/FlutterView.java
|
||||
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/FlutterEngine.java
|
||||
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/FlutterEnginePluginRegistry.java
|
||||
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java
|
||||
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/FlutterShellArgs.java
|
||||
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/dart/DartExecutor.java
|
||||
@ -553,6 +554,15 @@ FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/plugin
|
||||
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/plugins/activity/ActivityAware.java
|
||||
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/plugins/activity/ActivityControlSurface.java
|
||||
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/plugins/activity/ActivityPluginBinding.java
|
||||
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/plugins/broadcastreceiver/BroadcastReceiverAware.java
|
||||
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/plugins/broadcastreceiver/BroadcastReceiverControlSurface.java
|
||||
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/plugins/broadcastreceiver/BroadcastReceiverPluginBinding.java
|
||||
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/plugins/contentprovider/ContentProviderAware.java
|
||||
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/plugins/contentprovider/ContentProviderControlSurface.java
|
||||
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/plugins/contentprovider/ContentProviderPluginBinding.java
|
||||
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/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
|
||||
|
||||
@ -128,6 +128,7 @@ action("flutter_shell_java") {
|
||||
"io/flutter/embedding/android/FlutterTextureView.java",
|
||||
"io/flutter/embedding/android/FlutterView.java",
|
||||
"io/flutter/embedding/engine/FlutterEngine.java",
|
||||
"io/flutter/embedding/engine/FlutterEnginePluginRegistry.java",
|
||||
"io/flutter/embedding/engine/FlutterJNI.java",
|
||||
"io/flutter/embedding/engine/FlutterShellArgs.java",
|
||||
"io/flutter/embedding/engine/dart/DartExecutor.java",
|
||||
@ -138,6 +139,15 @@ action("flutter_shell_java") {
|
||||
"io/flutter/embedding/engine/plugins/activity/ActivityAware.java",
|
||||
"io/flutter/embedding/engine/plugins/activity/ActivityControlSurface.java",
|
||||
"io/flutter/embedding/engine/plugins/activity/ActivityPluginBinding.java",
|
||||
"io/flutter/embedding/engine/plugins/broadcastreceiver/BroadcastReceiverAware.java",
|
||||
"io/flutter/embedding/engine/plugins/broadcastreceiver/BroadcastReceiverControlSurface.java",
|
||||
"io/flutter/embedding/engine/plugins/broadcastreceiver/BroadcastReceiverPluginBinding.java",
|
||||
"io/flutter/embedding/engine/plugins/contentprovider/ContentProviderAware.java",
|
||||
"io/flutter/embedding/engine/plugins/contentprovider/ContentProviderControlSurface.java",
|
||||
"io/flutter/embedding/engine/plugins/contentprovider/ContentProviderPluginBinding.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/renderer/FlutterRenderer.java",
|
||||
"io/flutter/embedding/engine/renderer/OnFirstFrameRenderedListener.java",
|
||||
"io/flutter/embedding/engine/systemchannels/AccessibilityChannel.java",
|
||||
|
||||
@ -4,25 +4,15 @@
|
||||
|
||||
package io.flutter.embedding.engine;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.arch.lifecycle.Lifecycle;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import io.flutter.embedding.engine.dart.DartExecutor;
|
||||
import io.flutter.embedding.engine.plugins.FlutterPlugin;
|
||||
import io.flutter.embedding.engine.plugins.PluginRegistry;
|
||||
import io.flutter.embedding.engine.plugins.activity.ActivityAware;
|
||||
import io.flutter.embedding.engine.plugins.activity.ActivityControlSurface;
|
||||
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
|
||||
import io.flutter.embedding.engine.plugins.broadcastreceiver.BroadcastReceiverControlSurface;
|
||||
import io.flutter.embedding.engine.plugins.contentprovider.ContentProviderControlSurface;
|
||||
import io.flutter.embedding.engine.plugins.service.ServiceControlSurface;
|
||||
import io.flutter.embedding.engine.renderer.FlutterRenderer;
|
||||
import io.flutter.embedding.engine.systemchannels.AccessibilityChannel;
|
||||
import io.flutter.embedding.engine.systemchannels.KeyEventChannel;
|
||||
@ -283,339 +273,19 @@ public class FlutterEngine {
|
||||
return pluginRegistry;
|
||||
}
|
||||
|
||||
private static class FlutterEnginePluginRegistry implements PluginRegistry, ActivityControlSurface {
|
||||
private final Map<Class<? extends FlutterPlugin>, FlutterPlugin> plugins = new HashMap<>();
|
||||
private final FlutterPlugin.FlutterPluginBinding pluginBinding;
|
||||
|
||||
private final Map<Class<? extends FlutterPlugin>, ActivityAware> activityAwarePlugins = new HashMap<>();
|
||||
private Activity activity;
|
||||
private FlutterEngineActivityPluginBinding activityPluginBinding;
|
||||
|
||||
FlutterEnginePluginRegistry(
|
||||
@NonNull Context appContext,
|
||||
@NonNull FlutterEngine flutterEngine,
|
||||
@NonNull Lifecycle lifecycle
|
||||
) {
|
||||
pluginBinding = new FlutterPlugin.FlutterPluginBinding(
|
||||
appContext,
|
||||
flutterEngine,
|
||||
lifecycle
|
||||
);
|
||||
}
|
||||
|
||||
public void add(@NonNull FlutterPlugin plugin) {
|
||||
// Add the plugin to our generic set of plugins and notify the plugin
|
||||
// that is has been attached to an engine.
|
||||
plugins.put(plugin.getClass(), plugin);
|
||||
plugin.onAttachedToEngine(pluginBinding);
|
||||
|
||||
// For ActivityAware plugins, add the plugin to our set of ActivityAware
|
||||
// plugins, and if this engine is currently attached to an Activity,
|
||||
// notify the ActivityAware plugin that it is now attached to an Activity.
|
||||
if (plugin instanceof ActivityAware) {
|
||||
ActivityAware activityAware = (ActivityAware) plugin;
|
||||
activityAwarePlugins.put(plugin.getClass(), activityAware);
|
||||
|
||||
if (isAttachedToActivity()) {
|
||||
activityAware.onAttachedToActivity(activityPluginBinding);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(mattcarroll): ServiceAware
|
||||
// TODO(mattcarroll): BroadcastReceiverAware
|
||||
// TODO(mattcarroll): ContentProviderAware
|
||||
}
|
||||
|
||||
public void add(@NonNull Set<FlutterPlugin> plugins) {
|
||||
for (FlutterPlugin plugin : plugins) {
|
||||
add(plugin);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean has(@NonNull Class<? extends FlutterPlugin> pluginClass) {
|
||||
return plugins.containsKey(pluginClass);
|
||||
}
|
||||
|
||||
public FlutterPlugin get(@NonNull Class<? extends FlutterPlugin> pluginClass) {
|
||||
return plugins.get(pluginClass);
|
||||
}
|
||||
|
||||
public void remove(@NonNull Class<? extends FlutterPlugin> pluginClass) {
|
||||
FlutterPlugin plugin = plugins.get(pluginClass);
|
||||
if (plugin != null) {
|
||||
// For ActivityAware plugins, notify the plugin that it is detached from
|
||||
// an Activity if an Activity is currently attached to this engine. Then
|
||||
// remove the plugin from our set of ActivityAware plugins.
|
||||
if (plugin instanceof ActivityAware) {
|
||||
if (isAttachedToActivity()) {
|
||||
ActivityAware activityAware = (ActivityAware) plugin;
|
||||
activityAware.onDetachedFromActivity();
|
||||
}
|
||||
activityAwarePlugins.remove(pluginClass);
|
||||
}
|
||||
|
||||
// TODO(mattcarroll): ServiceAware
|
||||
// TODO(mattcarroll): BroadcastReceiverAware
|
||||
// TODO(mattcarroll): ContentProviderAware
|
||||
|
||||
// Notify the plugin that is now detached from this engine. Then remove
|
||||
// it from our set of generic plugins.
|
||||
plugin.onDetachedFromEngine(pluginBinding);
|
||||
plugins.remove(pluginClass);
|
||||
}
|
||||
}
|
||||
|
||||
public void remove(@NonNull Set<Class<? extends FlutterPlugin>> pluginClasses) {
|
||||
for (Class<? extends FlutterPlugin> pluginClass : pluginClasses) {
|
||||
remove(pluginClass);
|
||||
}
|
||||
}
|
||||
|
||||
public void removeAll() {
|
||||
// We copy the keys to a new set so that we can mutate the set while using
|
||||
// the keys.
|
||||
remove(new HashSet<>(plugins.keySet()));
|
||||
plugins.clear();
|
||||
}
|
||||
|
||||
//-------- Start ActivityControlSurface -------
|
||||
boolean isAttachedToActivity() {
|
||||
return activity != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void attachToActivity(@NonNull Activity activity, @NonNull Lifecycle lifecycle) {
|
||||
Log.d(TAG, "Attaching to an Activity.");
|
||||
// If we were already attached to an Activity, detach from it before attaching to
|
||||
// the new Activity.
|
||||
if (isAttachedToActivity()) {
|
||||
for (ActivityAware activityAware : activityAwarePlugins.values()) {
|
||||
activityAware.onDetachedFromActivity();
|
||||
}
|
||||
}
|
||||
|
||||
this.activity = activity;
|
||||
this.activityPluginBinding = new FlutterEngineActivityPluginBinding(activity);
|
||||
// TODO(mattcarroll): resolve possibility of different lifecycles between this and engine attachment
|
||||
|
||||
// Notify all ActivityAware plugins that they are now attached to a new Activity.
|
||||
for (ActivityAware activityAware : activityAwarePlugins.values()) {
|
||||
activityAware.onAttachedToActivity(activityPluginBinding);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void detachFromActivityForConfigChanges() {
|
||||
Log.d(TAG, "Detaching from an Activity for config changes.");
|
||||
if (isAttachedToActivity()) {
|
||||
for (ActivityAware activityAware : activityAwarePlugins.values()) {
|
||||
activityAware.onDetachedFromActivityForConfigChanges();
|
||||
}
|
||||
|
||||
activity = null;
|
||||
activityPluginBinding = null;
|
||||
} else {
|
||||
Log.e(TAG, "Attempted to detach plugins from an Activity when no Activity was attached.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reattachToActivityAfterConfigChange(@NonNull Activity activity) {
|
||||
Log.d(TAG, "Re-attaching to an Activity after config change.");
|
||||
if (!isAttachedToActivity()) {
|
||||
this.activity = activity;
|
||||
activityPluginBinding = new FlutterEngineActivityPluginBinding(activity);
|
||||
|
||||
for (ActivityAware activityAware : activityAwarePlugins.values()) {
|
||||
activityAware.onReattachedToActivityForConfigChanges(activityPluginBinding);
|
||||
}
|
||||
} else {
|
||||
Log.e(TAG, "Attempted to reattach plugins to an Activity after config changes, but an Activity was already attached.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void detachFromActivity() {
|
||||
Log.d(TAG, "Detaching from an Activity.");
|
||||
if (isAttachedToActivity()) {
|
||||
for (ActivityAware activityAware : activityAwarePlugins.values()) {
|
||||
activityAware.onDetachedFromActivity();
|
||||
}
|
||||
|
||||
activity = null;
|
||||
activityPluginBinding = null;
|
||||
} else {
|
||||
Log.e(TAG, "Attempted to detach plugins from an Activity when no Activity was attached.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResult) {
|
||||
Log.d(TAG, "Forwarding onRequestPermissionsResult() to plugins.");
|
||||
if (isAttachedToActivity()) {
|
||||
return activityPluginBinding.onRequestPermissionsResult(requestCode, permissions, grantResult);
|
||||
} else {
|
||||
Log.e(TAG, "Attempted to notify ActivityAware plugins of onRequestPermissionsResult, but no Activity was attached.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onActivityResult(int requestCode, int resultCode, @NonNull Intent data) {
|
||||
Log.d(TAG, "Forwarding onActivityResult() to plugins.");
|
||||
if (isAttachedToActivity()) {
|
||||
return activityPluginBinding.onActivityResult(requestCode, resultCode, data);
|
||||
} else {
|
||||
Log.e(TAG, "Attempted to notify ActivityAware plugins of onActivityResult, but no Activity was attached.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNewIntent(@NonNull Intent intent) {
|
||||
Log.d(TAG, "Forwarding onNewIntent() to plugins.");
|
||||
if (isAttachedToActivity()) {
|
||||
activityPluginBinding.onNewIntent(intent);
|
||||
} else {
|
||||
Log.e(TAG, "Attempted to notify ActivityAware plugins of onNewIntent, but no Activity was attached.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUserLeaveHint() {
|
||||
Log.d(TAG, "Forwarding onUserLeaveHint() to plugins.");
|
||||
if (isAttachedToActivity()) {
|
||||
activityPluginBinding.onUserLeaveHint();
|
||||
} else {
|
||||
Log.e(TAG, "Attempted to notify ActivityAware plugins of onUserLeaveHint, but no Activity was attached.");
|
||||
}
|
||||
}
|
||||
//------- End ActivityControlSurface -----
|
||||
@NonNull
|
||||
public ServiceControlSurface getServiceControlSurface() {
|
||||
return pluginRegistry;
|
||||
}
|
||||
|
||||
private static class FlutterEngineActivityPluginBinding implements ActivityPluginBinding {
|
||||
private final Activity activity;
|
||||
private final Set<io.flutter.plugin.common.PluginRegistry.RequestPermissionsResultListener> onRequestPermissionsResultListeners = new HashSet<>();
|
||||
private final Set<io.flutter.plugin.common.PluginRegistry.ActivityResultListener> onActivityResultListeners = new HashSet<>();
|
||||
private final Set<io.flutter.plugin.common.PluginRegistry.NewIntentListener> onNewIntentListeners = new HashSet<>();
|
||||
private final Set<io.flutter.plugin.common.PluginRegistry.UserLeaveHintListener> onUserLeaveHintListeners = new HashSet<>();
|
||||
@NonNull
|
||||
public BroadcastReceiverControlSurface getBroadcastReceiverControlSurface() {
|
||||
return pluginRegistry;
|
||||
}
|
||||
|
||||
public FlutterEngineActivityPluginBinding(@NonNull Activity activity) {
|
||||
this.activity = activity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link Activity} that is currently attached to the {@link FlutterEngine} that
|
||||
* owns this {@code ActivityPluginBinding}.
|
||||
*/
|
||||
@NonNull
|
||||
public Activity getActivity() {
|
||||
return activity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a listener that is invoked whenever the associated {@link Activity}'s
|
||||
* {@code onRequestPermissionsResult(...)} method is invoked.
|
||||
*/
|
||||
public void addRequestPermissionsResultListener(@NonNull io.flutter.plugin.common.PluginRegistry.RequestPermissionsResultListener listener) {
|
||||
onRequestPermissionsResultListeners.add(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a listener that was added in {@link #addRequestPermissionsResultListener(io.flutter.plugin.common.PluginRegistry.RequestPermissionsResultListener)}.
|
||||
*/
|
||||
public void removeRequestPermissionsResultListener(@NonNull io.flutter.plugin.common.PluginRegistry.RequestPermissionsResultListener listener) {
|
||||
onRequestPermissionsResultListeners.remove(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked by the {@link FlutterEngine} that owns this {@code ActivityPluginBinding} when its
|
||||
* associated {@link Activity} has its {@code onRequestPermissionsResult(...)} method invoked.
|
||||
*/
|
||||
boolean onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResult) {
|
||||
boolean didConsumeResult = false;
|
||||
for (io.flutter.plugin.common.PluginRegistry.RequestPermissionsResultListener listener : onRequestPermissionsResultListeners) {
|
||||
didConsumeResult = listener.onRequestPermissionsResult(requestCode, permissions, grantResult) || didConsumeResult;
|
||||
}
|
||||
return didConsumeResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a listener that is invoked whenever the associated {@link Activity}'s
|
||||
* {@code onActivityResult(...)} method is invoked.
|
||||
*/
|
||||
public void addActivityResultListener(@NonNull io.flutter.plugin.common.PluginRegistry.ActivityResultListener listener) {
|
||||
onActivityResultListeners.add(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a listener that was added in {@link #addActivityResultListener(io.flutter.plugin.common.PluginRegistry.ActivityResultListener)}.
|
||||
*/
|
||||
public void removeActivityResultListener(@NonNull io.flutter.plugin.common.PluginRegistry.ActivityResultListener listener) {
|
||||
onActivityResultListeners.remove(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked by the {@link FlutterEngine} that owns this {@code ActivityPluginBinding} when its
|
||||
* associated {@link Activity} has its {@code onActivityResult(...)} method invoked.
|
||||
*/
|
||||
boolean onActivityResult(int requestCode, int resultCode, @NonNull Intent data) {
|
||||
boolean didConsumeResult = false;
|
||||
for (io.flutter.plugin.common.PluginRegistry.ActivityResultListener listener : onActivityResultListeners) {
|
||||
didConsumeResult = listener.onActivityResult(requestCode, resultCode, data) || didConsumeResult;
|
||||
}
|
||||
return didConsumeResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a listener that is invoked whenever the associated {@link Activity}'s
|
||||
* {@code onNewIntent(...)} method is invoked.
|
||||
*/
|
||||
public void addOnNewIntentListener(@NonNull io.flutter.plugin.common.PluginRegistry.NewIntentListener listener) {
|
||||
onNewIntentListeners.add(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a listener that was added in {@link #addOnNewIntentListener(io.flutter.plugin.common.PluginRegistry.NewIntentListener)}.
|
||||
*/
|
||||
public void removeOnNewIntentListener(@NonNull io.flutter.plugin.common.PluginRegistry.NewIntentListener listener) {
|
||||
onNewIntentListeners.remove(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked by the {@link FlutterEngine} that owns this {@code ActivityPluginBinding} when its
|
||||
* associated {@link Activity} has its {@code onNewIntent(...)} method invoked.
|
||||
*/
|
||||
void onNewIntent(@Nullable Intent intent) {
|
||||
for (io.flutter.plugin.common.PluginRegistry.NewIntentListener listener : onNewIntentListeners) {
|
||||
listener.onNewIntent(intent);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a listener that is invoked whenever the associated {@link Activity}'s
|
||||
* {@code onUserLeaveHint()} method is invoked.
|
||||
*/
|
||||
public void addOnUserLeaveHintListener(@NonNull io.flutter.plugin.common.PluginRegistry.UserLeaveHintListener listener) {
|
||||
onUserLeaveHintListeners.add(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a listener that was added in {@link #addOnUserLeaveHintListener(io.flutter.plugin.common.PluginRegistry.UserLeaveHintListener)}.
|
||||
*/
|
||||
public void removeOnUserLeaveHintListener(@NonNull io.flutter.plugin.common.PluginRegistry.UserLeaveHintListener listener) {
|
||||
onUserLeaveHintListeners.remove(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked by the {@link FlutterEngine} that owns this {@code ActivityPluginBinding} when its
|
||||
* associated {@link Activity} has its {@code onUserLeaveHint()} method invoked.
|
||||
*/
|
||||
void onUserLeaveHint() {
|
||||
for (io.flutter.plugin.common.PluginRegistry.UserLeaveHintListener listener : onUserLeaveHintListeners) {
|
||||
listener.onUserLeaveHint();
|
||||
}
|
||||
}
|
||||
@NonNull
|
||||
public ContentProviderControlSurface getContentProviderControlSurface() {
|
||||
return pluginRegistry;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -0,0 +1,642 @@
|
||||
// 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;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Service;
|
||||
import android.arch.lifecycle.Lifecycle;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ContentProvider;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.HashMap;
|
||||
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.PluginRegistry;
|
||||
import io.flutter.embedding.engine.plugins.activity.ActivityAware;
|
||||
import io.flutter.embedding.engine.plugins.activity.ActivityControlSurface;
|
||||
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
|
||||
import io.flutter.embedding.engine.plugins.broadcastreceiver.BroadcastReceiverAware;
|
||||
import io.flutter.embedding.engine.plugins.broadcastreceiver.BroadcastReceiverControlSurface;
|
||||
import io.flutter.embedding.engine.plugins.broadcastreceiver.BroadcastReceiverPluginBinding;
|
||||
import io.flutter.embedding.engine.plugins.contentprovider.ContentProviderAware;
|
||||
import io.flutter.embedding.engine.plugins.contentprovider.ContentProviderControlSurface;
|
||||
import io.flutter.embedding.engine.plugins.contentprovider.ContentProviderPluginBinding;
|
||||
import io.flutter.embedding.engine.plugins.service.ServiceAware;
|
||||
import io.flutter.embedding.engine.plugins.service.ServiceControlSurface;
|
||||
import io.flutter.embedding.engine.plugins.service.ServicePluginBinding;
|
||||
|
||||
class FlutterEnginePluginRegistry implements PluginRegistry,
|
||||
ActivityControlSurface,
|
||||
ServiceControlSurface,
|
||||
BroadcastReceiverControlSurface,
|
||||
ContentProviderControlSurface {
|
||||
private static final String TAG = "EnginePluginRegistry";
|
||||
|
||||
// PluginRegistry
|
||||
private final Map<Class<? extends FlutterPlugin>, FlutterPlugin> plugins = new HashMap<>();
|
||||
|
||||
// Standard FlutterPlugin
|
||||
private final FlutterPlugin.FlutterPluginBinding pluginBinding;
|
||||
|
||||
// ActivityAware
|
||||
private final Map<Class<? extends FlutterPlugin>, ActivityAware> activityAwarePlugins = new HashMap<>();
|
||||
private Activity activity;
|
||||
private FlutterEngineActivityPluginBinding activityPluginBinding;
|
||||
|
||||
// ServiceAware
|
||||
private final Map<Class<? extends FlutterPlugin>, ServiceAware> serviceAwarePlugins = new HashMap<>();
|
||||
private Service service;
|
||||
private FlutterEngineServicePluginBinding servicePluginBinding;
|
||||
|
||||
// BroadcastReceiver
|
||||
private final Map<Class<? extends FlutterPlugin>, BroadcastReceiverAware> broadcastReceiverAwarePlugins = new HashMap<>();
|
||||
private BroadcastReceiver broadcastReceiver;
|
||||
private FlutterEngineBroadcastReceiverPluginBinding broadcastReceiverPluginBinding;
|
||||
|
||||
// ContentProvider
|
||||
private final Map<Class<? extends FlutterPlugin>, ContentProviderAware> contentProviderAwarePlugins = new HashMap<>();
|
||||
private ContentProvider contentProvider;
|
||||
private FlutterEngineContentProviderPluginBinding contentProviderPluginBinding;
|
||||
|
||||
FlutterEnginePluginRegistry(
|
||||
@NonNull Context appContext,
|
||||
@NonNull FlutterEngine flutterEngine,
|
||||
@NonNull Lifecycle lifecycle
|
||||
) {
|
||||
pluginBinding = new FlutterPlugin.FlutterPluginBinding(
|
||||
appContext,
|
||||
flutterEngine,
|
||||
lifecycle
|
||||
);
|
||||
}
|
||||
|
||||
public void add(@NonNull FlutterPlugin plugin) {
|
||||
// Add the plugin to our generic set of plugins and notify the plugin
|
||||
// that is has been attached to an engine.
|
||||
plugins.put(plugin.getClass(), plugin);
|
||||
plugin.onAttachedToEngine(pluginBinding);
|
||||
|
||||
// For ActivityAware plugins, add the plugin to our set of ActivityAware
|
||||
// plugins, and if this engine is currently attached to an Activity,
|
||||
// notify the ActivityAware plugin that it is now attached to an Activity.
|
||||
if (plugin instanceof ActivityAware) {
|
||||
ActivityAware activityAware = (ActivityAware) plugin;
|
||||
activityAwarePlugins.put(plugin.getClass(), activityAware);
|
||||
|
||||
if (isAttachedToActivity()) {
|
||||
activityAware.onAttachedToActivity(activityPluginBinding);
|
||||
}
|
||||
}
|
||||
|
||||
// For ServiceAware plugins, add the plugin to our set of ServiceAware
|
||||
// plugins, and if this engine is currently attached to a Service,
|
||||
// notify the ServiceAware plugin that it is now attached to a Service.
|
||||
if (plugin instanceof ServiceAware) {
|
||||
ServiceAware serviceAware = (ServiceAware) plugin;
|
||||
serviceAwarePlugins.put(plugin.getClass(), serviceAware);
|
||||
|
||||
if (isAttachedToService()) {
|
||||
serviceAware.onAttachedToService(servicePluginBinding);
|
||||
}
|
||||
}
|
||||
|
||||
// For BroadcastReceiverAware plugins, add the plugin to our set of BroadcastReceiverAware
|
||||
// plugins, and if this engine is currently attached to a BroadcastReceiver,
|
||||
// notify the BroadcastReceiverAware plugin that it is now attached to a BroadcastReceiver.
|
||||
if (plugin instanceof BroadcastReceiverAware) {
|
||||
BroadcastReceiverAware broadcastReceiverAware = (BroadcastReceiverAware) plugin;
|
||||
broadcastReceiverAwarePlugins.put(plugin.getClass(), broadcastReceiverAware);
|
||||
|
||||
if (isAttachedToBroadcastReceiver()) {
|
||||
broadcastReceiverAware.onAttachedToBroadcastReceiver(broadcastReceiverPluginBinding);
|
||||
}
|
||||
}
|
||||
|
||||
// For ContentProviderAware plugins, add the plugin to our set of ContentProviderAware
|
||||
// plugins, and if this engine is currently attached to a ContentProvider,
|
||||
// notify the ContentProviderAware plugin that it is now attached to a ContentProvider.
|
||||
if (plugin instanceof ContentProviderAware) {
|
||||
ContentProviderAware contentProviderAware = (ContentProviderAware) plugin;
|
||||
contentProviderAwarePlugins.put(plugin.getClass(), contentProviderAware);
|
||||
|
||||
if (isAttachedToContentProvider()) {
|
||||
contentProviderAware.onAttachedToContentProvider(contentProviderPluginBinding);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void add(@NonNull Set<FlutterPlugin> plugins) {
|
||||
for (FlutterPlugin plugin : plugins) {
|
||||
add(plugin);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean has(@NonNull Class<? extends FlutterPlugin> pluginClass) {
|
||||
return plugins.containsKey(pluginClass);
|
||||
}
|
||||
|
||||
public FlutterPlugin get(@NonNull Class<? extends FlutterPlugin> pluginClass) {
|
||||
return plugins.get(pluginClass);
|
||||
}
|
||||
|
||||
public void remove(@NonNull Class<? extends FlutterPlugin> pluginClass) {
|
||||
FlutterPlugin plugin = plugins.get(pluginClass);
|
||||
if (plugin != null) {
|
||||
// For ActivityAware plugins, notify the plugin that it is detached from
|
||||
// an Activity if an Activity is currently attached to this engine. Then
|
||||
// remove the plugin from our set of ActivityAware plugins.
|
||||
if (plugin instanceof ActivityAware) {
|
||||
if (isAttachedToActivity()) {
|
||||
ActivityAware activityAware = (ActivityAware) plugin;
|
||||
activityAware.onDetachedFromActivity();
|
||||
}
|
||||
activityAwarePlugins.remove(pluginClass);
|
||||
}
|
||||
|
||||
// For ServiceAware plugins, notify the plugin that it is detached from
|
||||
// a Service if a Service is currently attached to this engine. Then
|
||||
// remove the plugin from our set of ServiceAware plugins.
|
||||
if (plugin instanceof ServiceAware) {
|
||||
if (isAttachedToService()) {
|
||||
ServiceAware serviceAware = (ServiceAware) plugin;
|
||||
serviceAware.onDetachedFromService();
|
||||
}
|
||||
serviceAwarePlugins.remove(pluginClass);
|
||||
}
|
||||
|
||||
// For BroadcastReceiverAware plugins, notify the plugin that it is detached from
|
||||
// a BroadcastReceiver if a BroadcastReceiver is currently attached to this engine. Then
|
||||
// remove the plugin from our set of BroadcastReceiverAware plugins.
|
||||
if (plugin instanceof BroadcastReceiverAware) {
|
||||
if (isAttachedToBroadcastReceiver()) {
|
||||
BroadcastReceiverAware broadcastReceiverAware = (BroadcastReceiverAware) plugin;
|
||||
broadcastReceiverAware.onDetachedFromBroadcastReceiver();
|
||||
}
|
||||
broadcastReceiverAwarePlugins.remove(pluginClass);
|
||||
}
|
||||
|
||||
// For ContentProviderAware plugins, notify the plugin that it is detached from
|
||||
// a ContentProvider if a ContentProvider is currently attached to this engine. Then
|
||||
// remove the plugin from our set of ContentProviderAware plugins.
|
||||
if (plugin instanceof ContentProviderAware) {
|
||||
if (isAttachedToContentProvider()) {
|
||||
ContentProviderAware contentProviderAware = (ContentProviderAware) plugin;
|
||||
contentProviderAware.onDetachedFromContentProvider();
|
||||
}
|
||||
contentProviderAwarePlugins.remove(pluginClass);
|
||||
}
|
||||
|
||||
// Notify the plugin that is now detached from this engine. Then remove
|
||||
// it from our set of generic plugins.
|
||||
plugin.onDetachedFromEngine(pluginBinding);
|
||||
plugins.remove(pluginClass);
|
||||
}
|
||||
}
|
||||
|
||||
public void remove(@NonNull Set<Class<? extends FlutterPlugin>> pluginClasses) {
|
||||
for (Class<? extends FlutterPlugin> pluginClass : pluginClasses) {
|
||||
remove(pluginClass);
|
||||
}
|
||||
}
|
||||
|
||||
public void removeAll() {
|
||||
// We copy the keys to a new set so that we can mutate the set while using
|
||||
// the keys.
|
||||
remove(new HashSet<>(plugins.keySet()));
|
||||
plugins.clear();
|
||||
}
|
||||
|
||||
private void detachFromAndroidComponent() {
|
||||
if (isAttachedToActivity()) {
|
||||
detachFromActivity();
|
||||
} else if (isAttachedToService()) {
|
||||
detachFromService();
|
||||
} else if (isAttachedToBroadcastReceiver()) {
|
||||
detachFromBroadcastReceiver();
|
||||
} else if (isAttachedToContentProvider()) {
|
||||
detachFromContentProvider();
|
||||
}
|
||||
}
|
||||
|
||||
//-------- Start ActivityControlSurface -------
|
||||
private boolean isAttachedToActivity() {
|
||||
return activity != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void attachToActivity(@NonNull Activity activity, @NonNull Lifecycle lifecycle) {
|
||||
Log.d(TAG, "Attaching to an Activity.");
|
||||
// If we were already attached to an Android component, detach from it.
|
||||
detachFromAndroidComponent();
|
||||
|
||||
this.activity = activity;
|
||||
this.activityPluginBinding = new FlutterEngineActivityPluginBinding(activity);
|
||||
// TODO(mattcarroll): resolve possibility of different lifecycles between this and engine attachment
|
||||
|
||||
// Notify all ActivityAware plugins that they are now attached to a new Activity.
|
||||
for (ActivityAware activityAware : activityAwarePlugins.values()) {
|
||||
activityAware.onAttachedToActivity(activityPluginBinding);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void detachFromActivityForConfigChanges() {
|
||||
Log.d(TAG, "Detaching from an Activity for config changes.");
|
||||
if (isAttachedToActivity()) {
|
||||
for (ActivityAware activityAware : activityAwarePlugins.values()) {
|
||||
activityAware.onDetachedFromActivityForConfigChanges();
|
||||
}
|
||||
|
||||
activity = null;
|
||||
activityPluginBinding = null;
|
||||
} else {
|
||||
Log.e(TAG, "Attempted to detach plugins from an Activity when no Activity was attached.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reattachToActivityAfterConfigChange(@NonNull Activity activity) {
|
||||
Log.d(TAG, "Re-attaching to an Activity after config change.");
|
||||
if (!isAttachedToActivity()) {
|
||||
this.activity = activity;
|
||||
activityPluginBinding = new FlutterEngineActivityPluginBinding(activity);
|
||||
|
||||
for (ActivityAware activityAware : activityAwarePlugins.values()) {
|
||||
activityAware.onReattachedToActivityForConfigChanges(activityPluginBinding);
|
||||
}
|
||||
} else {
|
||||
Log.e(TAG, "Attempted to reattach plugins to an Activity after config changes, but an Activity was already attached.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void detachFromActivity() {
|
||||
Log.d(TAG, "Detaching from an Activity.");
|
||||
if (isAttachedToActivity()) {
|
||||
for (ActivityAware activityAware : activityAwarePlugins.values()) {
|
||||
activityAware.onDetachedFromActivity();
|
||||
}
|
||||
|
||||
activity = null;
|
||||
activityPluginBinding = null;
|
||||
} else {
|
||||
Log.e(TAG, "Attempted to detach plugins from an Activity when no Activity was attached.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResult) {
|
||||
Log.d(TAG, "Forwarding onRequestPermissionsResult() to plugins.");
|
||||
if (isAttachedToActivity()) {
|
||||
return activityPluginBinding.onRequestPermissionsResult(requestCode, permissions, grantResult);
|
||||
} else {
|
||||
Log.e(TAG, "Attempted to notify ActivityAware plugins of onRequestPermissionsResult, but no Activity was attached.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onActivityResult(int requestCode, int resultCode, @NonNull Intent data) {
|
||||
Log.d(TAG, "Forwarding onActivityResult() to plugins.");
|
||||
if (isAttachedToActivity()) {
|
||||
return activityPluginBinding.onActivityResult(requestCode, resultCode, data);
|
||||
} else {
|
||||
Log.e(TAG, "Attempted to notify ActivityAware plugins of onActivityResult, but no Activity was attached.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNewIntent(@NonNull Intent intent) {
|
||||
Log.d(TAG, "Forwarding onNewIntent() to plugins.");
|
||||
if (isAttachedToActivity()) {
|
||||
activityPluginBinding.onNewIntent(intent);
|
||||
} else {
|
||||
Log.e(TAG, "Attempted to notify ActivityAware plugins of onNewIntent, but no Activity was attached.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUserLeaveHint() {
|
||||
Log.d(TAG, "Forwarding onUserLeaveHint() to plugins.");
|
||||
if (isAttachedToActivity()) {
|
||||
activityPluginBinding.onUserLeaveHint();
|
||||
} else {
|
||||
Log.e(TAG, "Attempted to notify ActivityAware plugins of onUserLeaveHint, but no Activity was attached.");
|
||||
}
|
||||
}
|
||||
//------- End ActivityControlSurface -----
|
||||
|
||||
//----- Start ServiceControlSurface ----
|
||||
private boolean isAttachedToService() {
|
||||
return service != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void attachToService(@NonNull Service service, @NonNull Lifecycle lifecycle, boolean isForeground) {
|
||||
// If we were already attached to an Android component, detach from it.
|
||||
detachFromAndroidComponent();
|
||||
|
||||
this.service = service;
|
||||
this.servicePluginBinding = new FlutterEngineServicePluginBinding(service);
|
||||
// TODO(mattcarroll): resolve possibility of different lifecycles between this and engine attachment
|
||||
|
||||
// Notify all ServiceAware plugins that they are now attached to a new Service.
|
||||
for (ServiceAware serviceAware : serviceAwarePlugins.values()) {
|
||||
serviceAware.onAttachedToService(servicePluginBinding);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void detachFromService() {
|
||||
if (isAttachedToService()) {
|
||||
// Notify all ServiceAware plugins that they are no longer attached to a Service.
|
||||
for (ServiceAware serviceAware : serviceAwarePlugins.values()) {
|
||||
serviceAware.onDetachedFromService();
|
||||
}
|
||||
} else {
|
||||
Log.e(TAG, "Attempted to detach plugins from a Service when no Service was attached.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMoveToForeground() {
|
||||
if (isAttachedToService()) {
|
||||
servicePluginBinding.onMoveToForeground();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMoveToBackground() {
|
||||
if (isAttachedToService()) {
|
||||
servicePluginBinding.onMoveToBackground();
|
||||
}
|
||||
}
|
||||
//----- End ServiceControlSurface ---
|
||||
|
||||
//----- Start BroadcastReceiverControlSurface ---
|
||||
private boolean isAttachedToBroadcastReceiver() {
|
||||
return broadcastReceiver != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void attachToBroadcastReceiver(@NonNull BroadcastReceiver broadcastReceiver, @NonNull Lifecycle lifecycle) {
|
||||
// If we were already attached to an Android component, detach from it.
|
||||
detachFromAndroidComponent();
|
||||
|
||||
this.broadcastReceiver = broadcastReceiver;
|
||||
this.broadcastReceiverPluginBinding = new FlutterEngineBroadcastReceiverPluginBinding(broadcastReceiver);
|
||||
// TODO(mattcarroll): resolve possibility of different lifecycles between this and engine attachment
|
||||
|
||||
// Notify all BroadcastReceiverAware plugins that they are now attached to a new BroadcastReceiver.
|
||||
for (BroadcastReceiverAware broadcastReceiverAware : broadcastReceiverAwarePlugins.values()) {
|
||||
broadcastReceiverAware.onAttachedToBroadcastReceiver(broadcastReceiverPluginBinding);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void detachFromBroadcastReceiver() {
|
||||
if (isAttachedToBroadcastReceiver()) {
|
||||
// Notify all BroadcastReceiverAware plugins that they are no longer attached to a BroadcastReceiver.
|
||||
for (BroadcastReceiverAware broadcastReceiverAware : broadcastReceiverAwarePlugins.values()) {
|
||||
broadcastReceiverAware.onDetachedFromBroadcastReceiver();
|
||||
}
|
||||
} else {
|
||||
Log.e(TAG, "Attempted to detach plugins from a BroadcastReceiver when no BroadcastReceiver was attached.");
|
||||
}
|
||||
}
|
||||
//----- End BroadcastReceiverControlSurface ----
|
||||
|
||||
//----- Start ContentProviderControlSurface ----
|
||||
private boolean isAttachedToContentProvider() {
|
||||
return contentProvider != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void attachToContentProvider(@NonNull ContentProvider contentProvider, @NonNull Lifecycle lifecycle) {
|
||||
// If we were already attached to an Android component, detach from it.
|
||||
detachFromAndroidComponent();
|
||||
|
||||
this.contentProvider = contentProvider;
|
||||
this.contentProviderPluginBinding = new FlutterEngineContentProviderPluginBinding(contentProvider);
|
||||
// TODO(mattcarroll): resolve possibility of different lifecycles between this and engine attachment
|
||||
|
||||
// Notify all ContentProviderAware plugins that they are now attached to a new ContentProvider.
|
||||
for (ContentProviderAware contentProviderAware : contentProviderAwarePlugins.values()) {
|
||||
contentProviderAware.onAttachedToContentProvider(contentProviderPluginBinding);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void detachFromContentProvider() {
|
||||
if (isAttachedToContentProvider()) {
|
||||
// Notify all ContentProviderAware plugins that they are no longer attached to a ContentProvider.
|
||||
for (ContentProviderAware contentProviderAware : contentProviderAwarePlugins.values()) {
|
||||
contentProviderAware.onDetachedFromContentProvider();
|
||||
}
|
||||
} else {
|
||||
Log.e(TAG, "Attempted to detach plugins from a ContentProvider when no ContentProvider was attached.");
|
||||
}
|
||||
}
|
||||
//----- End ContentProviderControlSurface -----
|
||||
|
||||
private static class FlutterEngineActivityPluginBinding implements ActivityPluginBinding {
|
||||
private final Activity activity;
|
||||
private final Set<io.flutter.plugin.common.PluginRegistry.RequestPermissionsResultListener> onRequestPermissionsResultListeners = new HashSet<>();
|
||||
private final Set<io.flutter.plugin.common.PluginRegistry.ActivityResultListener> onActivityResultListeners = new HashSet<>();
|
||||
private final Set<io.flutter.plugin.common.PluginRegistry.NewIntentListener> onNewIntentListeners = new HashSet<>();
|
||||
private final Set<io.flutter.plugin.common.PluginRegistry.UserLeaveHintListener> onUserLeaveHintListeners = new HashSet<>();
|
||||
|
||||
public FlutterEngineActivityPluginBinding(@NonNull Activity activity) {
|
||||
this.activity = activity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link Activity} that is currently attached to the {@link FlutterEngine} that
|
||||
* owns this {@code ActivityPluginBinding}.
|
||||
*/
|
||||
@NonNull
|
||||
public Activity getActivity() {
|
||||
return activity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a listener that is invoked whenever the associated {@link Activity}'s
|
||||
* {@code onRequestPermissionsResult(...)} method is invoked.
|
||||
*/
|
||||
public void addRequestPermissionsResultListener(@NonNull io.flutter.plugin.common.PluginRegistry.RequestPermissionsResultListener listener) {
|
||||
onRequestPermissionsResultListeners.add(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a listener that was added in {@link #addRequestPermissionsResultListener(io.flutter.plugin.common.PluginRegistry.RequestPermissionsResultListener)}.
|
||||
*/
|
||||
public void removeRequestPermissionsResultListener(@NonNull io.flutter.plugin.common.PluginRegistry.RequestPermissionsResultListener listener) {
|
||||
onRequestPermissionsResultListeners.remove(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked by the {@link FlutterEngine} that owns this {@code ActivityPluginBinding} when its
|
||||
* associated {@link Activity} has its {@code onRequestPermissionsResult(...)} method invoked.
|
||||
*/
|
||||
boolean onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResult) {
|
||||
boolean didConsumeResult = false;
|
||||
for (io.flutter.plugin.common.PluginRegistry.RequestPermissionsResultListener listener : onRequestPermissionsResultListeners) {
|
||||
didConsumeResult = listener.onRequestPermissionsResult(requestCode, permissions, grantResult) || didConsumeResult;
|
||||
}
|
||||
return didConsumeResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a listener that is invoked whenever the associated {@link Activity}'s
|
||||
* {@code onActivityResult(...)} method is invoked.
|
||||
*/
|
||||
public void addActivityResultListener(@NonNull io.flutter.plugin.common.PluginRegistry.ActivityResultListener listener) {
|
||||
onActivityResultListeners.add(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a listener that was added in {@link #addActivityResultListener(io.flutter.plugin.common.PluginRegistry.ActivityResultListener)}.
|
||||
*/
|
||||
public void removeActivityResultListener(@NonNull io.flutter.plugin.common.PluginRegistry.ActivityResultListener listener) {
|
||||
onActivityResultListeners.remove(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked by the {@link FlutterEngine} that owns this {@code ActivityPluginBinding} when its
|
||||
* associated {@link Activity} has its {@code onActivityResult(...)} method invoked.
|
||||
*/
|
||||
boolean onActivityResult(int requestCode, int resultCode, @NonNull Intent data) {
|
||||
boolean didConsumeResult = false;
|
||||
for (io.flutter.plugin.common.PluginRegistry.ActivityResultListener listener : onActivityResultListeners) {
|
||||
didConsumeResult = listener.onActivityResult(requestCode, resultCode, data) || didConsumeResult;
|
||||
}
|
||||
return didConsumeResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a listener that is invoked whenever the associated {@link Activity}'s
|
||||
* {@code onNewIntent(...)} method is invoked.
|
||||
*/
|
||||
public void addOnNewIntentListener(@NonNull io.flutter.plugin.common.PluginRegistry.NewIntentListener listener) {
|
||||
onNewIntentListeners.add(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a listener that was added in {@link #addOnNewIntentListener(io.flutter.plugin.common.PluginRegistry.NewIntentListener)}.
|
||||
*/
|
||||
public void removeOnNewIntentListener(@NonNull io.flutter.plugin.common.PluginRegistry.NewIntentListener listener) {
|
||||
onNewIntentListeners.remove(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked by the {@link FlutterEngine} that owns this {@code ActivityPluginBinding} when its
|
||||
* associated {@link Activity} has its {@code onNewIntent(...)} method invoked.
|
||||
*/
|
||||
void onNewIntent(@Nullable Intent intent) {
|
||||
for (io.flutter.plugin.common.PluginRegistry.NewIntentListener listener : onNewIntentListeners) {
|
||||
listener.onNewIntent(intent);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a listener that is invoked whenever the associated {@link Activity}'s
|
||||
* {@code onUserLeaveHint()} method is invoked.
|
||||
*/
|
||||
public void addOnUserLeaveHintListener(@NonNull io.flutter.plugin.common.PluginRegistry.UserLeaveHintListener listener) {
|
||||
onUserLeaveHintListeners.add(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a listener that was added in {@link #addOnUserLeaveHintListener(io.flutter.plugin.common.PluginRegistry.UserLeaveHintListener)}.
|
||||
*/
|
||||
public void removeOnUserLeaveHintListener(@NonNull io.flutter.plugin.common.PluginRegistry.UserLeaveHintListener listener) {
|
||||
onUserLeaveHintListeners.remove(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked by the {@link FlutterEngine} that owns this {@code ActivityPluginBinding} when its
|
||||
* associated {@link Activity} has its {@code onUserLeaveHint()} method invoked.
|
||||
*/
|
||||
void onUserLeaveHint() {
|
||||
for (io.flutter.plugin.common.PluginRegistry.UserLeaveHintListener listener : onUserLeaveHintListeners) {
|
||||
listener.onUserLeaveHint();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class FlutterEngineServicePluginBinding implements ServicePluginBinding {
|
||||
private final Service service;
|
||||
private final Set<ServiceAware.OnModeChangeListener> onModeChangeListeners = new HashSet<>();
|
||||
|
||||
FlutterEngineServicePluginBinding(@NonNull Service service) {
|
||||
this.service = service;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Service getService() {
|
||||
return service;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addOnModeChangeListener(@NonNull ServiceAware.OnModeChangeListener listener) {
|
||||
onModeChangeListeners.add(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeOnModeChangeListener(@NonNull ServiceAware.OnModeChangeListener listener) {
|
||||
onModeChangeListeners.remove(listener);
|
||||
}
|
||||
|
||||
void onMoveToForeground() {
|
||||
for (ServiceAware.OnModeChangeListener listener : onModeChangeListeners) {
|
||||
listener.onMoveToForeground();
|
||||
}
|
||||
}
|
||||
|
||||
void onMoveToBackground() {
|
||||
for (ServiceAware.OnModeChangeListener listener : onModeChangeListeners) {
|
||||
listener.onMoveToBackground();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class FlutterEngineBroadcastReceiverPluginBinding implements BroadcastReceiverPluginBinding {
|
||||
private final BroadcastReceiver broadcastReceiver;
|
||||
|
||||
FlutterEngineBroadcastReceiverPluginBinding(@NonNull BroadcastReceiver broadcastReceiver) {
|
||||
this.broadcastReceiver = broadcastReceiver;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public BroadcastReceiver getBroadcastReceiver() {
|
||||
return broadcastReceiver;
|
||||
}
|
||||
}
|
||||
|
||||
private static class FlutterEngineContentProviderPluginBinding implements ContentProviderPluginBinding {
|
||||
private final ContentProvider contentProvider;
|
||||
|
||||
FlutterEngineContentProviderPluginBinding(@NonNull ContentProvider contentProvider) {
|
||||
this.contentProvider = contentProvider;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ContentProvider getContentProvider() {
|
||||
return contentProvider;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,24 @@
|
||||
// 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.broadcastreceiver;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
/**
|
||||
* A {@link FlutterPlugin} that wants to know when it is running within a {@link BroadcastReceiver}.
|
||||
*/
|
||||
public interface BroadcastReceiverAware {
|
||||
/**
|
||||
* Callback triggered when a {@code BroadcastReceiverAware} {@link FlutterPlugin} is associated
|
||||
* with a {@link BroadcastReceiver}.
|
||||
*/
|
||||
void onAttachedToBroadcastReceiver(@NonNull BroadcastReceiverPluginBinding binding);
|
||||
|
||||
/**
|
||||
* Callback triggered when a {@code BroadcastReceiverAware} {@link FlutterPlugin} is detached from
|
||||
* a {@link BroadcastReceiver}.
|
||||
*/
|
||||
void onDetachedFromBroadcastReceiver();
|
||||
}
|
||||
@ -0,0 +1,38 @@
|
||||
// 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.broadcastreceiver;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.arch.lifecycle.Lifecycle;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
/**
|
||||
* Control surface through which a {@link BroadcastReceiver} attaches to a {@link FlutterEngine}.
|
||||
* <p>
|
||||
* A {@link BroadcastReceiver} that contains a {@link FlutterEngine} should coordinate itself with the
|
||||
* {@link FlutterEngine}'s {@code BroadcastReceiverControlSurface}.
|
||||
*/
|
||||
public interface BroadcastReceiverControlSurface {
|
||||
/**
|
||||
* Call this method from the {@link BroadcastReceiver} that is running the {@link FlutterEngine}
|
||||
* that is associated with this {@code BroadcastReceiverControlSurface}.
|
||||
* <p>
|
||||
* Once a {@link BroadcastReceiver} is created, and its associated {@link FlutterEngine} is
|
||||
* executing Dart code, the {@link BroadcastReceiver} should invoke this method. At that point the
|
||||
* {@link FlutterEngine} is considered "attached" to the {@link BroadcastReceiver} and all
|
||||
* {@link BroadcastReceiverAware} plugins are given access to the {@link BroadcastReceiver}.
|
||||
*/
|
||||
void attachToBroadcastReceiver(@NonNull BroadcastReceiver broadcastReceiver, @NonNull Lifecycle lifecycle);
|
||||
|
||||
/**
|
||||
* Call this method from the {@link BroadcastReceiver} that is attached to this
|
||||
* {@code BroadcastReceiverControlSurfaces}'s {@link FlutterEngine} when the {@link BroadcastReceiver}
|
||||
* is about to be destroyed.
|
||||
* <p>
|
||||
* This method gives each {@link BroadcastReceiverAware} plugin an opportunity to clean up its references
|
||||
* before the {@link BroadcastReceiver is destroyed}.
|
||||
*/
|
||||
void detachFromBroadcastReceiver();
|
||||
}
|
||||
@ -0,0 +1,22 @@
|
||||
// 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.broadcastreceiver;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
/**
|
||||
* Binding that gives {@link BroadcastReceiverAware} plugins access to an associated
|
||||
* {@link BroadcastReceiver}.
|
||||
*/
|
||||
public interface BroadcastReceiverPluginBinding {
|
||||
|
||||
/**
|
||||
* Returns the {@link BroadcastReceiver} that is currently attached to the {@link FlutterEngine} that
|
||||
* owns this {@code BroadcastReceiverAwarePluginBinding}.
|
||||
*/
|
||||
@NonNull
|
||||
BroadcastReceiver getBroadcastReceiver();
|
||||
}
|
||||
@ -0,0 +1,24 @@
|
||||
// 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.contentprovider;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
/**
|
||||
* A {@link FlutterPlugin} that wants to know when it is running within a {@link ContentProvider}.
|
||||
*/
|
||||
public interface ContentProviderAware {
|
||||
/**
|
||||
* Callback triggered when a {@code ContentProviderAware} {@link FlutterPlugin} is associated with
|
||||
* a {@link ContentProvider}.
|
||||
*/
|
||||
void onAttachedToContentProvider(@NonNull ContentProviderPluginBinding binding);
|
||||
|
||||
/**
|
||||
* Callback triggered when a {@code ContentProviderAware} {@link FlutterPlugin} is detached from
|
||||
* a {@link ContentProvider}.
|
||||
*/
|
||||
void onDetachedFromContentProvider();
|
||||
}
|
||||
@ -0,0 +1,38 @@
|
||||
// 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.contentprovider;
|
||||
|
||||
import android.content.ContentProvider;
|
||||
import android.arch.lifecycle.Lifecycle;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
/**
|
||||
* Control surface through which a {@link ContentProvider} attaches to a {@link FlutterEngine}.
|
||||
* <p>
|
||||
* A {@link ContentProvider} that contains a {@link FlutterEngine} should coordinate itself with the
|
||||
* {@link FlutterEngine}'s {@code ContentProviderControlSurface}.
|
||||
*/
|
||||
public interface ContentProviderControlSurface {
|
||||
/**
|
||||
* Call this method from the {@link ContentProvider} that is running the {@link FlutterEngine}
|
||||
* that is associated with this {@code ContentProviderControlSurface}.
|
||||
* <p>
|
||||
* Once a {@link ContentProvider} is created, and its associated {@link FlutterEngine} is
|
||||
* executing Dart code, the {@link ContentProvider} should invoke this method. At that point the
|
||||
* {@link FlutterEngine} is considered "attached" to the {@link ContentProvider} and all
|
||||
* {@link ContentProviderAware} plugins are given access to the {@link ContentProvider}.
|
||||
*/
|
||||
void attachToContentProvider(@NonNull ContentProvider contentProvider, @NonNull Lifecycle lifecycle);
|
||||
|
||||
/**
|
||||
* Call this method from the {@link ContentProvider} that is attached to this
|
||||
* {@code ContentProviderControlSurfaces}'s {@link FlutterEngine} when the {@link ContentProvider}
|
||||
* is about to be destroyed.
|
||||
* <p>
|
||||
* This method gives each {@link ContentProviderAware} plugin an opportunity to clean up its references
|
||||
* before the {@link ContentProvider is destroyed}.
|
||||
*/
|
||||
void detachFromContentProvider();
|
||||
}
|
||||
@ -0,0 +1,22 @@
|
||||
// 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.contentprovider;
|
||||
|
||||
import android.content.ContentProvider;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
/**
|
||||
* Binding that gives {@link ContentProviderAware} plugins access to an associated
|
||||
* {@link ContentProvider}.
|
||||
*/
|
||||
public interface ContentProviderPluginBinding {
|
||||
|
||||
/**
|
||||
* Returns the {@link ContentProvider} that is currently attached to the {@link FlutterEngine} that
|
||||
* owns this {@code ContentProviderAwarePluginBinding}.
|
||||
*/
|
||||
@NonNull
|
||||
ContentProvider getContentProvider();
|
||||
}
|
||||
@ -0,0 +1,38 @@
|
||||
// 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.service;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
/**
|
||||
* A {@link FlutterPlugin} that wants to know when it is running within a {@link Service}.
|
||||
*/
|
||||
public interface ServiceAware {
|
||||
/**
|
||||
* Callback triggered when a {@code ServiceAware} {@link FlutterPlugin} is associated with a
|
||||
* {@link Service}.
|
||||
*/
|
||||
void onAttachedToService(@NonNull ServicePluginBinding binding);
|
||||
|
||||
/**
|
||||
* Callback triggered when a {@code ServiceAware} {@link FlutterPlugin} is detached from a
|
||||
* {@link Service}.
|
||||
*/
|
||||
void onDetachedFromService();
|
||||
|
||||
interface OnModeChangeListener {
|
||||
/**
|
||||
* Callback triggered when the associated {@link Service} goes from background execution to
|
||||
* foreground execution.
|
||||
*/
|
||||
void onMoveToForeground();
|
||||
|
||||
/**
|
||||
* Callback triggered when the associated {@link Service} goes from foreground execution to
|
||||
* background execution.
|
||||
*/
|
||||
void onMoveToBackground();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,52 @@
|
||||
// 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.service;
|
||||
|
||||
import android.app.Service;
|
||||
import android.arch.lifecycle.Lifecycle;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
/**
|
||||
* Control surface through which a {@link Service} attaches to a {@link FlutterEngine}.
|
||||
* <p>
|
||||
* A {@link Service} that contains a {@link FlutterEngine} should coordinate itself with the
|
||||
* {@link FlutterEngine}'s {@code ServiceControlSurface}.
|
||||
*/
|
||||
public interface ServiceControlSurface {
|
||||
/**
|
||||
* Call this method from the {@link Service} that is running the {@link FlutterEngine} that is
|
||||
* associated with this {@code ServiceControlSurface}.
|
||||
* <p>
|
||||
* Once a {@link Service} is created, and its associated {@link FlutterEngine} is
|
||||
* executing Dart code, the {@link Service} should invoke this method. At that point the
|
||||
* {@link FlutterEngine} is considered "attached" to the {@link Service} and all
|
||||
* {@link ServiceAware} plugins are given access to the {@link Service}.
|
||||
* <p>
|
||||
* {@code isForeground} should be true if the given {@link Service} is running in the foreground,
|
||||
* false otherwise.
|
||||
*/
|
||||
void attachToService(@NonNull Service service, @NonNull Lifecycle lifecycle, boolean isForeground);
|
||||
|
||||
/**
|
||||
* Call this method from the {@link Service} that is attached to this {@code ServiceControlSurfaces}'s
|
||||
* {@link FlutterEngine} when the {@link Service} is about to be destroyed.
|
||||
* <p>
|
||||
* This method gives each {@link ServiceAware} plugin an opportunity to clean up its references
|
||||
* before the {@link Service is destroyed}.
|
||||
*/
|
||||
void detachFromService();
|
||||
|
||||
/**
|
||||
* Call this method from the {@link Service} that is attached to this {@code ServiceControlSurface}'s
|
||||
* {@link FlutterEngine} when the {@link Service} goes from background to foreground.
|
||||
*/
|
||||
void onMoveToForeground();
|
||||
|
||||
/**
|
||||
* Call this method from the {@link Service} that is attached to this {@code ServiceControlSurface}'s
|
||||
* {@link FlutterEngine} when the {@link Service} goes from foreground to background.
|
||||
*/
|
||||
void onMoveToBackground();
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
// 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.service;
|
||||
|
||||
import android.app.Service;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
/**
|
||||
* Binding that gives {@link ServiceAware} plugins access to an associated {@link Service}.
|
||||
*/
|
||||
public interface ServicePluginBinding {
|
||||
|
||||
/**
|
||||
* Returns the {@link Service} that is currently attached to the {@link FlutterEngine} that
|
||||
* owns this {@code ServicePluginBinding}.
|
||||
*/
|
||||
@NonNull
|
||||
Service getService();
|
||||
|
||||
/**
|
||||
* Adds the given {@code listener} to be notified when the associated {@link Service} goes
|
||||
* from background to foreground, or foreground to background.
|
||||
*/
|
||||
void addOnModeChangeListener(@NonNull ServiceAware.OnModeChangeListener listener);
|
||||
|
||||
/**
|
||||
* Removes the given {@code listener}, which was previously added with
|
||||
* {@link #addOnModeChangeListener(OnModeChangeListener)}.
|
||||
*/
|
||||
void removeOnModeChangeListener(@NonNull ServiceAware.OnModeChangeListener listener);
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user