1 // Copyright 2013 The Flutter Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 package io.flutter.embedding.engine.plugins; 6 7 import android.arch.lifecycle.Lifecycle; 8 import android.arch.lifecycle.LifecycleOwner; 9 import android.content.Context; 10 import android.support.annotation.NonNull; 11 12 import io.flutter.embedding.engine.FlutterEngine; 13 14 /** 15 * Interface to be implemented by all Flutter plugins. 16 * <p> 17 * A Flutter plugin allows Flutter developers to interact with a host platform, e.g., Android and 18 * iOS, via Dart code. It includes platform code, as well as Dart code. A plugin author is 19 * responsible for setting up an appropriate {@link io.flutter.plugin.common.MethodChannel} 20 * to communicate between platform code and Dart code. 21 * <p> 22 * A Flutter plugin has a lifecycle. First, a developer must add a {@code FlutterPlugin} to an 23 * instance of {@link FlutterEngine}. To do this, obtain a {@link PluginRegistry} with 24 * {@link FlutterEngine#getPlugins()}, then call {@link PluginRegistry#add(FlutterPlugin)}, 25 * passing the instance of the Flutter plugin. During the call to 26 * {@link PluginRegistry#add(FlutterPlugin)}, the {@link FlutterEngine} will invoke 27 * {@link #onAttachedToEngine(FlutterPluginBinding)} on the given {@code FlutterPlugin}. If the 28 * {@code FlutterPlugin} is removed from the {@link FlutterEngine} via 29 * {@link PluginRegistry#remove(Class)}, or if the {@link FlutterEngine} is destroyed, the 30 * {@link FlutterEngine} will invoke {@link FlutterPlugin#onDetachedFromEngine(FlutterPluginBinding)} 31 * on the given {@code FlutterPlugin}. 32 * <p> 33 * Once a {@code FlutterPlugin} is attached to a {@link FlutterEngine}, the plugin's code is 34 * permitted to access and invoke methods on resources within the {@link FlutterPluginBinding} that 35 * the {@link FlutterEngine} gave to the {@code FlutterPlugin} in 36 * {@link #onAttachedToEngine(FlutterPluginBinding)}. This includes, for example, the application 37 * {@link Context} for the running app. 38 * <p> 39 * The {@link FlutterPluginBinding} provided in {@link #onAttachedToEngine(FlutterPluginBinding)} 40 * is no longer valid after the execution of {@link #onDetachedFromEngine(FlutterPluginBinding)}. 41 * Do not access any properties of the {@link FlutterPluginBinding} after the completion of 42 * {@link #onDetachedFromEngine(FlutterPluginBinding)}. 43 * <p> 44 * The Android side of a Flutter plugin can be thought of as applying itself to a {@link FlutterEngine}. 45 * Use {@link FlutterPluginBinding#getFlutterEngine()} to retrieve the {@link FlutterEngine} that 46 * the {@code FlutterPlugin} is attached to. To register a 47 * {@link io.flutter.plugin.common.MethodChannel}, obtain the {@link FlutterEngine}'s 48 * {@link io.flutter.embedding.engine.dart.DartExecutor} with {@link FlutterEngine#getDartExecutor()}, 49 * then pass the {@link io.flutter.embedding.engine.dart.DartExecutor} to the 50 * {@link io.flutter.plugin.common.MethodChannel} as a {@link io.flutter.plugin.common.BinaryMessenger}. 51 * <p> 52 * An Android Flutter plugin may require access to app resources or other artifacts that can only 53 * be retrieved through a {@link Context}. Developers can access the application context via 54 * {@link FlutterPluginBinding#getApplicationContext()}. 55 * <p> 56 * TODO(mattcarroll): explain ActivityAware when it's added to the new plugin API surface. 57 */ 58 public interface FlutterPlugin { 59 60 /** 61 * This {@code FlutterPlugin} has been associated with a {@link FlutterEngine} instance. 62 * <p> 63 * Relevant resources that this {@code FlutterPlugin} may need are provided via the {@code binding}. 64 * The {@code binding} may be cached and referenced until 65 * {@link #onDetachedFromEngine(FlutterPluginBinding)} is invoked and returns. 66 */ onAttachedToEngine(@onNull FlutterPluginBinding binding)67 void onAttachedToEngine(@NonNull FlutterPluginBinding binding); 68 69 /** 70 * This {@code FlutterPlugin} has been removed from a {@link FlutterEngine} instance. 71 * <p> 72 * The {@code binding} passed to this method is the same instance that was passed in 73 * {@link #onAttachedToEngine(FlutterPluginBinding)}. It is provided again in this method as a 74 * convenience. The {@code binding} may be referenced during the execution of this method, but 75 * it must not be cached or referenced after this method returns. 76 * <p> 77 * {@code FlutterPlugin}s should release all resources in this method. 78 */ onDetachedFromEngine(@onNull FlutterPluginBinding binding)79 void onDetachedFromEngine(@NonNull FlutterPluginBinding binding); 80 81 /** 82 * Resources made available to all plugins registered with a given {@link FlutterEngine}. 83 * <p> 84 * The {@code FlutterPluginBinding}'s {@code flutterEngine} refers to the {@link FlutterEngine} 85 * that the associated {@code FlutterPlugin} is intended to apply to. For example, if a 86 * {@code FlutterPlugin} needs to setup a communication channel with its associated Flutter app, 87 * that can be done by wrapping a {@code MethodChannel} around 88 * {@link FlutterEngine#getDartExecutor()}. 89 * <p> 90 * A {@link FlutterEngine} may move from foreground to background, from an {@code Activity} to 91 * a {@code Service}. {@code FlutterPluginBinding}'s {@code lifecycle} generalizes those 92 * lifecycles so that a {@code FlutterPlugin} can react to lifecycle events without being 93 * concerned about which Android Component is currently holding the {@link FlutterEngine}. 94 * TODO(mattcarroll): add info about ActivityAware and ServiceAware for plugins that care. 95 */ 96 class FlutterPluginBinding implements LifecycleOwner { 97 private final Context applicationContext; 98 private final FlutterEngine flutterEngine; 99 private final Lifecycle lifecycle; 100 FlutterPluginBinding( @onNull Context applicationContext, @NonNull FlutterEngine flutterEngine, @NonNull Lifecycle lifecycle )101 public FlutterPluginBinding( 102 @NonNull Context applicationContext, 103 @NonNull FlutterEngine flutterEngine, 104 @NonNull Lifecycle lifecycle 105 ) { 106 this.applicationContext = applicationContext; 107 this.flutterEngine = flutterEngine; 108 this.lifecycle = lifecycle; 109 } 110 111 @NonNull getApplicationContext()112 public Context getApplicationContext() { 113 return applicationContext; 114 } 115 116 @NonNull getFlutterEngine()117 public FlutterEngine getFlutterEngine() { 118 return flutterEngine; 119 } 120 121 @Override 122 @NonNull getLifecycle()123 public Lifecycle getLifecycle() { 124 return lifecycle; 125 } 126 } 127 } 128