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.app.Activity; 8 import android.content.Context; 9 import android.support.annotation.NonNull; 10 11 import java.util.HashSet; 12 import java.util.Map; 13 import java.util.Set; 14 15 import io.flutter.Log; 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.BinaryMessenger; 20 import io.flutter.plugin.common.PluginRegistry; 21 import io.flutter.plugin.platform.PlatformViewRegistry; 22 import io.flutter.view.FlutterMain; 23 import io.flutter.view.FlutterView; 24 import io.flutter.view.TextureRegistry; 25 26 /** 27 * A {@link PluginRegistry.Registrar} that is shimmed to use the new Android embedding and plugin 28 * API behind the scenes. 29 * <p> 30 * Instances of {@code ShimRegistrar}s are vended internally by a {@link ShimPluginRegistry}. 31 */ 32 class ShimRegistrar implements PluginRegistry.Registrar, FlutterPlugin, ActivityAware { 33 private static final String TAG = "ShimRegistrar"; 34 35 private final Map<String, Object> globalRegistrarMap; 36 private final String pluginId; 37 private final Set<PluginRegistry.ViewDestroyListener> viewDestroyListeners = new HashSet<>(); 38 private final Set<PluginRegistry.RequestPermissionsResultListener> requestPermissionsResultListeners = new HashSet<>(); 39 private final Set<PluginRegistry.ActivityResultListener> activityResultListeners = new HashSet<>(); 40 private final Set<PluginRegistry.NewIntentListener> newIntentListeners = new HashSet<>(); 41 private final Set<PluginRegistry.UserLeaveHintListener> userLeaveHintListeners = new HashSet<>(); 42 private FlutterPlugin.FlutterPluginBinding pluginBinding; 43 private ActivityPluginBinding activityPluginBinding; 44 ShimRegistrar(@onNull String pluginId, @NonNull Map<String, Object> globalRegistrarMap)45 public ShimRegistrar(@NonNull String pluginId, @NonNull Map<String, Object> globalRegistrarMap) { 46 this.pluginId = pluginId; 47 this.globalRegistrarMap = globalRegistrarMap; 48 } 49 50 @Override activity()51 public Activity activity() { 52 return activityPluginBinding != null ? activityPluginBinding.getActivity() : null; 53 } 54 55 @Override context()56 public Context context() { 57 return pluginBinding != null ? pluginBinding.getApplicationContext() : null; 58 } 59 60 @Override activeContext()61 public Context activeContext() { 62 return activityPluginBinding == null ? context() : activity(); 63 } 64 65 @Override messenger()66 public BinaryMessenger messenger() { 67 return pluginBinding != null ? pluginBinding.getFlutterEngine().getDartExecutor() : null; 68 } 69 70 @Override textures()71 public TextureRegistry textures() { 72 return pluginBinding != null ? pluginBinding.getFlutterEngine().getRenderer() : null; 73 } 74 75 @Override platformViewRegistry()76 public PlatformViewRegistry platformViewRegistry() { 77 return pluginBinding != null ? pluginBinding.getFlutterEngine().getPlatformViewsController().getRegistry() : null; 78 } 79 80 @Override view()81 public FlutterView view() { 82 throw new UnsupportedOperationException("The new embedding does not support the old FlutterView."); 83 } 84 85 @Override lookupKeyForAsset(String asset)86 public String lookupKeyForAsset(String asset) { 87 return FlutterMain.getLookupKeyForAsset(asset); 88 } 89 90 @Override lookupKeyForAsset(String asset, String packageName)91 public String lookupKeyForAsset(String asset, String packageName) { 92 return FlutterMain.getLookupKeyForAsset(asset, packageName); 93 } 94 95 @Override publish(Object value)96 public PluginRegistry.Registrar publish(Object value) { 97 globalRegistrarMap.put(pluginId, value); 98 return this; 99 } 100 101 @Override addRequestPermissionsResultListener(PluginRegistry.RequestPermissionsResultListener listener)102 public PluginRegistry.Registrar addRequestPermissionsResultListener(PluginRegistry.RequestPermissionsResultListener listener) { 103 requestPermissionsResultListeners.add(listener); 104 105 if (activityPluginBinding != null) { 106 activityPluginBinding.addRequestPermissionsResultListener(listener); 107 } 108 109 return this; 110 } 111 112 @Override addActivityResultListener(PluginRegistry.ActivityResultListener listener)113 public PluginRegistry.Registrar addActivityResultListener(PluginRegistry.ActivityResultListener listener) { 114 activityResultListeners.add(listener); 115 116 if (activityPluginBinding != null) { 117 activityPluginBinding.addActivityResultListener(listener); 118 } 119 120 return this; 121 } 122 123 @Override addNewIntentListener(PluginRegistry.NewIntentListener listener)124 public PluginRegistry.Registrar addNewIntentListener(PluginRegistry.NewIntentListener listener) { 125 newIntentListeners.add(listener); 126 127 if (activityPluginBinding != null) { 128 activityPluginBinding.addOnNewIntentListener(listener); 129 } 130 131 return this; 132 } 133 134 @Override addUserLeaveHintListener(PluginRegistry.UserLeaveHintListener listener)135 public PluginRegistry.Registrar addUserLeaveHintListener(PluginRegistry.UserLeaveHintListener listener) { 136 userLeaveHintListeners.add(listener); 137 138 if (activityPluginBinding != null) { 139 activityPluginBinding.addOnUserLeaveHintListener(listener); 140 } 141 142 return this; 143 } 144 145 @Override 146 @NonNull addViewDestroyListener(@onNull PluginRegistry.ViewDestroyListener listener)147 public PluginRegistry.Registrar addViewDestroyListener(@NonNull PluginRegistry.ViewDestroyListener listener) { 148 viewDestroyListeners.add(listener); 149 return this; 150 } 151 152 @Override onAttachedToEngine(@onNull FlutterPluginBinding binding)153 public void onAttachedToEngine(@NonNull FlutterPluginBinding binding) { 154 Log.v(TAG, "Attached to FlutterEngine."); 155 pluginBinding = binding; 156 } 157 158 @Override onDetachedFromEngine(@onNull FlutterPluginBinding binding)159 public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) { 160 Log.v(TAG, "Detached from FlutterEngine."); 161 for (PluginRegistry.ViewDestroyListener listener : viewDestroyListeners) { 162 // The following invocation might produce unexpected behavior in old plugins because 163 // we have no FlutterNativeView to pass to onViewDestroy(). This is a limitation of this shim. 164 listener.onViewDestroy(null); 165 } 166 167 pluginBinding = null; 168 } 169 170 @Override onAttachedToActivity(@onNull ActivityPluginBinding binding)171 public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) { 172 Log.v(TAG, "Attached to an Activity."); 173 activityPluginBinding = binding; 174 addExistingListenersToActivityPluginBinding(); 175 } 176 177 @Override onDetachedFromActivityForConfigChanges()178 public void onDetachedFromActivityForConfigChanges() { 179 Log.v(TAG, "Detached from an Activity for config changes."); 180 activityPluginBinding = null; 181 } 182 183 @Override onReattachedToActivityForConfigChanges(@onNull ActivityPluginBinding binding)184 public void onReattachedToActivityForConfigChanges(@NonNull ActivityPluginBinding binding) { 185 Log.v(TAG, "Reconnected to an Activity after config changes."); 186 activityPluginBinding = binding; 187 addExistingListenersToActivityPluginBinding(); 188 } 189 190 @Override onDetachedFromActivity()191 public void onDetachedFromActivity() { 192 Log.v(TAG, "Detached from an Activity."); 193 activityPluginBinding = null; 194 } 195 addExistingListenersToActivityPluginBinding()196 private void addExistingListenersToActivityPluginBinding() { 197 for (PluginRegistry.RequestPermissionsResultListener listener : requestPermissionsResultListeners) { 198 activityPluginBinding.addRequestPermissionsResultListener(listener); 199 } 200 for (PluginRegistry.ActivityResultListener listener : activityResultListeners) { 201 activityPluginBinding.addActivityResultListener(listener); 202 } 203 for (PluginRegistry.NewIntentListener listener : newIntentListeners) { 204 activityPluginBinding.addOnNewIntentListener(listener); 205 } 206 for (PluginRegistry.UserLeaveHintListener listener : userLeaveHintListeners) { 207 activityPluginBinding.addOnUserLeaveHintListener(listener); 208 } 209 } 210 } 211