Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
FlutterEngineConnectionRegistry.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;
6
7import android.app.Activity;
8import android.app.Service;
9import android.content.BroadcastReceiver;
10import android.content.ContentProvider;
11import android.content.Context;
12import android.content.Intent;
13import android.os.Bundle;
14import androidx.annotation.NonNull;
15import androidx.annotation.Nullable;
16import androidx.lifecycle.Lifecycle;
17import io.flutter.Log;
18import io.flutter.embedding.android.ExclusiveAppComponent;
19import io.flutter.embedding.engine.loader.FlutterLoader;
20import io.flutter.embedding.engine.plugins.FlutterPlugin;
21import io.flutter.embedding.engine.plugins.PluginRegistry;
22import io.flutter.embedding.engine.plugins.activity.ActivityAware;
23import io.flutter.embedding.engine.plugins.activity.ActivityControlSurface;
24import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
25import io.flutter.embedding.engine.plugins.broadcastreceiver.BroadcastReceiverAware;
26import io.flutter.embedding.engine.plugins.broadcastreceiver.BroadcastReceiverControlSurface;
27import io.flutter.embedding.engine.plugins.broadcastreceiver.BroadcastReceiverPluginBinding;
28import io.flutter.embedding.engine.plugins.contentprovider.ContentProviderAware;
29import io.flutter.embedding.engine.plugins.contentprovider.ContentProviderControlSurface;
30import io.flutter.embedding.engine.plugins.contentprovider.ContentProviderPluginBinding;
31import io.flutter.embedding.engine.plugins.lifecycle.HiddenLifecycleReference;
32import io.flutter.embedding.engine.plugins.service.ServiceAware;
33import io.flutter.embedding.engine.plugins.service.ServiceControlSurface;
34import io.flutter.embedding.engine.plugins.service.ServicePluginBinding;
35import io.flutter.util.TraceSection;
36import java.util.HashMap;
37import java.util.HashSet;
38import java.util.Map;
39import java.util.Set;
40
41/**
42 * This class is owned by the {@link io.flutter.embedding.engine.FlutterEngine} and its role is to
43 * managed its connections with Android App Components and Flutter plugins.
44 *
45 * <p>It enforces the {0|1}:1 relationship between activity and engine, and propagates the app
46 * component connection to the plugins.
47 */
49 implements PluginRegistry,
50 ActivityControlSurface,
51 ServiceControlSurface,
52 BroadcastReceiverControlSurface,
53 ContentProviderControlSurface {
54 private static final String TAG = "FlutterEngineCxnRegstry";
55
56 // PluginRegistry
57 @NonNull
58 private final Map<Class<? extends FlutterPlugin>, FlutterPlugin> plugins = new HashMap<>();
59
60 // Standard FlutterPlugin
61 @NonNull private final FlutterEngine flutterEngine;
62 @NonNull private final FlutterPlugin.FlutterPluginBinding pluginBinding;
63
64 // ActivityAware
65 @NonNull
66 private final Map<Class<? extends FlutterPlugin>, ActivityAware> activityAwarePlugins =
67 new HashMap<>();
68
69 @Nullable private ExclusiveAppComponent<Activity> exclusiveActivity;
70 @Nullable private FlutterEngineActivityPluginBinding activityPluginBinding;
71 private boolean isWaitingForActivityReattachment = false;
72
73 // ServiceAware
74 @NonNull
75 private final Map<Class<? extends FlutterPlugin>, ServiceAware> serviceAwarePlugins =
76 new HashMap<>();
77
78 @Nullable private Service service;
79 @Nullable private FlutterEngineServicePluginBinding servicePluginBinding;
80
81 // BroadcastReceiver
82 @NonNull
83 private final Map<Class<? extends FlutterPlugin>, BroadcastReceiverAware>
84 broadcastReceiverAwarePlugins = new HashMap<>();
85
86 @Nullable private BroadcastReceiver broadcastReceiver;
87 @Nullable private FlutterEngineBroadcastReceiverPluginBinding broadcastReceiverPluginBinding;
88
89 // ContentProvider
90 @NonNull
91 private final Map<Class<? extends FlutterPlugin>, ContentProviderAware>
92 contentProviderAwarePlugins = new HashMap<>();
93
94 @Nullable private ContentProvider contentProvider;
95 @Nullable private FlutterEngineContentProviderPluginBinding contentProviderPluginBinding;
96
98 @NonNull Context appContext,
99 @NonNull FlutterEngine flutterEngine,
100 @NonNull FlutterLoader flutterLoader,
101 @Nullable FlutterEngineGroup group) {
102 this.flutterEngine = flutterEngine;
103 pluginBinding =
104 new FlutterPlugin.FlutterPluginBinding(
105 appContext,
106 flutterEngine,
107 flutterEngine.getDartExecutor(),
108 flutterEngine.getRenderer(),
109 flutterEngine.getPlatformViewsController().getRegistry(),
110 new DefaultFlutterAssets(flutterLoader),
111 group);
112 }
113
114 public void destroy() {
115 Log.v(TAG, "Destroying.");
116 // Detach from any Android component that we may currently be attached to, e.g., Activity,
117 // Service, BroadcastReceiver, ContentProvider. This must happen before removing all plugins so
118 // that the plugins have an opportunity to clean up references as a result of component
119 // detachment.
120 detachFromAppComponent();
121
122 // Remove all registered plugins.
123 removeAll();
124 }
125
126 @Override
127 public void add(@NonNull FlutterPlugin plugin) {
128 try (TraceSection e =
129 TraceSection.scoped(
130 "FlutterEngineConnectionRegistry#add " + plugin.getClass().getSimpleName())) {
131 if (has(plugin.getClass())) {
132 Log.w(
133 TAG,
134 "Attempted to register plugin ("
135 + plugin
136 + ") but it was "
137 + "already registered with this FlutterEngine ("
138 + flutterEngine
139 + ").");
140 return;
141 }
142
143 Log.v(TAG, "Adding plugin: " + plugin);
144 // Add the plugin to our generic set of plugins and notify the plugin
145 // that is has been attached to an engine.
146 plugins.put(plugin.getClass(), plugin);
147 plugin.onAttachedToEngine(pluginBinding);
148
149 // For ActivityAware plugins, add the plugin to our set of ActivityAware
150 // plugins, and if this engine is currently attached to an Activity,
151 // notify the ActivityAware plugin that it is now attached to an Activity.
152 if (plugin instanceof ActivityAware) {
153 ActivityAware activityAware = (ActivityAware) plugin;
154 activityAwarePlugins.put(plugin.getClass(), activityAware);
155
156 if (isAttachedToActivity()) {
157 activityAware.onAttachedToActivity(activityPluginBinding);
158 }
159 }
160
161 // For ServiceAware plugins, add the plugin to our set of ServiceAware
162 // plugins, and if this engine is currently attached to a Service,
163 // notify the ServiceAware plugin that it is now attached to a Service.
164 if (plugin instanceof ServiceAware) {
165 ServiceAware serviceAware = (ServiceAware) plugin;
166 serviceAwarePlugins.put(plugin.getClass(), serviceAware);
167
168 if (isAttachedToService()) {
169 serviceAware.onAttachedToService(servicePluginBinding);
170 }
171 }
172
173 // For BroadcastReceiverAware plugins, add the plugin to our set of BroadcastReceiverAware
174 // plugins, and if this engine is currently attached to a BroadcastReceiver,
175 // notify the BroadcastReceiverAware plugin that it is now attached to a BroadcastReceiver.
176 if (plugin instanceof BroadcastReceiverAware) {
177 BroadcastReceiverAware broadcastReceiverAware = (BroadcastReceiverAware) plugin;
178 broadcastReceiverAwarePlugins.put(plugin.getClass(), broadcastReceiverAware);
179
180 if (isAttachedToBroadcastReceiver()) {
181 broadcastReceiverAware.onAttachedToBroadcastReceiver(broadcastReceiverPluginBinding);
182 }
183 }
184
185 // For ContentProviderAware plugins, add the plugin to our set of ContentProviderAware
186 // plugins, and if this engine is currently attached to a ContentProvider,
187 // notify the ContentProviderAware plugin that it is now attached to a ContentProvider.
188 if (plugin instanceof ContentProviderAware) {
189 ContentProviderAware contentProviderAware = (ContentProviderAware) plugin;
190 contentProviderAwarePlugins.put(plugin.getClass(), contentProviderAware);
191
192 if (isAttachedToContentProvider()) {
193 contentProviderAware.onAttachedToContentProvider(contentProviderPluginBinding);
194 }
195 }
196 }
197 }
198
199 @Override
200 public void add(@NonNull Set<FlutterPlugin> plugins) {
201 for (FlutterPlugin plugin : plugins) {
202 add(plugin);
203 }
204 }
205
206 @Override
207 public boolean has(@NonNull Class<? extends FlutterPlugin> pluginClass) {
208 return plugins.containsKey(pluginClass);
209 }
210
211 @Override
212 public FlutterPlugin get(@NonNull Class<? extends FlutterPlugin> pluginClass) {
213 return plugins.get(pluginClass);
214 }
215
216 @Override
217 public void remove(@NonNull Class<? extends FlutterPlugin> pluginClass) {
218 FlutterPlugin plugin = plugins.get(pluginClass);
219 if (plugin == null) {
220 return;
221 }
222
223 try (TraceSection e =
224 TraceSection.scoped(
225 "FlutterEngineConnectionRegistry#remove " + pluginClass.getSimpleName())) {
226 // For ActivityAware plugins, notify the plugin that it is detached from
227 // an Activity if an Activity is currently attached to this engine. Then
228 // remove the plugin from our set of ActivityAware plugins.
229 if (plugin instanceof ActivityAware) {
230 if (isAttachedToActivity()) {
231 ActivityAware activityAware = (ActivityAware) plugin;
232 activityAware.onDetachedFromActivity();
233 }
234 activityAwarePlugins.remove(pluginClass);
235 }
236
237 // For ServiceAware plugins, notify the plugin that it is detached from
238 // a Service if a Service is currently attached to this engine. Then
239 // remove the plugin from our set of ServiceAware plugins.
240 if (plugin instanceof ServiceAware) {
241 if (isAttachedToService()) {
242 ServiceAware serviceAware = (ServiceAware) plugin;
243 serviceAware.onDetachedFromService();
244 }
245 serviceAwarePlugins.remove(pluginClass);
246 }
247
248 // For BroadcastReceiverAware plugins, notify the plugin that it is detached from
249 // a BroadcastReceiver if a BroadcastReceiver is currently attached to this engine. Then
250 // remove the plugin from our set of BroadcastReceiverAware plugins.
251 if (plugin instanceof BroadcastReceiverAware) {
252 if (isAttachedToBroadcastReceiver()) {
253 BroadcastReceiverAware broadcastReceiverAware = (BroadcastReceiverAware) plugin;
254 broadcastReceiverAware.onDetachedFromBroadcastReceiver();
255 }
256 broadcastReceiverAwarePlugins.remove(pluginClass);
257 }
258
259 // For ContentProviderAware plugins, notify the plugin that it is detached from
260 // a ContentProvider if a ContentProvider is currently attached to this engine. Then
261 // remove the plugin from our set of ContentProviderAware plugins.
262 if (plugin instanceof ContentProviderAware) {
263 if (isAttachedToContentProvider()) {
264 ContentProviderAware contentProviderAware = (ContentProviderAware) plugin;
265 contentProviderAware.onDetachedFromContentProvider();
266 }
267 contentProviderAwarePlugins.remove(pluginClass);
268 }
269
270 // Notify the plugin that is now detached from this engine. Then remove
271 // it from our set of generic plugins.
272 plugin.onDetachedFromEngine(pluginBinding);
273 plugins.remove(pluginClass);
274 }
275 }
276
277 @Override
278 public void remove(@NonNull Set<Class<? extends FlutterPlugin>> pluginClasses) {
279 for (Class<? extends FlutterPlugin> pluginClass : pluginClasses) {
280 remove(pluginClass);
281 }
282 }
283
284 @Override
285 public void removeAll() {
286 // We copy the keys to a new set so that we can mutate the set while using
287 // the keys.
288 remove(new HashSet<>(plugins.keySet()));
289 plugins.clear();
290 }
291
292 private void detachFromAppComponent() {
293 if (isAttachedToActivity()) {
295 } else if (isAttachedToService()) {
297 } else if (isAttachedToBroadcastReceiver()) {
299 } else if (isAttachedToContentProvider()) {
301 }
302 }
303
304 // -------- Start ActivityControlSurface -------
305 private boolean isAttachedToActivity() {
306 return exclusiveActivity != null;
307 }
308
309 private Activity attachedActivity() {
310 return exclusiveActivity != null ? exclusiveActivity.getAppComponent() : null;
311 }
312
313 @Override
314 public void attachToActivity(
315 @NonNull ExclusiveAppComponent<Activity> exclusiveActivity, @NonNull Lifecycle lifecycle) {
316 try (TraceSection e = TraceSection.scoped("FlutterEngineConnectionRegistry#attachToActivity")) {
317 if (this.exclusiveActivity != null) {
318 this.exclusiveActivity.detachFromFlutterEngine();
319 }
320 // If we were already attached to an app component, detach from it.
321 detachFromAppComponent();
322 this.exclusiveActivity = exclusiveActivity;
323 attachToActivityInternal(exclusiveActivity.getAppComponent(), lifecycle);
324 }
325 }
326
327 private void attachToActivityInternal(@NonNull Activity activity, @NonNull Lifecycle lifecycle) {
328 this.activityPluginBinding = new FlutterEngineActivityPluginBinding(activity, lifecycle);
329
330 final boolean useSoftwareRendering =
331 activity.getIntent() != null
332 ? activity
333 .getIntent()
335 : false;
336 flutterEngine.getPlatformViewsController().setSoftwareRendering(useSoftwareRendering);
337
338 // Activate the PlatformViewsController. This must happen before any plugins attempt
339 // to use it, otherwise an error stack trace will appear that says there is no
340 // flutter/platform_views channel.
341 flutterEngine
342 .getPlatformViewsController()
343 .attach(activity, flutterEngine.getRenderer(), flutterEngine.getDartExecutor());
344
345 // Notify all ActivityAware plugins that they are now attached to a new Activity.
346 for (ActivityAware activityAware : activityAwarePlugins.values()) {
347 if (isWaitingForActivityReattachment) {
348 activityAware.onReattachedToActivityForConfigChanges(activityPluginBinding);
349 } else {
350 activityAware.onAttachedToActivity(activityPluginBinding);
351 }
352 }
353 isWaitingForActivityReattachment = false;
354 }
355
356 @Override
358 if (isAttachedToActivity()) {
359 try (TraceSection e =
360 TraceSection.scoped(
361 "FlutterEngineConnectionRegistry#detachFromActivityForConfigChanges")) {
362 isWaitingForActivityReattachment = true;
363
364 for (ActivityAware activityAware : activityAwarePlugins.values()) {
365 activityAware.onDetachedFromActivityForConfigChanges();
366 }
367
368 detachFromActivityInternal();
369 }
370 } else {
371 Log.e(TAG, "Attempted to detach plugins from an Activity when no Activity was attached.");
372 }
373 }
374
375 @Override
376 public void detachFromActivity() {
377 if (isAttachedToActivity()) {
378 try (TraceSection e =
379 TraceSection.scoped("FlutterEngineConnectionRegistry#detachFromActivity")) {
380 for (ActivityAware activityAware : activityAwarePlugins.values()) {
381 activityAware.onDetachedFromActivity();
382 }
383
384 detachFromActivityInternal();
385 }
386 } else {
387 Log.e(TAG, "Attempted to detach plugins from an Activity when no Activity was attached.");
388 }
389 }
390
391 private void detachFromActivityInternal() {
392 // Deactivate PlatformViewsController.
393 flutterEngine.getPlatformViewsController().detach();
394
395 exclusiveActivity = null;
396 activityPluginBinding = null;
397 }
398
399 @Override
401 int requestCode, @NonNull String[] permissions, @NonNull int[] grantResult) {
402 if (isAttachedToActivity()) {
403 try (TraceSection e =
404 TraceSection.scoped("FlutterEngineConnectionRegistry#onRequestPermissionsResult")) {
405 return activityPluginBinding.onRequestPermissionsResult(
406 requestCode, permissions, grantResult);
407 }
408 } else {
409 Log.e(
410 TAG,
411 "Attempted to notify ActivityAware plugins of onRequestPermissionsResult, but no Activity"
412 + " was attached.");
413 return false;
414 }
415 }
416
417 @Override
418 public boolean onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
419 if (isAttachedToActivity()) {
420 try (TraceSection e =
421 TraceSection.scoped("FlutterEngineConnectionRegistry#onActivityResult")) {
422 return activityPluginBinding.onActivityResult(requestCode, resultCode, data);
423 }
424 } else {
425 Log.e(
426 TAG,
427 "Attempted to notify ActivityAware plugins of onActivityResult, but no Activity was"
428 + " attached.");
429 return false;
430 }
431 }
432
433 @Override
434 public void onNewIntent(@NonNull Intent intent) {
435 if (isAttachedToActivity()) {
436 try (TraceSection e = TraceSection.scoped("FlutterEngineConnectionRegistry#onNewIntent")) {
437 activityPluginBinding.onNewIntent(intent);
438 }
439 } else {
440 Log.e(
441 TAG,
442 "Attempted to notify ActivityAware plugins of onNewIntent, but no Activity was"
443 + " attached.");
444 }
445 }
446
447 @Override
448 public void onUserLeaveHint() {
449 if (isAttachedToActivity()) {
450 try (TraceSection e =
451 TraceSection.scoped("FlutterEngineConnectionRegistry#onUserLeaveHint")) {
452 activityPluginBinding.onUserLeaveHint();
453 }
454 } else {
455 Log.e(
456 TAG,
457 "Attempted to notify ActivityAware plugins of onUserLeaveHint, but no Activity was"
458 + " attached.");
459 }
460 }
461
462 @Override
463 public void onSaveInstanceState(@NonNull Bundle bundle) {
464 if (isAttachedToActivity()) {
465 try (TraceSection e =
466 TraceSection.scoped("FlutterEngineConnectionRegistry#onSaveInstanceState")) {
467 activityPluginBinding.onSaveInstanceState(bundle);
468 }
469 } else {
470 Log.e(
471 TAG,
472 "Attempted to notify ActivityAware plugins of onSaveInstanceState, but no Activity was"
473 + " attached.");
474 }
475 }
476
477 @Override
478 public void onRestoreInstanceState(@Nullable Bundle bundle) {
479 if (isAttachedToActivity()) {
480 try (TraceSection e =
481 TraceSection.scoped("FlutterEngineConnectionRegistry#onRestoreInstanceState")) {
482 activityPluginBinding.onRestoreInstanceState(bundle);
483 }
484 } else {
485 Log.e(
486 TAG,
487 "Attempted to notify ActivityAware plugins of onRestoreInstanceState, but no Activity was"
488 + " attached.");
489 }
490 }
491 // ------- End ActivityControlSurface -----
492
493 // ----- Start ServiceControlSurface ----
494 private boolean isAttachedToService() {
495 return service != null;
496 }
497
498 @Override
499 public void attachToService(
500 @NonNull Service service, @Nullable Lifecycle lifecycle, boolean isForeground) {
501 try (TraceSection e = TraceSection.scoped("FlutterEngineConnectionRegistry#attachToService")) {
502 // If we were already attached to an Android component, detach from it.
503 detachFromAppComponent();
504
505 this.service = service;
506 this.servicePluginBinding = new FlutterEngineServicePluginBinding(service, lifecycle);
507
508 // Notify all ServiceAware plugins that they are now attached to a new Service.
509 for (ServiceAware serviceAware : serviceAwarePlugins.values()) {
510 serviceAware.onAttachedToService(servicePluginBinding);
511 }
512 }
513 }
514
515 @Override
516 public void detachFromService() {
517 if (isAttachedToService()) {
518 try (TraceSection e =
519 TraceSection.scoped("FlutterEngineConnectionRegistry#detachFromService")) {
520 // Notify all ServiceAware plugins that they are no longer attached to a Service.
521 for (ServiceAware serviceAware : serviceAwarePlugins.values()) {
522 serviceAware.onDetachedFromService();
523 }
524
525 service = null;
526 servicePluginBinding = null;
527 }
528 } else {
529 Log.e(TAG, "Attempted to detach plugins from a Service when no Service was attached.");
530 }
531 }
532
533 @Override
534 public void onMoveToForeground() {
535 if (isAttachedToService()) {
536 try (TraceSection e =
537 TraceSection.scoped("FlutterEngineConnectionRegistry#onMoveToForeground")) {
538 servicePluginBinding.onMoveToForeground();
539 }
540 }
541 }
542
543 @Override
544 public void onMoveToBackground() {
545 if (isAttachedToService()) {
546 try (TraceSection e =
547 TraceSection.scoped("FlutterEngineConnectionRegistry#onMoveToBackground")) {
548 servicePluginBinding.onMoveToBackground();
549 }
550 }
551 }
552 // ----- End ServiceControlSurface ---
553
554 // ----- Start BroadcastReceiverControlSurface ---
555 private boolean isAttachedToBroadcastReceiver() {
556 return broadcastReceiver != null;
557 }
558
559 @Override
561 @NonNull BroadcastReceiver broadcastReceiver, @NonNull Lifecycle lifecycle) {
562 try (TraceSection e =
563 TraceSection.scoped("FlutterEngineConnectionRegistry#attachToBroadcastReceiver")) {
564 // If we were already attached to an Android component, detach from it.
565 detachFromAppComponent();
566
567 this.broadcastReceiver = broadcastReceiver;
568 this.broadcastReceiverPluginBinding =
569 new FlutterEngineBroadcastReceiverPluginBinding(broadcastReceiver);
570 // TODO(mattcarroll): resolve possibility of different lifecycles between this and engine
571 // attachment
572
573 // Notify all BroadcastReceiverAware plugins that they are now attached to a new
574 // BroadcastReceiver.
575 for (BroadcastReceiverAware broadcastReceiverAware : broadcastReceiverAwarePlugins.values()) {
576 broadcastReceiverAware.onAttachedToBroadcastReceiver(broadcastReceiverPluginBinding);
577 }
578 }
579 }
580
581 @Override
583 if (isAttachedToBroadcastReceiver()) {
584 try (TraceSection e =
585 TraceSection.scoped("FlutterEngineConnectionRegistry#detachFromBroadcastReceiver")) {
586 // Notify all BroadcastReceiverAware plugins that they are no longer attached to a
587 // BroadcastReceiver.
588 for (BroadcastReceiverAware broadcastReceiverAware :
589 broadcastReceiverAwarePlugins.values()) {
590 broadcastReceiverAware.onDetachedFromBroadcastReceiver();
591 }
592 }
593 } else {
594 Log.e(
595 TAG,
596 "Attempted to detach plugins from a BroadcastReceiver when no BroadcastReceiver was"
597 + " attached.");
598 }
599 }
600 // ----- End BroadcastReceiverControlSurface ----
601
602 // ----- Start ContentProviderControlSurface ----
603 private boolean isAttachedToContentProvider() {
604 return contentProvider != null;
605 }
606
607 @Override
609 @NonNull ContentProvider contentProvider, @NonNull Lifecycle lifecycle) {
610
611 try (TraceSection e =
612 TraceSection.scoped("FlutterEngineConnectionRegistry#attachToContentProvider")) {
613 // If we were already attached to an Android component, detach from it.
614 detachFromAppComponent();
615
616 this.contentProvider = contentProvider;
617 this.contentProviderPluginBinding =
618 new FlutterEngineContentProviderPluginBinding(contentProvider);
619 // TODO(mattcarroll): resolve possibility of different lifecycles between this and engine
620 // attachment
621
622 // Notify all ContentProviderAware plugins that they are now attached to a new
623 // ContentProvider.
624 for (ContentProviderAware contentProviderAware : contentProviderAwarePlugins.values()) {
625 contentProviderAware.onAttachedToContentProvider(contentProviderPluginBinding);
626 }
627 }
628 }
629
630 @Override
632 if (isAttachedToContentProvider()) {
633 try (TraceSection e =
634 TraceSection.scoped("FlutterEngineConnectionRegistry#detachFromContentProvider")) {
635 // Notify all ContentProviderAware plugins that they are no longer attached to a
636 // ContentProvider.
637 for (ContentProviderAware contentProviderAware : contentProviderAwarePlugins.values()) {
638 contentProviderAware.onDetachedFromContentProvider();
639 }
640 }
641 } else {
642 Log.e(
643 TAG,
644 "Attempted to detach plugins from a ContentProvider when no ContentProvider was"
645 + " attached.");
646 }
647 }
648 // ----- End ContentProviderControlSurface -----
649
650 private static class DefaultFlutterAssets implements FlutterPlugin.FlutterAssets {
651 final FlutterLoader flutterLoader;
652
653 private DefaultFlutterAssets(@NonNull FlutterLoader flutterLoader) {
654 this.flutterLoader = flutterLoader;
655 }
656
657 public String getAssetFilePathByName(@NonNull String assetFileName) {
658 return flutterLoader.getLookupKeyForAsset(assetFileName);
659 }
660
661 public String getAssetFilePathByName(
662 @NonNull String assetFileName, @NonNull String packageName) {
663 return flutterLoader.getLookupKeyForAsset(assetFileName, packageName);
664 }
665
666 public String getAssetFilePathBySubpath(@NonNull String assetSubpath) {
667 return flutterLoader.getLookupKeyForAsset(assetSubpath);
668 }
669
670 public String getAssetFilePathBySubpath(
671 @NonNull String assetSubpath, @NonNull String packageName) {
672 return flutterLoader.getLookupKeyForAsset(assetSubpath, packageName);
673 }
674 }
675
676 private static class FlutterEngineActivityPluginBinding implements ActivityPluginBinding {
677 @NonNull private final Activity activity;
678 @NonNull private final HiddenLifecycleReference hiddenLifecycleReference;
679
680 @NonNull
681 private final Set<io.flutter.plugin.common.PluginRegistry.RequestPermissionsResultListener>
682 onRequestPermissionsResultListeners = new HashSet<>();
683
684 @NonNull
685 private final Set<io.flutter.plugin.common.PluginRegistry.ActivityResultListener>
686 onActivityResultListeners = new HashSet<>();
687
688 @NonNull
689 private final Set<io.flutter.plugin.common.PluginRegistry.NewIntentListener>
690 onNewIntentListeners = new HashSet<>();
691
692 @NonNull
693 private final Set<io.flutter.plugin.common.PluginRegistry.UserLeaveHintListener>
694 onUserLeaveHintListeners = new HashSet<>();
695
696 @NonNull
697 private final Set<io.flutter.plugin.common.PluginRegistry.WindowFocusChangedListener>
698 onWindowFocusChangedListeners = new HashSet<>();
699
700 @NonNull
701 private final Set<OnSaveInstanceStateListener> onSaveInstanceStateListeners = new HashSet<>();
702
703 public FlutterEngineActivityPluginBinding(
704 @NonNull Activity activity, @NonNull Lifecycle lifecycle) {
705 this.activity = activity;
706 this.hiddenLifecycleReference = new HiddenLifecycleReference(lifecycle);
707 }
708
709 @Override
710 @NonNull
711 public Activity getActivity() {
712 return activity;
713 }
714
715 @NonNull
716 @Override
717 public Object getLifecycle() {
718 return hiddenLifecycleReference;
719 }
720
721 @Override
722 public void addRequestPermissionsResultListener(
723 @NonNull
724 io.flutter.plugin.common.PluginRegistry.RequestPermissionsResultListener listener) {
725 onRequestPermissionsResultListeners.add(listener);
726 }
727
728 @Override
729 public void removeRequestPermissionsResultListener(
730 @NonNull
731 io.flutter.plugin.common.PluginRegistry.RequestPermissionsResultListener listener) {
732 onRequestPermissionsResultListeners.remove(listener);
733 }
734
735 /**
736 * Invoked by the {@link io.flutter.embedding.engine.FlutterEngine} that owns this {@code
737 * ActivityPluginBinding} when its associated {@link android.app.Activity} has its {@code
738 * onRequestPermissionsResult(...)} method invoked.
739 */
740 boolean onRequestPermissionsResult(
741 int requestCode, @NonNull String[] permissions, @NonNull int[] grantResult) {
742 boolean didConsumeResult = false;
743 for (io.flutter.plugin.common.PluginRegistry.RequestPermissionsResultListener listener :
744 onRequestPermissionsResultListeners) {
745 didConsumeResult =
746 listener.onRequestPermissionsResult(requestCode, permissions, grantResult)
747 || didConsumeResult;
748 }
749 return didConsumeResult;
750 }
751
752 @Override
753 public void addActivityResultListener(
754 @NonNull io.flutter.plugin.common.PluginRegistry.ActivityResultListener listener) {
755 onActivityResultListeners.add(listener);
756 }
757
758 @Override
759 public void removeActivityResultListener(
760 @NonNull io.flutter.plugin.common.PluginRegistry.ActivityResultListener listener) {
761 onActivityResultListeners.remove(listener);
762 }
763
764 /**
765 * Invoked by the {@link io.flutter.embedding.engine.FlutterEngine} that owns this {@code
766 * ActivityPluginBinding} when its associated {@link android.app.Activity} has its {@code
767 * onActivityResult(...)} method invoked.
768 */
769 boolean onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
770 boolean didConsumeResult = false;
771 for (io.flutter.plugin.common.PluginRegistry.ActivityResultListener listener :
772 new HashSet<>(onActivityResultListeners)) {
773 didConsumeResult =
774 listener.onActivityResult(requestCode, resultCode, data) || didConsumeResult;
775 }
776 return didConsumeResult;
777 }
778
779 @Override
780 public void addOnNewIntentListener(
781 @NonNull io.flutter.plugin.common.PluginRegistry.NewIntentListener listener) {
782 onNewIntentListeners.add(listener);
783 }
784
785 @Override
786 public void removeOnNewIntentListener(
787 @NonNull io.flutter.plugin.common.PluginRegistry.NewIntentListener listener) {
788 onNewIntentListeners.remove(listener);
789 }
790
791 /**
792 * Invoked by the {@link io.flutter.embedding.engine.FlutterEngine} that owns this {@code
793 * ActivityPluginBinding} when its associated {@link android.app.Activity} has its {@code
794 * onNewIntent(...)} method invoked.
795 */
796 void onNewIntent(@Nullable Intent intent) {
797 for (io.flutter.plugin.common.PluginRegistry.NewIntentListener listener :
798 onNewIntentListeners) {
799 listener.onNewIntent(intent);
800 }
801 }
802
803 @Override
804 public void addOnUserLeaveHintListener(
805 @NonNull io.flutter.plugin.common.PluginRegistry.UserLeaveHintListener listener) {
806 onUserLeaveHintListeners.add(listener);
807 }
808
809 @Override
810 public void removeOnUserLeaveHintListener(
811 @NonNull io.flutter.plugin.common.PluginRegistry.UserLeaveHintListener listener) {
812 onUserLeaveHintListeners.remove(listener);
813 }
814
815 @Override
816 public void addOnWindowFocusChangedListener(
817 @NonNull io.flutter.plugin.common.PluginRegistry.WindowFocusChangedListener listener) {
818 onWindowFocusChangedListeners.add(listener);
819 }
820
821 @Override
822 public void removeOnWindowFocusChangedListener(
823 @NonNull io.flutter.plugin.common.PluginRegistry.WindowFocusChangedListener listener) {
824 onWindowFocusChangedListeners.remove(listener);
825 }
826
827 void onWindowFocusChanged(boolean hasFocus) {
828 for (io.flutter.plugin.common.PluginRegistry.WindowFocusChangedListener listener :
829 onWindowFocusChangedListeners) {
830 listener.onWindowFocusChanged(hasFocus);
831 }
832 }
833
834 @Override
835 public void addOnSaveStateListener(@NonNull OnSaveInstanceStateListener listener) {
836 onSaveInstanceStateListeners.add(listener);
837 }
838
839 @Override
840 public void removeOnSaveStateListener(@NonNull OnSaveInstanceStateListener listener) {
841 onSaveInstanceStateListeners.remove(listener);
842 }
843
844 /**
845 * Invoked by the {@link io.flutter.embedding.engine.FlutterEngine} that owns this {@code
846 * ActivityPluginBinding} when its associated {@link android.app.Activity} has its {@code
847 * onUserLeaveHint()} method invoked.
848 */
849 void onUserLeaveHint() {
850 for (io.flutter.plugin.common.PluginRegistry.UserLeaveHintListener listener :
851 onUserLeaveHintListeners) {
852 listener.onUserLeaveHint();
853 }
854 }
855
856 /**
857 * Invoked by the {@link io.flutter.embedding.engine.FlutterEngine} that owns this {@code
858 * ActivityPluginBinding} when its associated {@link android.app.Activity} or {@code Fragment}
859 * has its {@code onSaveInstanceState(Bundle)} method invoked.
860 */
861 void onSaveInstanceState(@NonNull Bundle bundle) {
862 for (OnSaveInstanceStateListener listener : onSaveInstanceStateListeners) {
863 listener.onSaveInstanceState(bundle);
864 }
865 }
866
867 /**
868 * Invoked by the {@link io.flutter.embedding.engine.FlutterEngine} that owns this {@code
869 * ActivityPluginBinding} when its associated {@link android.app.Activity} or {@code Fragment}
870 * has its {@code onCreate(Bundle)} method invoked.
871 */
872 void onRestoreInstanceState(@Nullable Bundle bundle) {
873 for (OnSaveInstanceStateListener listener : onSaveInstanceStateListeners) {
874 listener.onRestoreInstanceState(bundle);
875 }
876 }
877 }
878
879 private static class FlutterEngineServicePluginBinding implements ServicePluginBinding {
880 @NonNull private final Service service;
881 @Nullable private final HiddenLifecycleReference hiddenLifecycleReference;
882
883 @NonNull
884 private final Set<ServiceAware.OnModeChangeListener> onModeChangeListeners = new HashSet<>();
885
886 FlutterEngineServicePluginBinding(@NonNull Service service, @Nullable Lifecycle lifecycle) {
887 this.service = service;
888 hiddenLifecycleReference = lifecycle != null ? new HiddenLifecycleReference(lifecycle) : null;
889 }
890
891 @Override
892 @NonNull
893 public Service getService() {
894 return service;
895 }
896
897 @Nullable
898 @Override
899 public Object getLifecycle() {
900 return hiddenLifecycleReference;
901 }
902
903 @Override
904 public void addOnModeChangeListener(@NonNull ServiceAware.OnModeChangeListener listener) {
905 onModeChangeListeners.add(listener);
906 }
907
908 @Override
909 public void removeOnModeChangeListener(@NonNull ServiceAware.OnModeChangeListener listener) {
910 onModeChangeListeners.remove(listener);
911 }
912
913 void onMoveToForeground() {
914 for (ServiceAware.OnModeChangeListener listener : onModeChangeListeners) {
915 listener.onMoveToForeground();
916 }
917 }
918
919 void onMoveToBackground() {
920 for (ServiceAware.OnModeChangeListener listener : onModeChangeListeners) {
921 listener.onMoveToBackground();
922 }
923 }
924 }
925
926 private static class FlutterEngineBroadcastReceiverPluginBinding
927 implements BroadcastReceiverPluginBinding {
928 @NonNull private final BroadcastReceiver broadcastReceiver;
929
930 FlutterEngineBroadcastReceiverPluginBinding(@NonNull BroadcastReceiver broadcastReceiver) {
931 this.broadcastReceiver = broadcastReceiver;
932 }
933
934 @NonNull
935 @Override
936 public BroadcastReceiver getBroadcastReceiver() {
937 return broadcastReceiver;
938 }
939 }
940
941 private static class FlutterEngineContentProviderPluginBinding
942 implements ContentProviderPluginBinding {
943 @NonNull private final ContentProvider contentProvider;
944
945 FlutterEngineContentProviderPluginBinding(@NonNull ContentProvider contentProvider) {
946 this.contentProvider = contentProvider;
947 }
948
949 @NonNull
950 @Override
951 public ContentProvider getContentProvider() {
952 return contentProvider;
953 }
954 }
955}
static void v(@NonNull String tag, @NonNull String message)
Definition Log.java:40
static void e(@NonNull String tag, @NonNull String message)
Definition Log.java:84
static void w(@NonNull String tag, @NonNull String message)
Definition Log.java:76
void attachToActivity( @NonNull ExclusiveAppComponent< Activity > exclusiveActivity, @NonNull Lifecycle lifecycle)
FlutterEngineConnectionRegistry( @NonNull Context appContext, @NonNull FlutterEngine flutterEngine, @NonNull FlutterLoader flutterLoader, @Nullable FlutterEngineGroup group)
void attachToContentProvider( @NonNull ContentProvider contentProvider, @NonNull Lifecycle lifecycle)
boolean onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResult)
void attachToBroadcastReceiver( @NonNull BroadcastReceiver broadcastReceiver, @NonNull Lifecycle lifecycle)
void attachToService( @NonNull Service service, @Nullable Lifecycle lifecycle, boolean isForeground)
boolean has(@NonNull Class<? extends FlutterPlugin > pluginClass)
boolean onActivityResult(int requestCode, int resultCode, @Nullable Intent data)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm service
Definition switches.h:99
#define TAG()