Flutter Engine
The Flutter Engine
ShimPluginRegistry.java
Go to the documentation of this file.
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
5package io.flutter.embedding.engine.plugins.shim;
6
7import androidx.annotation.NonNull;
8import io.flutter.Log;
9import io.flutter.embedding.engine.FlutterEngine;
10import io.flutter.embedding.engine.plugins.FlutterPlugin;
11import io.flutter.embedding.engine.plugins.activity.ActivityAware;
12import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
13import io.flutter.plugin.common.PluginRegistry;
14import java.util.HashMap;
15import java.util.HashSet;
16import java.util.Map;
17import java.util.Set;
18
19/**
20 * A {@link PluginRegistry} that is shimmed to let old plugins use the new Android embedding and
21 * plugin API behind the scenes.
22 *
23 * <p>The following is an example usage of {@code ShimPluginRegistry} within a {@code
24 * FlutterActivity}:
25 *
26 * <pre>
27 * // Create the FlutterEngine that will back the Flutter UI.
28 * FlutterEngineGroup group = new FlutterEngineGroup(context);
29 * FlutterEngine flutterEngine = group.createAndRunDefaultEngine(context);
30 *
31 * // Create a ShimPluginRegistry and wrap the FlutterEngine with the shim.
32 * ShimPluginRegistry shimPluginRegistry = new ShimPluginRegistry(flutterEngine, platformViewsController);
33 *
34 * // Use the GeneratedPluginRegistrant to add every plugin that's in the pubspec.
35 * GeneratedPluginRegistrant.registerWith(shimPluginRegistry);
36 * </pre>
37 */
38public class ShimPluginRegistry implements PluginRegistry {
39 private static final String TAG = "ShimPluginRegistry";
40
41 private final FlutterEngine flutterEngine;
42 private final Map<String, Object> pluginMap = new HashMap<>();
43 private final ShimRegistrarAggregate shimRegistrarAggregate;
44
45 public ShimPluginRegistry(@NonNull FlutterEngine flutterEngine) {
46 this.flutterEngine = flutterEngine;
47 this.shimRegistrarAggregate = new ShimRegistrarAggregate();
48 this.flutterEngine.getPlugins().add(shimRegistrarAggregate);
49 }
50
51 @Override
52 @NonNull
53 public Registrar registrarFor(@NonNull String pluginKey) {
54 Log.v(TAG, "Creating plugin Registrar for '" + pluginKey + "'");
55 if (pluginMap.containsKey(pluginKey)) {
56 throw new IllegalStateException("Plugin key " + pluginKey + " is already in use");
57 }
58 pluginMap.put(pluginKey, null);
59 ShimRegistrar registrar = new ShimRegistrar(pluginKey, pluginMap);
60 shimRegistrarAggregate.addPlugin(registrar);
61 return registrar;
62 }
63
64 @Override
65 public boolean hasPlugin(@NonNull String pluginKey) {
66 return pluginMap.containsKey(pluginKey);
67 }
68
69 @Override
70 @SuppressWarnings("unchecked")
71 public <T> T valuePublishedByPlugin(@NonNull String pluginKey) {
72 return (T) pluginMap.get(pluginKey);
73 }
74
75 /**
76 * Aggregates all {@link ShimRegistrar}s within one single {@link FlutterPlugin}.
77 *
78 * <p>The reason we need this aggregate is because the new embedding uniquely identifies plugins
79 * by their plugin class, but the plugin shim system represents every plugin with a {@link
80 * ShimRegistrar}. Therefore, every plugin we would register after the first plugin, would
81 * overwrite the previous plugin, because they're all {@link ShimRegistrar} instances.
82 *
83 * <p>{@code ShimRegistrarAggregate} multiplexes {@link FlutterPlugin} and {@link ActivityAware}
84 * calls so that we can register just one {@code ShimRegistrarAggregate} with a {@link
85 * FlutterEngine}, while forwarding the relevant plugin resources to any number of {@link
86 * ShimRegistrar}s within this {@code ShimRegistrarAggregate}.
87 */
88 private static class ShimRegistrarAggregate implements FlutterPlugin, ActivityAware {
89 private final Set<ShimRegistrar> shimRegistrars = new HashSet<>();
90 private FlutterPluginBinding flutterPluginBinding;
91 private ActivityPluginBinding activityPluginBinding;
92
93 public void addPlugin(@NonNull ShimRegistrar shimRegistrar) {
94 shimRegistrars.add(shimRegistrar);
95
96 if (flutterPluginBinding != null) {
97 shimRegistrar.onAttachedToEngine(flutterPluginBinding);
98 }
99 if (activityPluginBinding != null) {
100 shimRegistrar.onAttachedToActivity(activityPluginBinding);
101 }
102 }
103
104 @Override
105 public void onAttachedToEngine(@NonNull FlutterPluginBinding binding) {
106 flutterPluginBinding = binding;
107 for (ShimRegistrar shimRegistrar : shimRegistrars) {
108 shimRegistrar.onAttachedToEngine(binding);
109 }
110 }
111
112 @Override
113 public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
114 for (ShimRegistrar shimRegistrar : shimRegistrars) {
115 shimRegistrar.onDetachedFromEngine(binding);
116 }
117 flutterPluginBinding = null;
118 activityPluginBinding = null;
119 }
120
121 @Override
122 public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) {
123 activityPluginBinding = binding;
124 for (ShimRegistrar shimRegistrar : shimRegistrars) {
125 shimRegistrar.onAttachedToActivity(binding);
126 }
127 }
128
129 @Override
130 public void onDetachedFromActivityForConfigChanges() {
131 for (ShimRegistrar shimRegistrar : shimRegistrars) {
132 shimRegistrar.onDetachedFromActivity();
133 }
134 activityPluginBinding = null;
135 }
136
137 @Override
138 public void onReattachedToActivityForConfigChanges(@NonNull ActivityPluginBinding binding) {
139 activityPluginBinding = binding;
140 for (ShimRegistrar shimRegistrar : shimRegistrars) {
141 shimRegistrar.onReattachedToActivityForConfigChanges(binding);
142 }
143 }
144
145 @Override
146 public void onDetachedFromActivity() {
147 for (ShimRegistrar shimRegistrar : shimRegistrars) {
148 shimRegistrar.onDetachedFromActivity();
149 }
150 activityPluginBinding = null;
151 }
152 }
153}
static void v(@NonNull String tag, @NonNull String message)
Definition: Log.java:40
public< T > T valuePublishedByPlugin(@NonNull String pluginKey)
#define T
Definition: precompiler.cc:65
#define TAG()