Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 00db306

Browse files
Reverts "Bump minSdk to 19 for Android tests" (#47935)
Reverts #47686 Initiated by: zanderso This change reverts the following previous change: Original Description: The latest Robolectric version, 4.11.x, removed the support for SDKs < 19 by following AndroidX strategy. Also following flutter/buildroot#750, and removing obsolete SDK checking in code to pass android_lint checking after bumping minSdk to 19 for testing target. [C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
1 parent 28d9146 commit 00db306

18 files changed

+212
-88
lines changed

shell/platform/android/AndroidManifest.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
-->
66
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="io.flutter.app" android:versionCode="1" android:versionName="0.0.1">
77

8-
<uses-sdk android:minSdkVersion="19" android:targetSdkVersion="34" />
8+
<uses-sdk android:minSdkVersion="16" android:targetSdkVersion="34" />
99
<uses-permission android:name="android.permission.INTERNET" />
1010
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
1111
<uses-feature android:name="android.hardware.sensor.accelerometer" android:required="true" />

shell/platform/android/io/flutter/embedding/android/AndroidTouchProcessor.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,9 @@ public boolean onTouchEvent(@NonNull MotionEvent event, @NonNull Matrix transfor
198198
public boolean onGenericMotionEvent(@NonNull MotionEvent event, @NonNull Context context) {
199199
// Method isFromSource is only available in API 18+ (Jelly Bean MR2)
200200
// Mouse hover support is not implemented for API < 18.
201-
boolean isPointerEvent = event.isFromSource(InputDevice.SOURCE_CLASS_POINTER);
201+
boolean isPointerEvent =
202+
Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2
203+
&& event.isFromSource(InputDevice.SOURCE_CLASS_POINTER);
202204
boolean isMovementEvent =
203205
(event.getActionMasked() == MotionEvent.ACTION_HOVER_MOVE
204206
|| event.getActionMasked() == MotionEvent.ACTION_SCROLL);

shell/platform/android/io/flutter/embedding/android/FlutterFragment.java

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import android.content.ComponentCallbacks2;
99
import android.content.Context;
1010
import android.content.Intent;
11+
import android.os.Build;
1112
import android.os.Bundle;
1213
import android.view.LayoutInflater;
1314
import android.view.View;
@@ -171,14 +172,16 @@ public class FlutterFragment extends Fragment
171172

172173
@RequiresApi(18)
173174
private final OnWindowFocusChangeListener onWindowFocusChangeListener =
174-
new OnWindowFocusChangeListener() {
175-
@Override
176-
public void onWindowFocusChanged(boolean hasFocus) {
177-
if (stillAttachedForEvent("onWindowFocusChanged")) {
178-
delegate.onWindowFocusChanged(hasFocus);
175+
Build.VERSION.SDK_INT >= 18
176+
? new OnWindowFocusChangeListener() {
177+
@Override
178+
public void onWindowFocusChanged(boolean hasFocus) {
179+
if (stillAttachedForEvent("onWindowFocusChanged")) {
180+
delegate.onWindowFocusChanged(hasFocus);
181+
}
182+
}
179183
}
180-
}
181-
};
184+
: null;
182185

183186
/**
184187
* Creates a {@code FlutterFragment} with a default configuration.
@@ -1125,16 +1128,20 @@ public void onStop() {
11251128
@Override
11261129
public void onViewCreated(View view, Bundle savedInstanceState) {
11271130
super.onViewCreated(view, savedInstanceState);
1128-
view.getViewTreeObserver().addOnWindowFocusChangeListener(onWindowFocusChangeListener);
1131+
if (Build.VERSION.SDK_INT >= 18) {
1132+
view.getViewTreeObserver().addOnWindowFocusChangeListener(onWindowFocusChangeListener);
1133+
}
11291134
}
11301135

11311136
@Override
11321137
public void onDestroyView() {
11331138
super.onDestroyView();
1134-
// onWindowFocusChangeListener is API 18+ only.
1135-
requireView()
1136-
.getViewTreeObserver()
1137-
.removeOnWindowFocusChangeListener(onWindowFocusChangeListener);
1139+
if (Build.VERSION.SDK_INT >= 18) {
1140+
// onWindowFocusChangeListener is API 18+ only.
1141+
requireView()
1142+
.getViewTreeObserver()
1143+
.removeOnWindowFocusChangeListener(onWindowFocusChangeListener);
1144+
}
11381145
if (stillAttachedForEvent("onDestroyView")) {
11391146
delegate.onDestroyView();
11401147
}

shell/platform/android/io/flutter/embedding/android/FlutterImageView.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
* an {@link android.media.Image} and renders it to the {@link android.graphics.Canvas} in {@code
4040
* onDraw}.
4141
*/
42+
@TargetApi(19)
4243
public class FlutterImageView extends View implements RenderSurface {
4344
private static final String TAG = "FlutterImageView";
4445

@@ -98,6 +99,7 @@ private static void logW(String format, Object... args) {
9899
Log.w(TAG, String.format(Locale.US, format, args));
99100
}
100101

102+
@TargetApi(19)
101103
@SuppressLint("WrongConstant") // RGBA_8888 is a valid constant.
102104
@NonNull
103105
private static ImageReader createImageReader(int width, int height) {
@@ -192,6 +194,7 @@ public void resume() {
192194
* Acquires the next image to be drawn to the {@link android.graphics.Canvas}. Returns true if
193195
* there's an image available in the queue.
194196
*/
197+
@TargetApi(19)
195198
public boolean acquireLatestImage() {
196199
if (!isAttachedToFlutterRenderer) {
197200
return false;

shell/platform/android/io/flutter/embedding/android/FlutterView.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,7 @@ public FlutterView(@NonNull Context context, @NonNull FlutterTextureView flutter
290290
* <p>{@code FlutterView} requires an {@code Activity} instead of a generic {@code Context} to be
291291
* compatible with {@link PlatformViewsController}.
292292
*/
293+
@TargetApi(19)
293294
public FlutterView(@NonNull Context context, @NonNull FlutterImageView flutterImageView) {
294295
this(context, null, flutterImageView);
295296
}
@@ -356,6 +357,7 @@ private FlutterView(
356357
init();
357358
}
358359

360+
@TargetApi(19)
359361
private FlutterView(
360362
@NonNull Context context,
361363
@Nullable AttributeSet attrs,

shell/platform/android/io/flutter/embedding/engine/loader/FlutterLoader.java

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import android.os.Looper;
1717
import android.os.SystemClock;
1818
import android.util.DisplayMetrics;
19+
import android.view.WindowManager;
1920
import androidx.annotation.NonNull;
2021
import androidx.annotation.Nullable;
2122
import io.flutter.BuildConfig;
@@ -169,9 +170,17 @@ public void startInitialization(@NonNull Context applicationContext, @NonNull Se
169170
flutterApplicationInfo = ApplicationInfoLoader.load(appContext);
170171

171172
VsyncWaiter waiter;
172-
final DisplayManager dm =
173-
(DisplayManager) appContext.getSystemService(Context.DISPLAY_SERVICE);
174-
waiter = VsyncWaiter.getInstance(dm, flutterJNI);
173+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 /* 17 */) {
174+
final DisplayManager dm =
175+
(DisplayManager) appContext.getSystemService(Context.DISPLAY_SERVICE);
176+
waiter = VsyncWaiter.getInstance(dm, flutterJNI);
177+
} else {
178+
float fps =
179+
((WindowManager) appContext.getSystemService(Context.WINDOW_SERVICE))
180+
.getDefaultDisplay()
181+
.getRefreshRate();
182+
waiter = VsyncWaiter.getInstance(fps, flutterJNI);
183+
}
175184
waiter.init();
176185

177186
// Use a background thread for initialization tasks that require disk access.

shell/platform/android/io/flutter/embedding/engine/mutatorsstack/FlutterMutatorView.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import static android.view.View.OnFocusChangeListener;
44

55
import android.annotation.SuppressLint;
6+
import android.annotation.TargetApi;
67
import android.content.Context;
78
import android.graphics.Canvas;
89
import android.graphics.Matrix;
@@ -22,6 +23,7 @@
2223
* A view that applies the {@link io.flutter.embedding.engine.mutatorsstack.FlutterMutatorsStack} to
2324
* its children.
2425
*/
26+
@TargetApi(19)
2527
public class FlutterMutatorView extends FrameLayout {
2628
private FlutterMutatorsStack mutatorsStack;
2729
private float screenDensity;

shell/platform/android/io/flutter/embedding/engine/renderer/FlutterRenderer.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,7 @@ public long id() {
355355
}
356356

357357
@Override
358+
@TargetApi(19)
358359
public void release() {
359360
if (released) {
360361
return;
@@ -368,6 +369,7 @@ public void release() {
368369
}
369370

370371
@Override
372+
@TargetApi(19)
371373
public void pushImage(Image image) {
372374
if (released) {
373375
return;
@@ -431,6 +433,7 @@ public Image acquireLatestImage() {
431433
}
432434

433435
@Override
436+
@TargetApi(19)
434437
protected void finalize() throws Throwable {
435438
try {
436439
if (released) {

shell/platform/android/io/flutter/plugin/localization/LocalizationPlugin.java

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import android.annotation.SuppressLint;
88
import android.content.Context;
99
import android.content.res.Configuration;
10+
import android.content.res.Resources;
1011
import android.os.Build;
1112
import android.os.LocaleList;
1213
import androidx.annotation.NonNull;
@@ -39,9 +40,18 @@ public String getStringResource(@NonNull String key, @Nullable String localeStri
3940
Locale locale = localeFromString(localeString);
4041

4142
// setLocale and createConfigurationContext is only available on API >= 17
42-
Configuration config = new Configuration(context.getResources().getConfiguration());
43-
config.setLocale(locale);
44-
localContext = context.createConfigurationContext(config);
43+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
44+
Configuration config = new Configuration(context.getResources().getConfiguration());
45+
config.setLocale(locale);
46+
localContext = context.createConfigurationContext(config);
47+
} else {
48+
// In API < 17, we have to update the locale in Configuration.
49+
Resources resources = context.getResources();
50+
Configuration config = resources.getConfiguration();
51+
savedLocale = config.locale;
52+
config.locale = locale;
53+
resources.updateConfiguration(config, null);
54+
}
4555
}
4656

4757
String packageName = context.getPackageName();
@@ -51,6 +61,14 @@ public String getStringResource(@NonNull String key, @Nullable String localeStri
5161
stringToReturn = localContext.getResources().getString(resId);
5262
}
5363

64+
// In API < 17, we had to restore the original locale after using.
65+
if (localeString != null && Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
66+
Resources resources = context.getResources();
67+
Configuration config = resources.getConfiguration();
68+
config.locale = savedLocale;
69+
resources.updateConfiguration(config, null);
70+
}
71+
5472
return stringToReturn;
5573
}
5674
};

shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,8 @@ private void setSystemChromeEnabledSystemUIMode(PlatformChannel.SystemUiMode sys
282282
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
283283
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
284284
| View.SYSTEM_UI_FLAG_FULLSCREEN;
285-
} else if (systemUiMode == PlatformChannel.SystemUiMode.IMMERSIVE) {
285+
} else if (systemUiMode == PlatformChannel.SystemUiMode.IMMERSIVE
286+
&& Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
286287
// IMMERSIVE
287288
// Available starting at 19
288289
// Should not show overlays, swipe from edges to reveal overlays, needs onChange callback
@@ -297,7 +298,8 @@ private void setSystemChromeEnabledSystemUIMode(PlatformChannel.SystemUiMode sys
297298
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
298299
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
299300
| View.SYSTEM_UI_FLAG_FULLSCREEN;
300-
} else if (systemUiMode == PlatformChannel.SystemUiMode.IMMERSIVE_STICKY) {
301+
} else if (systemUiMode == PlatformChannel.SystemUiMode.IMMERSIVE_STICKY
302+
&& Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
301303
// STICKY IMMERSIVE
302304
// Available starting at 19
303305
// Should not show overlays, swipe from edges to reveal overlays. The app will also receive
@@ -344,7 +346,7 @@ private void setSystemChromeEnabledSystemUIOverlays(
344346
// The SYSTEM_UI_FLAG_IMMERSIVE_STICKY flag was introduced in API 19, so we
345347
// apply it
346348
// if desired, and if the current Android version is 19 or greater.
347-
if (overlaysToShow.size() == 0) {
349+
if (overlaysToShow.size() == 0 && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
348350
enabledOverlays |= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
349351
}
350352

0 commit comments

Comments
 (0)