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