Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Android embedding API updates for plugin ecosystem #13280

Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,7 @@ protected void onCreate(@Nullable Bundle savedInstanceState) {

delegate = new FlutterActivityAndFragmentDelegate(this);
delegate.onAttach(this);
delegate.onActivityCreated(savedInstanceState);

configureWindowForTransparency();
setContentView(createFlutterView());
Expand Down Expand Up @@ -557,6 +558,12 @@ protected void onStop() {
lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_STOP);
}

@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
delegate.onSaveInstanceState(outState);
}

@Override
protected void onDestroy() {
super.onDestroy();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,15 @@ View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nulla
return flutterSplashView;
}

void onActivityCreated(@Nullable Bundle bundle) {
Log.v(TAG, "onActivityCreated. Giving plugins an opportunity to restore state.");
ensureAlive();

if (host.shouldAttachEngineToActivity()) {
flutterEngine.getActivityControlSurface().onRestoreInstanceState(bundle);
}
}

/**
* Invoke this from {@code Activity#onStart()} or {@code Fragment#onStart()}.
* <p>
Expand Down Expand Up @@ -404,6 +413,15 @@ void onDestroyView() {
flutterView.removeOnFirstFrameRenderedListener(flutterUiDisplayListener);
}

void onSaveInstanceState(@Nullable Bundle bundle) {
Log.v(TAG, "onSaveInstanceState. Giving plugins an opportunity to save state.");
ensureAlive();

if (host.shouldAttachEngineToActivity()) {
flutterEngine.getActivityControlSurface().onSaveInstanceState(bundle);
}
}

/**
* Invoke this from {@code Activity#onDestroy()} or {@code Fragment#onDetach()}.
* <p>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -586,6 +586,12 @@ public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
return delegate.onCreateView(inflater, container, savedInstanceState);
}

@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
delegate.onActivityCreated(savedInstanceState);
}

@Override
public void onStart() {
super.onStart();
Expand Down Expand Up @@ -622,6 +628,12 @@ public void onDestroyView() {
delegate.onDestroyView();
}

@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
delegate.onSaveInstanceState(outState);
}

@Override
public void onDetach() {
super.onDetach();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import android.content.ContentProvider;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;

Expand Down Expand Up @@ -49,6 +50,8 @@ class FlutterEnginePluginRegistry implements PluginRegistry,

// Standard FlutterPlugin
@NonNull
private final FlutterEngine flutterEngine;
@NonNull
private final FlutterPlugin.FlutterPluginBinding pluginBinding;
@NonNull
private final FlutterEngineAndroidLifecycle flutterEngineAndroidLifecycle;
Expand Down Expand Up @@ -91,10 +94,14 @@ class FlutterEnginePluginRegistry implements PluginRegistry,
@NonNull FlutterEngine flutterEngine,
@NonNull FlutterEngineAndroidLifecycle lifecycle
) {
this.flutterEngine = flutterEngine;
flutterEngineAndroidLifecycle = lifecycle;
pluginBinding = new FlutterPlugin.FlutterPluginBinding(
appContext,
flutterEngine,
flutterEngine.getDartExecutor(),
flutterEngine.getRenderer(),
flutterEngine.getPlatformViewsController().getRegistry(),
lifecycle
);
}
Expand Down Expand Up @@ -288,16 +295,16 @@ public void attachToActivity(
detachFromAndroidComponent();

this.activity = activity;
this.activityPluginBinding = new FlutterEngineActivityPluginBinding(activity);
this.activityPluginBinding = new FlutterEngineActivityPluginBinding(activity, lifecycle);
this.flutterEngineAndroidLifecycle.setBackingLifecycle(lifecycle);

// Activate the PlatformViewsController. This must happen before any plugins attempt
// to use it, otherwise an error stack trace will appear that says there is no
// flutter/platform_views channel.
pluginBinding.getFlutterEngine().getPlatformViewsController().attach(
flutterEngine.getPlatformViewsController().attach(
activity,
pluginBinding.getFlutterEngine().getRenderer(),
pluginBinding.getFlutterEngine().getDartExecutor()
flutterEngine.getRenderer(),
flutterEngine.getDartExecutor()
);

// Notify all ActivityAware plugins that they are now attached to a new Activity.
Expand All @@ -322,7 +329,7 @@ public void detachFromActivityForConfigChanges() {
}

// Deactivate PlatformViewsController.
pluginBinding.getFlutterEngine().getPlatformViewsController().detach();
flutterEngine.getPlatformViewsController().detach();

flutterEngineAndroidLifecycle.setBackingLifecycle(null);
activity = null;
Expand All @@ -341,7 +348,7 @@ public void detachFromActivity() {
}

// Deactivate PlatformViewsController.
pluginBinding.getFlutterEngine().getPlatformViewsController().detach();
flutterEngine.getPlatformViewsController().detach();

flutterEngineAndroidLifecycle.setBackingLifecycle(null);
activity = null;
Expand Down Expand Up @@ -392,6 +399,26 @@ public void onUserLeaveHint() {
Log.e(TAG, "Attempted to notify ActivityAware plugins of onUserLeaveHint, but no Activity was attached.");
}
}

@Override
public void onSaveInstanceState(@NonNull Bundle bundle) {
Log.v(TAG, "Forwarding onSaveInstanceState() to plugins.");
if (isAttachedToActivity()) {
activityPluginBinding.onSaveInstanceState(bundle);
} else {
Log.e(TAG, "Attempted to notify ActivityAware plugins of onSaveInstanceState, but no Activity was attached.");
}
}

@Override
public void onRestoreInstanceState(@Nullable Bundle bundle) {
Log.v(TAG, "Forwarding onRestoreInstanceState() to plugins.");
if (isAttachedToActivity()) {
activityPluginBinding.onRestoreInstanceState(bundle);
} else {
Log.e(TAG, "Attempted to notify ActivityAware plugins of onRestoreInstanceState, but no Activity was attached.");
}
}
//------- End ActivityControlSurface -----

//----- Start ServiceControlSurface ----
Expand All @@ -400,13 +427,13 @@ private boolean isAttachedToService() {
}

@Override
public void attachToService(@NonNull Service service, @NonNull Lifecycle lifecycle, boolean isForeground) {
public void attachToService(@NonNull Service service, @Nullable Lifecycle lifecycle, boolean isForeground) {
Log.v(TAG, "Attaching to a Service: " + service);
// If we were already attached to an Android component, detach from it.
detachFromAndroidComponent();

this.service = service;
this.servicePluginBinding = new FlutterEngineServicePluginBinding(service);
this.servicePluginBinding = new FlutterEngineServicePluginBinding(service, lifecycle);
flutterEngineAndroidLifecycle.setBackingLifecycle(lifecycle);

// Notify all ServiceAware plugins that they are now attached to a new Service.
Expand Down Expand Up @@ -523,16 +550,21 @@ private static class FlutterEngineActivityPluginBinding implements ActivityPlugi
@NonNull
private final Activity activity;
@NonNull
private final Lifecycle lifecycle;
@NonNull
private final Set<io.flutter.plugin.common.PluginRegistry.RequestPermissionsResultListener> onRequestPermissionsResultListeners = new HashSet<>();
@NonNull
private final Set<io.flutter.plugin.common.PluginRegistry.ActivityResultListener> onActivityResultListeners = new HashSet<>();
@NonNull
private final Set<io.flutter.plugin.common.PluginRegistry.NewIntentListener> onNewIntentListeners = new HashSet<>();
@NonNull
private final Set<io.flutter.plugin.common.PluginRegistry.UserLeaveHintListener> onUserLeaveHintListeners = new HashSet<>();
@NonNull
private final Set<OnSaveInstanceStateListener> onSaveInstanceStateListeners = new HashSet<>();

public FlutterEngineActivityPluginBinding(@NonNull Activity activity) {
public FlutterEngineActivityPluginBinding(@NonNull Activity activity, @NonNull Lifecycle lifecycle) {
this.activity = activity;
this.lifecycle = lifecycle;
}

@Override
Expand All @@ -541,6 +573,12 @@ public Activity getActivity() {
return activity;
}

@NonNull
@Override
public Lifecycle getLifecycle() {
return lifecycle;
}

@Override
public void addRequestPermissionsResultListener(@NonNull io.flutter.plugin.common.PluginRegistry.RequestPermissionsResultListener listener) {
onRequestPermissionsResultListeners.add(listener);
Expand Down Expand Up @@ -615,6 +653,16 @@ public void removeOnUserLeaveHintListener(@NonNull io.flutter.plugin.common.Plug
onUserLeaveHintListeners.remove(listener);
}

@Override
public void addOnSaveStateListener(@NonNull OnSaveInstanceStateListener listener) {
onSaveInstanceStateListeners.add(listener);
}

@Override
public void removeOnSaveStateListener(@NonNull OnSaveInstanceStateListener listener) {
onSaveInstanceStateListeners.remove(listener);
}

/**
* Invoked by the {@link FlutterEngine} that owns this {@code ActivityPluginBinding} when its
* associated {@link Activity} has its {@code onUserLeaveHint()} method invoked.
Expand All @@ -624,16 +672,41 @@ void onUserLeaveHint() {
listener.onUserLeaveHint();
}
}

/**
* Invoked by the {@link FlutterEngine} that owns this {@code ActivityPluginBinding} when its
* associated {@link Activity} or {@code Fragment} has its {@code onSaveInstanceState(Bundle)}
* method invoked.
*/
void onSaveInstanceState(@NonNull Bundle bundle) {
for (OnSaveInstanceStateListener listener : onSaveInstanceStateListeners) {
listener.onSaveInstanceState(bundle);
}
}

