Update Engine to Android 16 (API 36) (#166796)

Following the directions
[here](https://github.com/flutter/flutter/blob/main/docs/platforms/android/Upgrading-Engine's-Android-API-version.md)
to update engine to android 16.

1. Uploaded api 36 SDK to CIPD using the script from the above docs
2. Updates in Engine to use api 36
     - Updated buildroot
     - Updated SDK CIPD package in `DEPS`
     - Updated android build tools
     - Updated `targetsdk` and `compilesdk`
3. Confirm the engine sucessfully builds. I ran `et build -c
android_debug_unopt_arm64`
4. Bumped the gradle version in this PR due to seeing this warning
[here](https://github.com/flutter/flutter/blob/master/docs/platforms/android/New-Android-version.md#:~:text=Update%20Gradle/AGP%20support).

Note: Post mono-repo merge, we can now update buildroot and `DEPS` in
the same PR 🎊 !!! Also, updated the Clang path due to use of a new Clang
version in the bumped ndk.

Partially Addresses #166950

## Pre-launch Checklist

- [x] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [x] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [x] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [x] I signed the [CLA].
- [x] I listed at least one issue that this PR fixes in the description
above.
- [x] I updated/added relevant documentation (doc comments with `///`).
- [x] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [x] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [x] All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel
on [Discord].

<!-- Links -->
[Contributor Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview
[Tree Hygiene]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md
[test-exempt]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests
[Flutter Style Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md
[Features we expect every widget to implement]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement
[CLA]: https://cla.developers.google.com/
[flutter/tests]: https://github.com/flutter/tests
[breaking change policy]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes
[Discord]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md
[Data Driven Fixes]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
This commit is contained in:
jesswrd 2025-05-08 12:46:59 -07:00 committed by GitHub
parent 5041a592c8
commit f8b544a7ff
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
36 changed files with 101 additions and 118 deletions

4
DEPS
View File

@ -574,7 +574,7 @@ deps = {
{
# See tools/gradle/README.md for update instructions.
# Version here means the CIPD tag.
'version': 'version:8.9',
'version': 'version:8.11.1',
'package': 'flutter/gradle'
}
],
@ -614,7 +614,7 @@ deps = {
'packages': [
{
'package': 'flutter/android/sdk/all/${{platform}}',
'version': 'version:35v1'
'version': 'version:36v1'
}
],
'condition': 'download_android_deps',

View File

@ -7,8 +7,8 @@
if (is_android) {
if (!defined(default_android_sdk_root)) {
default_android_sdk_root = "//flutter/third_party/android_tools/sdk"
default_android_sdk_version = "35"
default_android_sdk_build_tools_version = "35.0.0-rc4"
default_android_sdk_version = "36"
default_android_sdk_build_tools_version = "36.0.0"
}
declare_args() {

View File

@ -583,7 +583,7 @@ config("runtime_library") {
"m",
]
lib_dirs += [ "${android_toolchain_root}/lib/clang/17/lib/linux/" ]
lib_dirs += [ "${android_toolchain_root}/lib/clang/18/lib/linux/" ]
current_android_cpu = current_cpu
if (current_cpu == "arm64") {
current_android_cpu = "aarch64"

View File

@ -5,7 +5,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="io.flutter.embedding" android:versionCode="1" android:versionName="0.0.1">
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="35" />
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="36" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-feature android:name="android.hardware.sensor.accelerometer" android:required="true" />

View File

@ -8,7 +8,7 @@ buildscript {
mavenCentral()
}
dependencies {
classpath "com.android.tools.build:gradle:8.7.2"
classpath "com.android.tools.build:gradle:8.9.1"
}
}
@ -21,7 +21,7 @@ apply plugin: "com.android.library"
android {
namespace "io.flutter.embedding"
compileSdk 35
compileSdk 36
defaultConfig {
minSdkVersion 21

View File

@ -2,7 +2,6 @@ package io.flutter.embedding.android;
import static io.flutter.Build.API_LEVELS;
import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Matrix;
import android.os.Build;
@ -12,6 +11,7 @@ import android.view.MotionEvent;
import android.view.ViewConfiguration;
import androidx.annotation.IntDef;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.annotation.VisibleForTesting;
import io.flutter.embedding.engine.renderer.FlutterRenderer;
import java.nio.ByteBuffer;
@ -465,7 +465,7 @@ public class AndroidTouchProcessor {
}
}
@TargetApi(API_LEVELS.API_26)
@RequiresApi(API_LEVELS.API_26)
private float getVerticalScrollFactorAbove26(@NonNull Context context) {
return ViewConfiguration.get(context).getScaledVerticalScrollFactor();
}

View File

@ -22,7 +22,6 @@ import static io.flutter.embedding.android.FlutterActivityLaunchConfigs.INITIAL_
import static io.flutter.embedding.android.FlutterActivityLaunchConfigs.NORMAL_THEME_META_DATA_KEY;
import static io.flutter.embedding.android.FlutterActivityLaunchConfigs.deepLinkEnabled;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
@ -698,7 +697,6 @@ public class FlutterActivity extends Activity
}
@NonNull
@TargetApi(API_LEVELS.API_33)
@RequiresApi(API_LEVELS.API_33)
private OnBackInvokedCallback createOnBackInvokedCallback() {
if (Build.VERSION.SDK_INT >= API_LEVELS.API_34) {
@ -942,7 +940,6 @@ public class FlutterActivity extends Activity
}
}
@TargetApi(API_LEVELS.API_34)
@RequiresApi(API_LEVELS.API_34)
public void startBackGesture(@NonNull BackEvent backEvent) {
if (stillAttachedForEvent("startBackGesture")) {
@ -950,7 +947,6 @@ public class FlutterActivity extends Activity
}
}
@TargetApi(API_LEVELS.API_34)
@RequiresApi(API_LEVELS.API_34)
public void updateBackGestureProgress(@NonNull BackEvent backEvent) {
if (stillAttachedForEvent("updateBackGestureProgress")) {
@ -958,7 +954,6 @@ public class FlutterActivity extends Activity
}
}
@TargetApi(API_LEVELS.API_34)
@RequiresApi(API_LEVELS.API_34)
public void commitBackGesture() {
if (stillAttachedForEvent("commitBackGesture")) {
@ -966,7 +961,6 @@ public class FlutterActivity extends Activity
}
}
@TargetApi(API_LEVELS.API_34)
@RequiresApi(API_LEVELS.API_34)
public void cancelBackGesture() {
if (stillAttachedForEvent("cancelBackGesture")) {

View File

@ -7,7 +7,6 @@ package io.flutter.embedding.android;
import static android.content.ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW;
import static io.flutter.embedding.android.FlutterActivityLaunchConfigs.DEFAULT_INITIAL_ROUTE;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.ComponentCallbacks2;
import android.content.Context;
@ -821,7 +820,6 @@ import java.util.List;
*
* @param backEvent The BackEvent object containing information about the touch.
*/
@TargetApi(API_LEVELS.API_34)
@RequiresApi(API_LEVELS.API_34)
void startBackGesture(@NonNull BackEvent backEvent) {
ensureAlive();
@ -844,7 +842,6 @@ import java.util.List;
*
* @param backEvent An BackEvent object describing the progress event.
*/
@TargetApi(API_LEVELS.API_34)
@RequiresApi(API_LEVELS.API_34)
void updateBackGestureProgress(@NonNull BackEvent backEvent) {
ensureAlive();
@ -869,7 +866,6 @@ import java.util.List;
* navigation, including finalizing animations and updating the UI to reflect the navigation
* outcome.
*/
@TargetApi(API_LEVELS.API_34)
@RequiresApi(API_LEVELS.API_34)
void commitBackGesture() {
ensureAlive();
@ -891,7 +887,6 @@ import java.util.List;
* in response to the back gesture. This includes resetting UI elements to their state prior to
* the gesture's start.
*/
@TargetApi(API_LEVELS.API_34)
@RequiresApi(API_LEVELS.API_34)
void cancelBackGesture() {
ensureAlive();

View File

@ -7,7 +7,6 @@ package io.flutter.embedding.android;
import static io.flutter.Build.API_LEVELS;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
@ -15,7 +14,6 @@ import android.graphics.ColorSpace;
import android.graphics.PixelFormat;
import android.hardware.HardwareBuffer;
import android.media.Image;
import android.media.Image.Plane;
import android.media.ImageReader;
import android.util.AttributeSet;
import android.view.Surface;
@ -253,19 +251,18 @@ public class FlutterImageView extends View implements RenderSurface {
}
}
@TargetApi(API_LEVELS.API_29)
private void updateCurrentBitmap() {
if (android.os.Build.VERSION.SDK_INT >= API_LEVELS.API_29) {
final HardwareBuffer buffer = currentImage.getHardwareBuffer();
currentBitmap = Bitmap.wrapHardwareBuffer(buffer, ColorSpace.get(ColorSpace.Named.SRGB));
buffer.close();
} else {
final Plane[] imagePlanes = currentImage.getPlanes();
final Image.Plane[] imagePlanes = currentImage.getPlanes();
if (imagePlanes.length != 1) {
return;
}
final Plane imagePlane = imagePlanes[0];
final Image.Plane imagePlane = imagePlanes[0];
final int desiredWidth = imagePlane.getRowStride() / imagePlane.getPixelStride();
final int desiredHeight = currentImage.getHeight();

View File

@ -7,7 +7,6 @@ package io.flutter.embedding.android;
import static io.flutter.Build.API_LEVELS;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.content.res.Configuration;
@ -537,7 +536,7 @@ public class FlutterView extends FrameLayout
* Refresh {@link androidx.window.layout.WindowInfoTracker} and {@link android.view.DisplayCutout}
* display features. Fold, hinge and cutout areas are populated here.
*/
@TargetApi(API_LEVELS.API_28)
@RequiresApi(API_LEVELS.API_28)
protected void setWindowInfoListenerDisplayFeatures(WindowLayoutInfo layoutInfo) {
List<DisplayFeature> newDisplayFeatures = layoutInfo.getDisplayFeatures();
List<FlutterRenderer.DisplayFeature> flutterDisplayFeatures = new ArrayList<>();
@ -1048,7 +1047,6 @@ public class FlutterView extends FrameLayout
// -------- Start: Mouse -------
@Override
@TargetApi(API_LEVELS.API_24)
@RequiresApi(API_LEVELS.API_24)
@NonNull
public PointerIcon getSystemPointerIcon(int type) {

View File

@ -6,7 +6,6 @@ package io.flutter.embedding.engine.renderer;
import static io.flutter.Build.API_LEVELS;
import android.annotation.TargetApi;
import android.content.ComponentCallbacks2;
import android.graphics.Bitmap;
import android.graphics.ImageFormat;
@ -23,6 +22,7 @@ import android.view.Surface;
import androidx.annotation.Keep;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.annotation.VisibleForTesting;
import androidx.lifecycle.DefaultLifecycleObserver;
import androidx.lifecycle.LifecycleOwner;
@ -408,7 +408,6 @@ public class FlutterRenderer implements TextureRegistry {
// When we acquire the next image, close any ImageReaders that don't have any
// more pending images.
@Keep
@TargetApi(API_LEVELS.API_29)
final class ImageReaderSurfaceProducer
implements TextureRegistry.SurfaceProducer,
TextureRegistry.ImageConsumer,
@ -741,7 +740,7 @@ public class FlutterRenderer implements TextureRegistry {
}
}
@TargetApi(API_LEVELS.API_33)
@RequiresApi(API_LEVELS.API_33)
private void waitOnFence(Image image) {
try {
SyncFence fence = image.getFence();
@ -844,7 +843,7 @@ public class FlutterRenderer implements TextureRegistry {
}
@Override
@TargetApi(API_LEVELS.API_29)
@RequiresApi(API_LEVELS.API_29)
public Image acquireLatestImage() {
PerImage r = dequeueImage();
if (r == null) {
@ -883,7 +882,7 @@ public class FlutterRenderer implements TextureRegistry {
}
}
@TargetApi(API_LEVELS.API_33)
@RequiresApi(API_LEVELS.API_33)
private ImageReader createImageReader33() {
final ImageReader.Builder builder = new ImageReader.Builder(requestedWidth, requestedHeight);
// Allow for double buffering.
@ -900,7 +899,7 @@ public class FlutterRenderer implements TextureRegistry {
return builder.build();
}
@TargetApi(API_LEVELS.API_29)
@RequiresApi(API_LEVELS.API_29)
private ImageReader createImageReader29() {
return ImageReader.newInstance(
requestedWidth,
@ -1008,7 +1007,7 @@ public class FlutterRenderer implements TextureRegistry {
}
}
@TargetApi(API_LEVELS.API_33)
@RequiresApi(API_LEVELS.API_33)
private void waitOnFence(Image image) {
try {
SyncFence fence = image.getFence();
@ -1018,7 +1017,7 @@ public class FlutterRenderer implements TextureRegistry {
}
}
@TargetApi(API_LEVELS.API_29)
@RequiresApi(API_LEVELS.API_29)
private void maybeWaitOnFence(Image image) {
if (image == null) {
return;
@ -1037,7 +1036,7 @@ public class FlutterRenderer implements TextureRegistry {
}
@Override
@TargetApi(API_LEVELS.API_29)
@RequiresApi(API_LEVELS.API_29)
public Image acquireLatestImage() {
Image r;
synchronized (this) {

View File

@ -4,7 +4,6 @@
package io.flutter.embedding.engine.systemchannels;
import android.annotation.TargetApi;
import android.window.BackEvent;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@ -60,7 +59,6 @@ public class BackGestureChannel {
*
* @param backEvent The BackEvent object containing information about the touch.
*/
@TargetApi(API_LEVELS.API_34)
@RequiresApi(API_LEVELS.API_34)
public void startBackGesture(@NonNull BackEvent backEvent) {
Log.v(TAG, "Sending message to start back gesture");
@ -74,7 +72,6 @@ public class BackGestureChannel {
*
* @param backEvent An BackEvent object describing the progress event.
*/
@TargetApi(API_LEVELS.API_34)
@RequiresApi(API_LEVELS.API_34)
public void updateBackGestureProgress(@NonNull BackEvent backEvent) {
Log.v(TAG, "Sending message to update back gesture progress");
@ -87,7 +84,6 @@ public class BackGestureChannel {
* <p>This method should be called to signify the completion of a back gesture event and commit
* the navigation action initiated by the gesture.
*/
@TargetApi(API_LEVELS.API_34)
@RequiresApi(API_LEVELS.API_34)
public void commitBackGesture() {
Log.v(TAG, "Sending message to commit back gesture");
@ -99,7 +95,6 @@ public class BackGestureChannel {
*
* <p>This method should be called when a back gesture is cancelled or the back button is pressed.
*/
@TargetApi(API_LEVELS.API_34)
@RequiresApi(API_LEVELS.API_34)
public void cancelBackGesture() {
Log.v(TAG, "Sending message to cancel back gesture");
@ -115,7 +110,6 @@ public class BackGestureChannel {
channel.setMethodCallHandler(handler);
}
@TargetApi(API_LEVELS.API_34)
@RequiresApi(API_LEVELS.API_34)
private Map<String, Object> backEventToJsonMap(@NonNull BackEvent backEvent) {
Map<String, Object> message = new HashMap<>(3);

View File

@ -6,7 +6,6 @@ package io.flutter.embedding.engine.systemchannels;
import static io.flutter.Build.API_LEVELS;
import android.annotation.TargetApi;
import android.os.Build;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@ -129,7 +128,6 @@ public class ScribeChannel {
* Responds to the {@code result} with success and a boolean indicating whether or not stylus
* handwriting is available.
*/
@TargetApi(API_LEVELS.API_34)
@RequiresApi(API_LEVELS.API_34)
boolean isStylusHandwritingAvailable();
@ -137,7 +135,6 @@ public class ScribeChannel {
* Requests to start Scribe stylus handwriting, which will respond to the {@code result} with
* either success if handwriting input has started or error otherwise.
*/
@TargetApi(API_LEVELS.API_33)
@RequiresApi(API_LEVELS.API_33)
void startStylusHandwriting();
}

View File

@ -7,7 +7,6 @@ package io.flutter.plugin.editing;
import static io.flutter.Build.API_LEVELS;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.graphics.Insets;
import android.view.View;
import android.view.WindowInsets;
@ -44,7 +43,6 @@ import java.util.List;
// dispatched again, this time avoiding any flicker since the animation is now
// complete.
@VisibleForTesting
@TargetApi(API_LEVELS.API_30)
@RequiresApi(API_LEVELS.API_30)
@SuppressLint({"NewApi", "Override"})
@Keep

View File

@ -6,7 +6,6 @@ package io.flutter.plugin.editing;
import static io.flutter.Build.API_LEVELS;
import android.annotation.TargetApi;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
@ -29,7 +28,6 @@ import android.view.inputmethod.ExtractedTextRequest;
import android.view.inputmethod.InputContentInfo;
import android.view.inputmethod.InputMethodManager;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.core.view.inputmethod.InputConnectionCompat;
import io.flutter.Log;
import io.flutter.embedding.engine.FlutterJNI;
@ -495,8 +493,6 @@ public class InputConnectionAdaptor extends BaseInputConnection
}
@Override
@TargetApi(API_LEVELS.API_25)
@RequiresApi(API_LEVELS.API_25)
public boolean commitContent(InputContentInfo inputContentInfo, int flags, Bundle opts) {
// Ensure permission is granted.
if (Build.VERSION.SDK_INT >= API_LEVELS.API_25

View File

@ -6,7 +6,6 @@ package io.flutter.plugin.editing;
import static io.flutter.Build.API_LEVELS;
import android.annotation.TargetApi;
import android.os.Build;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
@ -70,7 +69,6 @@ public class ScribePlugin implements ScribeChannel.ScribeMethodHandler {
* <p>Call this or isFeatureAvailable before calling startStylusHandwriting to make sure it's
* available.
*/
@TargetApi(API_LEVELS.API_34)
@RequiresApi(API_LEVELS.API_34)
@Override
public boolean isStylusHandwritingAvailable() {
@ -83,7 +81,6 @@ public class ScribePlugin implements ScribeChannel.ScribeMethodHandler {
* <p>Typically isStylusHandwritingAvailable should be called first to determine whether this is
* supported by the IME.
*/
@TargetApi(API_LEVELS.API_33)
@RequiresApi(API_LEVELS.API_33)
@Override
public void startStylusHandwriting() {

View File

@ -183,26 +183,25 @@ public class LocalizationPlugin {
*/
@NonNull
public static Locale localeFromString(@NonNull String localeString) {
// Normalize the locale string, replace all underscores with hyphens.
localeString = localeString.replace('_', '-');
Locale.Builder localeBuilder = new Locale.Builder();
// Pre-API 21, we fall back to manually parsing the locale tag.
String parts[] = localeString.split("-", -1);
// Normalize the locale string, replace all underscores with hyphens.
String[] parts = localeString.replace('_', '-').split("-");
// Assume the first part is always the language code.
String languageCode = parts[0];
String scriptCode = "";
String countryCode = "";
localeBuilder.setLanguage(parts[0]);
int index = 1;
if (parts.length > index && parts[index].length() == 4) {
scriptCode = parts[index];
localeBuilder.setScript(parts[index]);
index++;
}
if (parts.length > index && parts[index].length() >= 2 && parts[index].length() <= 3) {
countryCode = parts[index];
localeBuilder.setRegion(parts[index]);
index++;
}
// Ignore the rest of the locale for this purpose.
return new Locale(languageCode, countryCode, scriptCode);
return localeBuilder.build();
}
}

View File

@ -6,7 +6,6 @@ package io.flutter.plugin.mouse;
import static io.flutter.Build.API_LEVELS;
import android.annotation.TargetApi;
import android.view.PointerIcon;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
@ -14,7 +13,6 @@ import io.flutter.embedding.engine.systemchannels.MouseCursorChannel;
import java.util.HashMap;
/** A mandatory plugin that handles mouse cursor requests. */
@TargetApi(API_LEVELS.API_24)
@RequiresApi(API_LEVELS.API_24)
public class MouseCursorPlugin {
@NonNull private final MouseCursorViewDelegate mView;

View File

@ -2,7 +2,6 @@ package io.flutter.plugin.platform;
import static io.flutter.Build.API_LEVELS;
import android.annotation.TargetApi;
import android.graphics.ImageFormat;
import android.hardware.HardwareBuffer;
import android.media.Image;
@ -10,10 +9,10 @@ import android.media.ImageReader;
import android.os.Build;
import android.os.Handler;
import android.view.Surface;
import androidx.annotation.RequiresApi;
import io.flutter.Log;
import io.flutter.view.TextureRegistry.ImageTextureEntry;
@TargetApi(API_LEVELS.API_29)
public class ImageReaderPlatformViewRenderTarget implements PlatformViewRenderTarget {
private ImageTextureEntry textureEntry;
private ImageReader reader;
@ -50,7 +49,7 @@ public class ImageReaderPlatformViewRenderTarget implements PlatformViewRenderTa
}
};
@TargetApi(API_LEVELS.API_33)
@RequiresApi(API_LEVELS.API_33)
protected ImageReader createImageReader33() {
final ImageReader.Builder builder = new ImageReader.Builder(bufferWidth, bufferHeight);
// Allow for double buffering.
@ -69,7 +68,7 @@ public class ImageReaderPlatformViewRenderTarget implements PlatformViewRenderTa
return reader;
}
@TargetApi(API_LEVELS.API_29)
@RequiresApi(API_LEVELS.API_29)
protected ImageReader createImageReader29() {
final ImageReader reader =
ImageReader.newInstance(

View File

@ -7,7 +7,6 @@ package io.flutter.plugin.platform;
import static io.flutter.Build.API_LEVELS;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
@ -23,6 +22,7 @@ import android.view.accessibility.AccessibilityEvent;
import android.widget.FrameLayout;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.annotation.VisibleForTesting;
import io.flutter.Log;
import io.flutter.embedding.android.AndroidTouchProcessor;
@ -40,7 +40,7 @@ import io.flutter.util.ViewUtils;
* <p>Since the view is in the Android view hierarchy, keyboard and accessibility interactions
* behave normally.
*/
@TargetApi(API_LEVELS.API_23)
@RequiresApi(API_LEVELS.API_23)
public class PlatformViewWrapper extends FrameLayout {
private static final String TAG = "PlatformViewWrapper";

View File

@ -6,7 +6,6 @@ package io.flutter.plugin.platform;
import static io.flutter.Build.API_LEVELS;
import android.annotation.TargetApi;
import android.content.ComponentCallbacks2;
import android.content.Context;
import android.content.MutableContextWrapper;
@ -21,6 +20,7 @@ import android.view.ViewGroup;
import android.widget.FrameLayout;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.annotation.UiThread;
import androidx.annotation.VisibleForTesting;
import io.flutter.Log;
@ -592,7 +592,7 @@ public class PlatformViewsController implements PlatformViewsAccessibilityDelega
// Configures the view for Texture Layer Hybrid Composition mode, returning the associated
// texture ID.
@TargetApi(API_LEVELS.API_23)
@RequiresApi(API_LEVELS.API_23)
@VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
public long configureForTextureLayerComposition(
@NonNull PlatformView platformView,

View File

@ -2,11 +2,11 @@ package io.flutter.plugin.platform;
import static io.flutter.Build.API_LEVELS;
import android.annotation.TargetApi;
import android.view.Surface;
import androidx.annotation.RequiresApi;
import io.flutter.view.TextureRegistry.SurfaceProducer;
@TargetApi(API_LEVELS.API_29)
@RequiresApi(API_LEVELS.API_29)
public class SurfaceProducerPlatformViewRenderTarget implements PlatformViewRenderTarget {
private static final String TAG = "SurfaceProducerRenderTarget";
private SurfaceProducer producer;

View File

@ -3,14 +3,13 @@ package io.flutter.plugin.platform;
import static android.content.ComponentCallbacks2.TRIM_MEMORY_COMPLETE;
import static io.flutter.Build.API_LEVELS;
import android.annotation.TargetApi;
import android.graphics.SurfaceTexture;
import android.os.Build;
import android.view.Surface;
import androidx.annotation.RequiresApi;
import io.flutter.view.TextureRegistry;
import io.flutter.view.TextureRegistry.SurfaceTextureEntry;
@TargetApi(API_LEVELS.API_26)
public class SurfaceTexturePlatformViewRenderTarget implements PlatformViewRenderTarget {
private static final String TAG = "SurfaceTexturePlatformViewRenderTarget";
@ -101,6 +100,7 @@ public class SurfaceTexturePlatformViewRenderTarget implements PlatformViewRende
}
}
@RequiresApi(API_LEVELS.API_26)
public Surface getSurface() {
recreateSurfaceIfNeeded();
if (surfaceTexture == null || surfaceTexture.isReleased()) {

View File

@ -7,7 +7,6 @@ package io.flutter.plugin.platform;
import static android.view.View.OnFocusChangeListener;
import static io.flutter.Build.API_LEVELS;
import android.annotation.TargetApi;
import android.content.Context;
import android.hardware.display.DisplayManager;
import android.hardware.display.VirtualDisplay;
@ -18,6 +17,7 @@ import android.view.View;
import android.view.View.OnFocusChangeListener;
import android.view.ViewTreeObserver;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.annotation.VisibleForTesting;
class VirtualDisplayController {
@ -232,7 +232,7 @@ class VirtualDisplayController {
}
// On Android versions 31+ resizing of a Virtual Display's Presentation is natively supported.
@TargetApi(API_LEVELS.API_31)
@RequiresApi(API_LEVELS.API_31)
private void resize31(
View embeddedView, int width, int height, final Runnable onNewSizeFrameAvailable) {
renderTarget.resize(width, height);

View File

@ -6,7 +6,6 @@ package io.flutter.plugin.text;
import static io.flutter.Build.API_LEVELS;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
@ -136,7 +135,6 @@ public class ProcessTextPlugin
* <p>When an activity does not return a value. the request is completed successfully and returns
* null.
*/
@TargetApi(API_LEVELS.API_23)
@RequiresApi(API_LEVELS.API_23)
public boolean onActivityResult(int requestCode, int resultCode, @Nullable Intent intent) {
// Return early if the result is not related to a request sent by this plugin.

View File

@ -7,7 +7,6 @@ package io.flutter.view;
import static io.flutter.Build.API_LEVELS;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.Context;
@ -564,7 +563,6 @@ public class AccessibilityBridge extends AccessibilityNodeProvider {
accessibilityFocusedSemanticsNode, o -> o.hasFlag(Flag.HAS_IMPLICIT_SCROLLING)));
}
@TargetApi(API_LEVELS.API_31)
@RequiresApi(API_LEVELS.API_31)
private void setBoldTextFlag() {
if (rootAccessibilityView == null || rootAccessibilityView.getResources() == null) {
@ -1926,7 +1924,6 @@ public class AccessibilityBridge extends AccessibilityNodeProvider {
}
}
@TargetApi(API_LEVELS.API_28)
@RequiresApi(API_LEVELS.API_28)
private void setAccessibilityPaneTitle(String title) {
rootAccessibilityView.setAccessibilityPaneTitle(title);
@ -1975,7 +1972,6 @@ public class AccessibilityBridge extends AccessibilityNodeProvider {
*
* <p>The {@code layoutInDisplayCutoutMode} is added after API level 28.
*/
@TargetApi(API_LEVELS.API_28)
@RequiresApi(API_LEVELS.API_28)
private boolean doesLayoutInDisplayCutoutModeRequireLeftInset() {
Context context = rootAccessibilityView.getContext();

View File

@ -78,7 +78,10 @@ public class FlutterJNITest {
Configuration config = mock(Configuration.class);
DartExecutor dartExecutor = mock(DartExecutor.class);
LocaleList localeList =
new LocaleList(new Locale("es", "MX"), new Locale("zh", "CN"), new Locale("en", "US"));
new LocaleList(
new Locale.Builder().setLanguage("es").setRegion("MX").build(),
new Locale.Builder().setLanguage("zh").setRegion("CN").build(),
new Locale.Builder().setLanguage("en").setRegion("US").build());
when(context.getResources()).thenReturn(resources);
when(resources.getConfiguration()).thenReturn(config);
when(config.getLocales()).thenReturn(localeList);

View File

@ -57,7 +57,9 @@ public class TextInputChannelTest {
final TextInputChannel.Configuration configuration =
TextInputChannel.Configuration.fromJson(arguments);
final Locale[] hintLocales = {new Locale("en"), new Locale("fr")};
final Locale[] hintLocales = {
new Locale.Builder().setLanguage("en").build(), new Locale.Builder().setLanguage("fr").build()
};
assertEquals(configuration.hintLocales.length, hintLocales.length);
assertEquals(configuration.hintLocales[0], hintLocales[0]);
assertEquals(configuration.hintLocales[1], hintLocales[1]);

View File

@ -82,7 +82,10 @@ public class SpellCheckPluginTest {
SpellCheckerSession fakeSpellCheckerSession = mock(SpellCheckerSession.class);
when(fakeTextServicesManager.newSpellCheckerSession(
null, new Locale("en", "US"), spellCheckPlugin, true))
null,
new Locale.Builder().setLanguage("en").setRegion("US").build(),
spellCheckPlugin,
true))
.thenReturn(fakeSpellCheckerSession);
spellCheckPlugin.initiateSpellCheck("en-US", "Hello, wrold!", mockResult);
@ -118,7 +121,10 @@ public class SpellCheckPluginTest {
SpellCheckerSession fakeSpellCheckerSession = mock(SpellCheckerSession.class);
when(fakeTextServicesManager.newSpellCheckerSession(
null, new Locale("en", "US"), spellCheckPlugin, true))
null,
new Locale.Builder().setLanguage("en").setRegion("US").build(),
spellCheckPlugin,
true))
.thenReturn(fakeSpellCheckerSession);
spellCheckPlugin.performSpellCheck("en-US", "Hello, wrold!");
@ -138,7 +144,7 @@ public class SpellCheckPluginTest {
SpellCheckPlugin spellCheckPlugin =
spy(new SpellCheckPlugin(fakeTextServicesManager, fakeSpellCheckChannel));
SpellCheckerSession fakeSpellCheckerSession = mock(SpellCheckerSession.class);
Locale english_US = new Locale("en", "US");
Locale english_US = new Locale.Builder().setLanguage("en").setRegion("US").build();
when(fakeTextServicesManager.newSpellCheckerSession(null, english_US, spellCheckPlugin, true))
.thenReturn(fakeSpellCheckerSession);
@ -165,7 +171,7 @@ public class SpellCheckPluginTest {
SpellCheckPlugin spellCheckPlugin =
spy(new SpellCheckPlugin(fakeTextServicesManager, fakeSpellCheckChannel));
SpellCheckerSession fakeSpellCheckerSession = mock(SpellCheckerSession.class);
Locale english_US = new Locale("en", "US");
Locale english_US = new Locale.Builder().setLanguage("en").setRegion("US").build();
when(fakeTextServicesManager.newSpellCheckerSession(null, english_US, spellCheckPlugin, true))
.thenReturn(fakeSpellCheckerSession);

View File

@ -2808,7 +2808,7 @@ public class TextInputPluginTest {
scribeChannel,
mock(PlatformViewsController.class),
mock(PlatformViewsController2.class));
final Locale[] hintLocales = {new Locale("en")};
final Locale[] hintLocales = {new Locale.Builder().setLanguage("en").build()};
textInputPlugin.setTextInputClient(
0,
new TextInputChannel.Configuration(

View File

@ -43,7 +43,10 @@ public class LocalizationPluginTest {
Configuration config = mock(Configuration.class);
DartExecutor dartExecutor = mock(DartExecutor.class);
LocaleList localeList =
new LocaleList(new Locale("es", "MX"), new Locale("zh", "CN"), new Locale("en", "US"));
new LocaleList(
new Locale.Builder().setLanguage("es").setRegion("MX").build(),
new Locale.Builder().setLanguage("zh").setRegion("CN").build(),
new Locale.Builder().setLanguage("en").setRegion("US").build());
when(context.getResources()).thenReturn(resources);
when(resources.getConfiguration()).thenReturn(config);
when(config.getLocales()).thenReturn(localeList);
@ -81,7 +84,7 @@ public class LocalizationPluginTest {
"fr", "FR", "",
"it", "IT", ""
};
localeList = new LocaleList(new Locale("fr", "CH"));
localeList = new LocaleList(new Locale.Builder().setLanguage("fr").setRegion("CH").build());
when(config.getLocales()).thenReturn(localeList);
result = flutterJNI.computePlatformResolvedLocale(supportedLocales);
// The call will use the new (> API 24) algorithm.
@ -99,7 +102,8 @@ public class LocalizationPluginTest {
"fr", "", "",
"it", "IT", ""
};
localeList = new LocaleList(new Locale("fr", "CH"));
Locale testSecondLocaleFrCh = new Locale.Builder().setLanguage("fr").setRegion("CH").build();
localeList = new LocaleList(testSecondLocaleFrCh);
when(config.getLocales()).thenReturn(localeList);
result = flutterJNI.computePlatformResolvedLocale(supportedLocales);
// The call will use the new (> API 24) algorithm.
@ -116,7 +120,10 @@ public class LocalizationPluginTest {
"es", "ES", "",
"it", "IT", ""
};
localeList = new LocaleList(new Locale("fr", "CH"), new Locale("it", "CH"));
localeList =
new LocaleList(
new Locale.Builder().setLanguage("fr").setRegion("CH").build(),
new Locale.Builder().setLanguage("it").setRegion("CH").build());
when(config.getLocales()).thenReturn(localeList);
result = flutterJNI.computePlatformResolvedLocale(supportedLocales);
// The call will use the new (> API 24) algorithm.
@ -130,7 +137,7 @@ public class LocalizationPluginTest {
"zh", "CN", "Hans",
"zh", "HK", "Hant",
};
localeList = new LocaleList(new Locale("zh", "CN"));
localeList = new LocaleList(new Locale.Builder().setLanguage("zh").setRegion("CN").build());
when(config.getLocales()).thenReturn(localeList);
result = flutterJNI.computePlatformResolvedLocale(supportedLocales);
assertEquals(result.length, 3);
@ -151,7 +158,10 @@ public class LocalizationPluginTest {
Configuration config = mock(Configuration.class);
DartExecutor dartExecutor = mock(DartExecutor.class);
LocaleList localeList =
new LocaleList(new Locale("es", "MX"), new Locale("zh", "CN"), new Locale("en", "US"));
new LocaleList(
new Locale.Builder().setLanguage("es").setRegion("MX").build(),
new Locale.Builder().setLanguage("zh").setRegion("CN").build(),
new Locale.Builder().setLanguage("en").setRegion("US").build());
when(context.getResources()).thenReturn(resources);
when(resources.getConfiguration()).thenReturn(config);
when(config.getLocales()).thenReturn(localeList);
@ -189,7 +199,7 @@ public class LocalizationPluginTest {
"fr", "FR", "",
"it", "IT", ""
};
localeList = new LocaleList(new Locale("fr", "CH"));
localeList = new LocaleList(new Locale.Builder().setLanguage("fr").setRegion("CH").build());
when(config.getLocales()).thenReturn(localeList);
result = flutterJNI.computePlatformResolvedLocale(supportedLocales);
// The call will use the new (> API 24) algorithm.
@ -207,7 +217,7 @@ public class LocalizationPluginTest {
"fr", "", "",
"it", "IT", ""
};
localeList = new LocaleList(new Locale("fr", "CH"));
localeList = new LocaleList(new Locale.Builder().setLanguage("fr").setRegion("CH").build());
when(config.getLocales()).thenReturn(localeList);
result = flutterJNI.computePlatformResolvedLocale(supportedLocales);
// The call will use the new (> API 24) algorithm.
@ -224,7 +234,10 @@ public class LocalizationPluginTest {
"es", "ES", "",
"it", "IT", ""
};
localeList = new LocaleList(new Locale("fr", "CH"), new Locale("it", "CH"));
localeList =
new LocaleList(
new Locale.Builder().setLanguage("fr").setRegion("CH").build(),
new Locale.Builder().setLanguage("it").setRegion("CH").build());
when(config.getLocales()).thenReturn(localeList);
result = flutterJNI.computePlatformResolvedLocale(supportedLocales);
// The call will use the new (> API 24) algorithm.
@ -340,31 +353,35 @@ public class LocalizationPluginTest {
@Test
public void localeFromString_languageOnly() {
Locale locale = LocalizationPlugin.localeFromString("en");
assertEquals(locale, new Locale("en"));
assertEquals(locale, new Locale.Builder().setLanguage("en").build());
}
@Test
public void localeFromString_languageAndCountry() {
Locale locale = LocalizationPlugin.localeFromString("en-US");
assertEquals(locale, new Locale("en", "US"));
assertEquals(locale, new Locale.Builder().setLanguage("en").setRegion("US").build());
}
@Test
public void localeFromString_languageCountryAndVariant() {
Locale locale = LocalizationPlugin.localeFromString("zh-Hans-CN");
assertEquals(locale, new Locale("zh", "CN", "Hans"));
Locale testLocale =
new Locale.Builder().setLanguage("zh").setRegion("CN").setScript("Hans").build();
assertEquals(locale, testLocale);
}
@Test
public void localeFromString_underscore() {
Locale locale = LocalizationPlugin.localeFromString("zh_Hans_CN");
assertEquals(locale, new Locale("zh", "CN", "Hans"));
Locale testLocale =
new Locale.Builder().setLanguage("zh").setRegion("CN").setScript("Hans").build();
assertEquals(locale, testLocale);
}
@Test
public void localeFromString_additionalVariantsAreIgnored() {
Locale locale = LocalizationPlugin.localeFromString("de-DE-u-co-phonebk");
assertEquals(locale, new Locale("de", "DE"));
assertEquals(locale, new Locale.Builder().setLanguage("de").setRegion("DE").build());
}
@Test

View File

@ -4,7 +4,7 @@ buildscript {
mavenCentral()
}
dependencies {
classpath "com.android.tools.build:gradle:8.7.2"
classpath "com.android.tools.build:gradle:8.9.1"
}
}
@ -33,7 +33,7 @@ println "=========================================="
android {
namespace 'io.flutter.app.test'
compileSdk 35
compileSdk 36
defaultConfig {
minSdkVersion 21

View File

@ -6,12 +6,12 @@ import("//build/config/android/config.gni")
import("//flutter/tools/templater/templater.gni")
android_buildtools =
"//flutter/third_party/android_tools/sdk/build-tools/35.0.0-rc4"
"//flutter/third_party/android_tools/sdk/build-tools/36.0.0"
aapt2 = "$android_buildtools/aapt2"
zipalign = "$android_buildtools/zipalign"
apksigner = "$android_buildtools/apksigner"
android_jar =
"//flutter/third_party/android_tools/sdk/platforms/android-35/android.jar"
"//flutter/third_party/android_tools/sdk/platforms/android-36/android.jar"
src_root = "//flutter/testing/android/native_activity"
# A drop in replacement for an executable or shared library target. Providing a

View File

@ -1,6 +1,6 @@
platforms;android-35:platforms
platforms;android-36:platforms
cmdline-tools;latest:cmdline-tools
build-tools;35.0.0-rc4:build-tools
build-tools;36.0.0:build-tools
platform-tools:platform-tools
tools:tools
ndk;26.3.11579264:ndk
ndk;27.0.12077973:ndk

View File

@ -13,7 +13,7 @@ buildscript {
mavenCentral()
}
dependencies {
classpath "com.android.tools.build:gradle:7.3.0"
classpath "com.android.tools.build:gradle:8.9.1"
}
}
@ -33,7 +33,7 @@ allprojects {
apply plugin: "com.android.application"
android {
compileSdk 35
compileSdk 36
}
configurations {

View File

@ -48,7 +48,7 @@ def main():
os.makedirs(args.out_dir)
android_jar_path = os.path.join(
args.src_dir, 'flutter', 'third_party', 'android_tools', 'sdk', 'platforms', 'android-35',
args.src_dir, 'flutter', 'third_party', 'android_tools', 'sdk', 'platforms', 'android-36',
'android.jar'
)
if not os.path.exists(android_jar_path):