Skip to content

Commit

Permalink
Add auto plugin registration to FlutterFragmentActivity as well (flut…
Browse files Browse the repository at this point in the history
  • Loading branch information
xster authored Aug 31, 2020
1 parent 9398717 commit 5f49a95
Show file tree
Hide file tree
Showing 6 changed files with 110 additions and 34 deletions.
1 change: 1 addition & 0 deletions ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -754,6 +754,7 @@ FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/plugin
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/plugins/service/ServicePluginBinding.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/plugins/shim/ShimPluginRegistry.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/plugins/shim/ShimRegistrar.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/plugins/util/GeneratedPluginRegister.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/renderer/FlutterRenderer.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/renderer/FlutterUiDisplayListener.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/renderer/RenderSurface.java
Expand Down
1 change: 1 addition & 0 deletions shell/platform/android/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ android_java_sources = [
"io/flutter/embedding/engine/plugins/service/ServicePluginBinding.java",
"io/flutter/embedding/engine/plugins/shim/ShimPluginRegistry.java",
"io/flutter/embedding/engine/plugins/shim/ShimRegistrar.java",
"io/flutter/embedding/engine/plugins/util/GeneratedPluginRegister.java",
"io/flutter/embedding/engine/renderer/FlutterRenderer.java",
"io/flutter/embedding/engine/renderer/FlutterUiDisplayListener.java",
"io/flutter/embedding/engine/renderer/RenderSurface.java",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.embedding.engine.FlutterShellArgs;
import io.flutter.embedding.engine.plugins.activity.ActivityControlSurface;
import io.flutter.embedding.engine.plugins.util.GeneratedPluginRegister;
import io.flutter.plugin.platform.PlatformPlugin;
import io.flutter.view.FlutterMain;
import java.lang.reflect.Method;

/**
* {@code Activity} which displays a fullscreen Flutter UI.
Expand Down Expand Up @@ -872,7 +872,7 @@ public PlatformPlugin providePlatformPlugin(
*/
@Override
public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
registerPlugins(flutterEngine);
GeneratedPluginRegister.registerGeneratedPlugins(flutterEngine);
}

/**
Expand Down Expand Up @@ -962,34 +962,4 @@ public boolean shouldRestoreAndSaveState() {
}
return true;
}

/**
* Registers all plugins that an app lists in its pubspec.yaml.
*
* <p>The Flutter tool generates a class called GeneratedPluginRegistrant, which includes the code
* necessary to register every plugin in the pubspec.yaml with a given {@code FlutterEngine}. The
* GeneratedPluginRegistrant must be generated per app, because each app uses different sets of
* plugins. Therefore, the Android embedding cannot place a compile-time dependency on this
* generated class. This method uses reflection to attempt to locate the generated file and then
* use it at runtime.
*
* <p>This method fizzles if the GeneratedPluginRegistrant cannot be found or invoked. This
* situation should never occur, but if any eventuality comes up that prevents an app from using
* this behavior, that app can still write code that explicitly registers plugins.
*/
private static void registerPlugins(@NonNull FlutterEngine flutterEngine) {
try {
Class<?> generatedPluginRegistrant =
Class.forName("io.flutter.plugins.GeneratedPluginRegistrant");
Method registrationMethod =
generatedPluginRegistrant.getDeclaredMethod("registerWith", FlutterEngine.class);
registrationMethod.invoke(null, flutterEngine);
} catch (Exception e) {
Log.w(
TAG,
"Tried to automatically register plugins with FlutterEngine ("
+ flutterEngine
+ ") but could not find and invoke the GeneratedPluginRegistrant.");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import io.flutter.embedding.android.FlutterActivityLaunchConfigs.BackgroundMode;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.embedding.engine.FlutterShellArgs;
import io.flutter.embedding.engine.plugins.util.GeneratedPluginRegister;
import io.flutter.plugin.platform.PlatformPlugin;
import io.flutter.view.FlutterMain;

Expand Down Expand Up @@ -554,13 +555,18 @@ public FlutterEngine provideFlutterEngine(@NonNull Context context) {
}

/**
* Hook for subclasses to easily configure a {@code FlutterEngine}, e.g., register plugins.
* Hook for subclasses to easily configure a {@code FlutterEngine}.
*
* <p>This method is called after {@link #provideFlutterEngine(Context)}.
*
* <p>All plugins listed in the app's pubspec are registered in the base implementation of this
* method. To avoid automatic plugin registration, override this method without invoking super().
* To keep automatic plugin registration and further configure the flutterEngine, override this
* method, invoke super(), and then configure the flutterEngine as desired.
*/
@Override
public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
// No-op. Hook for subclasses.
GeneratedPluginRegister.registerGeneratedPlugins(flutterEngine);
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package io.flutter.embedding.engine.plugins.util;

import androidx.annotation.NonNull;
import io.flutter.Log;
import io.flutter.embedding.engine.FlutterEngine;
import java.lang.reflect.Method;

public class GeneratedPluginRegister {
private static final String TAG = "GeneratedPluginsRegister";
/**
* Registers all plugins that an app lists in its pubspec.yaml.
*
* <p>The Flutter tool generates a class called GeneratedPluginRegistrant, which includes the code
* necessary to register every plugin in the pubspec.yaml with a given {@code FlutterEngine}. The
* GeneratedPluginRegistrant must be generated per app, because each app uses different sets of
* plugins. Therefore, the Android embedding cannot place a compile-time dependency on this
* generated class. This method uses reflection to attempt to locate the generated file and then
* use it at runtime.
*
* <p>This method fizzles if the GeneratedPluginRegistrant cannot be found or invoked. This
* situation should never occur, but if any eventuality comes up that prevents an app from using
* this behavior, that app can still write code that explicitly registers plugins.
*/
public static void registerGeneratedPlugins(@NonNull FlutterEngine flutterEngine) {
try {
Class<?> generatedPluginRegistrant =
Class.forName("io.flutter.plugins.GeneratedPluginRegistrant");
Method registrationMethod =
generatedPluginRegistrant.getDeclaredMethod("registerWith", FlutterEngine.class);
registrationMethod.invoke(null, flutterEngine);
} catch (Exception e) {
Log.w(
TAG,
"Tried to automatically register plugins with FlutterEngine ("
+ flutterEngine
+ ") but could not find and invoke the GeneratedPluginRegistrant.");
}
}
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,40 @@
package io.flutter.embedding.android;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import android.content.Context;
import android.content.Intent;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import io.flutter.embedding.android.FlutterActivityLaunchConfigs.BackgroundMode;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.embedding.engine.FlutterJNI;
import io.flutter.embedding.engine.loader.FlutterLoader;
import io.flutter.plugins.GeneratedPluginRegistrant;
import java.util.List;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;

@Config(manifest = Config.NONE)
@RunWith(RobolectricTestRunner.class)
public class FlutterFragmentActivityTest {
@Before
public void setUp() {
GeneratedPluginRegistrant.clearRegisteredEngines();
}

@After
public void tearDown() {
GeneratedPluginRegistrant.clearRegisteredEngines();
}

@Test
public void createFlutterFragment__defaultRenderModeSurface() {
Expand Down Expand Up @@ -44,6 +66,39 @@ protected RenderMode getRenderMode() {
assertEquals(activity.createFlutterFragment().getRenderMode(), RenderMode.texture);
}

@Test
public void itRegistersPluginsAtConfigurationTime() {
FlutterFragmentActivity activity =
Robolectric.buildActivity(FlutterFragmentActivityWithProvidedEngine.class).get();
assertTrue(GeneratedPluginRegistrant.getRegisteredEngines().isEmpty());

// Calling onCreate on the FlutterFragmentActivity will create a FlutterFragment and
// commit it to the fragment manager. This attaches the fragment to the FlutterFragmentActivity
// creating and configuring the engine.
activity.onCreate(null);

List<FlutterEngine> registeredEngines = GeneratedPluginRegistrant.getRegisteredEngines();
assertEquals(1, registeredEngines.size());
assertEquals(activity.getFlutterEngine(), registeredEngines.get(0));
}

static class FlutterFragmentActivityWithProvidedEngine extends FlutterFragmentActivity {
@Override
protected FlutterFragment createFlutterFragment() {
return FlutterFragment.createDefault();
}

@Nullable
@Override
public FlutterEngine provideFlutterEngine(@NonNull Context context) {
FlutterJNI flutterJNI = mock(FlutterJNI.class);
when(flutterJNI.isAttached()).thenReturn(true);

return new FlutterEngine(
context, mock(FlutterLoader.class), flutterJNI, new String[] {}, false);
}
}

private static class FakeFlutterFragmentActivity extends FlutterFragmentActivity {
@Override
public Intent getIntent() {
Expand Down

0 comments on commit 5f49a95

Please sign in to comment.