/**
* Invoked by the {@link FlutterEngine} that owns this {@code ActivityPluginBinding} when its
* associated {@link Activity} has its {@code onCreate(Bundle)} method invoked, or its
* associated {@code Fragment} has its {@code onActivityCreated(Bundle)} method invoked.
*/
void onRestoreInstanceState(@Nullable Bundle bundle) {
for (OnSaveInstanceStateListener listener : onSaveInstanceStateListeners) {
listener.onRestoreInstanceState(bundle);
}
}
}

private static class FlutterEngineServicePluginBinding implements ServicePluginBinding {
@NonNull
private final Service service;
@Nullable
private final Lifecycle lifecycle;
@NonNull
private final Set<ServiceAware.OnModeChangeListener> onModeChangeListeners = new HashSet<>();

FlutterEngineServicePluginBinding(@NonNull Service service) {
FlutterEngineServicePluginBinding(@NonNull Service service, @Nullable Lifecycle lifecycle) {
this.service = service;
this.lifecycle = lifecycle;
}

@Override
Expand All @@ -642,6 +715,12 @@ public Service getService() {
return service;
}

@Nullable
@Override
public Lifecycle getLifecycle() {
return lifecycle;
}

@Override
public void addOnModeChangeListener(@NonNull ServiceAware.OnModeChangeListener listener) {
onModeChangeListeners.add(listener);
Expand Down
Loading