Skip to content

Commit

Permalink
Send locales to Flutter in FlutterEngine initialization instead of Fl…
Browse files Browse the repository at this point in the history
…utterView (flutter#34243)
  • Loading branch information
GaryQian authored Jun 28, 2022
1 parent 6301c5c commit 8f07aeb
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1210,7 +1210,6 @@ public void attachToFlutterEngine(@NonNull FlutterEngine flutterEngine) {
false,
systemSettingsObserver);

localizationPlugin.sendLocalesToFlutter(getResources().getConfiguration());
sendViewportMetricsToFlutter();

flutterEngine.getPlatformViewsController().attachToView(this);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,8 @@ public FlutterEngine(
this.pluginRegistry =
new FlutterEngineConnectionRegistry(context.getApplicationContext(), this, flutterLoader);

localizationPlugin.sendLocalesToFlutter(context.getResources().getConfiguration());

// Only automatically register plugins if both constructor parameter and
// loaded AndroidManifest config turn this feature on.
if (automaticallyRegisterPlugins && flutterLoader.automaticallyRegisterPlugins()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
Expand All @@ -15,6 +17,9 @@

import android.content.Context;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.LocaleList;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import io.flutter.FlutterInjector;
Expand All @@ -41,12 +46,20 @@
@RunWith(AndroidJUnit4.class)
public class FlutterEngineTest {
private final Context ctx = ApplicationProvider.getApplicationContext();
private final Context mockContext = mock(Context.class);
@Mock FlutterJNI flutterJNI;
boolean jniAttached;

@Before
public void setUp() {
MockitoAnnotations.openMocks(this);

Resources mockResources = mock(Resources.class);
Configuration mockConfiguration = mock(Configuration.class);
doReturn(mockResources).when(mockContext).getResources();
doReturn(mockConfiguration).when(mockResources).getConfiguration();
doReturn(LocaleList.getEmptyLocaleList()).when(mockConfiguration).getLocales();

jniAttached = false;
when(flutterJNI.isAttached()).thenAnswer(invocation -> jniAttached);
doAnswer(
Expand Down Expand Up @@ -82,6 +95,20 @@ public void itAutomaticallyRegistersPluginsByDefault() {
assertEquals(flutterEngine, registeredEngines.get(0));
}

@Test
public void itSendLocalesOnEngineInit() {
FlutterJNI mockFlutterJNI = mock(FlutterJNI.class);
when(mockFlutterJNI.isAttached()).thenReturn(true);

assertTrue(GeneratedPluginRegistrant.getRegisteredEngines().isEmpty());
FlutterLoader mockFlutterLoader = mock(FlutterLoader.class);
when(mockFlutterLoader.automaticallyRegisterPlugins()).thenReturn(true);
FlutterEngine flutterEngine = new FlutterEngine(ctx, mockFlutterLoader, mockFlutterJNI);

verify(mockFlutterJNI, times(1))
.dispatchPlatformMessage(eq("flutter/localization"), any(), anyInt(), anyInt());
}

// Helps show the root cause of MissingPluginException type errors like
// https://github.com/flutter/flutter/issues/78625.
@Test
Expand Down Expand Up @@ -194,36 +221,34 @@ public void itNotifiesPlatformViewsControllerAboutJNILifecycle() {

@Test
public void itUsesApplicationContext() throws NameNotFoundException {
Context context = mock(Context.class);
Context packageContext = mock(Context.class);

when(context.createPackageContext(any(), anyInt())).thenReturn(packageContext);
when(mockContext.createPackageContext(any(), anyInt())).thenReturn(packageContext);

new FlutterEngine(
context,
mockContext,
mock(FlutterLoader.class),
flutterJNI,
/*dartVmArgs=*/ new String[] {},
/*automaticallyRegisterPlugins=*/ false);

verify(context, atLeast(1)).getApplicationContext();
verify(mockContext, atLeast(1)).getApplicationContext();
}

@Test
public void itUsesPackageContextForAssetManager() throws NameNotFoundException {
Context context = mock(Context.class);
Context packageContext = mock(Context.class);
when(context.createPackageContext(any(), anyInt())).thenReturn(packageContext);
when(mockContext.createPackageContext(any(), anyInt())).thenReturn(packageContext);

new FlutterEngine(
context,
mockContext,
mock(FlutterLoader.class),
flutterJNI,
/*dartVmArgs=*/ new String[] {},
/*automaticallyRegisterPlugins=*/ false);

verify(packageContext, atLeast(1)).getAssets();
verify(context, times(0)).getAssets();
verify(mockContext, times(0)).getAssets();
}

@Test
Expand All @@ -232,7 +257,6 @@ public void itCanUseFlutterLoaderInjectionViaFlutterInjector() throws NameNotFou
FlutterLoader mockFlutterLoader = mock(FlutterLoader.class);
FlutterInjector.setInstance(
new FlutterInjector.Builder().setFlutterLoader(mockFlutterLoader).build());
Context mockContext = mock(Context.class);
Context packageContext = mock(Context.class);

when(mockContext.createPackageContext(any(), anyInt())).thenReturn(packageContext);
Expand All @@ -246,14 +270,13 @@ public void itCanUseFlutterLoaderInjectionViaFlutterInjector() throws NameNotFou

@Test
public void itNotifiesListenersForDestruction() throws NameNotFoundException {
Context context = mock(Context.class);
Context packageContext = mock(Context.class);

when(context.createPackageContext(any(), anyInt())).thenReturn(packageContext);
when(mockContext.createPackageContext(any(), anyInt())).thenReturn(packageContext);

FlutterEngine engineUnderTest =
new FlutterEngine(
context,
mockContext,
mock(FlutterLoader.class),
flutterJNI,
/*dartVmArgs=*/ new String[] {},
Expand All @@ -267,15 +290,14 @@ public void itNotifiesListenersForDestruction() throws NameNotFoundException {

@Test
public void itDoesNotAttachAgainWhenBuiltWithAnAttachedJNI() throws NameNotFoundException {
Context context = mock(Context.class);
Context packageContext = mock(Context.class);

when(context.createPackageContext(any(), anyInt())).thenReturn(packageContext);
when(mockContext.createPackageContext(any(), anyInt())).thenReturn(packageContext);
when(flutterJNI.isAttached()).thenReturn(true);

FlutterEngine engineUnderTest =
new FlutterEngine(
context,
mockContext,
mock(FlutterLoader.class),
flutterJNI,
/*dartVmArgs=*/ new String[] {},
Expand All @@ -286,15 +308,14 @@ public void itDoesNotAttachAgainWhenBuiltWithAnAttachedJNI() throws NameNotFound

@Test
public void itComesWithARunningDartExecutorIfJNIIsAlreadyAttached() throws NameNotFoundException {
Context context = mock(Context.class);
Context packageContext = mock(Context.class);

when(context.createPackageContext(any(), anyInt())).thenReturn(packageContext);
when(mockContext.createPackageContext(any(), anyInt())).thenReturn(packageContext);
when(flutterJNI.isAttached()).thenReturn(true);

FlutterEngine engineUnderTest =
new FlutterEngine(
context,
mockContext,
mock(FlutterLoader.class),
flutterJNI,
/*dartVmArgs=*/ new String[] {},
Expand Down

0 comments on commit 8f07aeb

Please sign in to comment.