flutter 3.44 pre

Signed-off-by: dom <githubaccount56556@proton.me>
This commit is contained in:
dom
2026-05-14 21:48:25 +08:00
parent 3c6d4ef08c
commit cf2877b77c
34 changed files with 1173 additions and 329 deletions

View File

@@ -3,7 +3,6 @@ import org.jetbrains.kotlin.konan.properties.Properties
plugins {
id("com.android.application")
id("kotlin-android")
// The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
id("dev.flutter.flutter-gradle-plugin")
}
@@ -20,7 +19,7 @@ android {
kotlin {
compilerOptions {
jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17)
jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17
}
}

View File

@@ -0,0 +1,532 @@
package io.flutter;
import android.app.Activity;
import android.os.Build;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import androidx.core.view.WindowInsetsControllerCompat;
import org.json.JSONArray;
import org.json.JSONException;
import java.util.ArrayList;
import java.util.List;
/// from Flutter
public class SystemChrome {
public static void onMethodCall(Activity activity, String methodName, Object arguments) {
switch (methodName) {
case "SystemChrome.setEnabledSystemUIMode":
try {
SystemUiMode mode = decodeSystemUiMode((String) arguments);
setSystemChromeEnabledSystemUIMode(activity, mode);
} catch (JSONException | NoSuchFieldException exception) {
}
break;
case "SystemChrome.setEnabledSystemUIOverlays":
try {
List<SystemUiOverlay> overlays = decodeSystemUiOverlays((JSONArray) arguments);
setSystemChromeEnabledSystemUIOverlays(activity, overlays);
} catch (JSONException | NoSuchFieldException exception) {
}
break;
}
}
@NonNull
private static SystemUiMode decodeSystemUiMode(@NonNull String encodedSystemUiMode)
throws JSONException, NoSuchFieldException {
SystemUiMode mode = SystemUiMode.fromValue(encodedSystemUiMode);
switch (mode) {
case LEAN_BACK:
return SystemUiMode.LEAN_BACK;
case IMMERSIVE:
return SystemUiMode.IMMERSIVE;
case IMMERSIVE_STICKY:
return SystemUiMode.IMMERSIVE_STICKY;
case EDGE_TO_EDGE:
return SystemUiMode.EDGE_TO_EDGE;
}
// Execution should never ever get this far, but if it does, we default to edge to edge.
return SystemUiMode.EDGE_TO_EDGE;
}
public static final int DEFAULT_SYSTEM_UI =
View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
private static void setSystemChromeEnabledSystemUIOverlays(Activity activity, List<SystemUiOverlay> overlaysToShow) {
// Start by assuming we want to hide all system overlays (like an immersive
// game).
int enabledOverlays =
DEFAULT_SYSTEM_UI
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
if (overlaysToShow.isEmpty()) {
enabledOverlays |= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
}
// Re-add any desired system overlays.
for (int i = 0; i < overlaysToShow.size(); ++i) {
SystemUiOverlay overlayToShow = overlaysToShow.get(i);
switch (overlayToShow) {
case TOP_OVERLAYS:
enabledOverlays &= ~View.SYSTEM_UI_FLAG_FULLSCREEN;
break;
case BOTTOM_OVERLAYS:
enabledOverlays &= ~View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
enabledOverlays &= ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
break;
}
}
mEnabledOverlays = enabledOverlays;
updateSystemUiOverlays(activity);
}
@NonNull
private static List<SystemUiOverlay> decodeSystemUiOverlays(@NonNull JSONArray encodedSystemUiOverlay)
throws JSONException, NoSuchFieldException {
List<SystemUiOverlay> overlays = new ArrayList<>();
for (int i = 0; i < encodedSystemUiOverlay.length(); ++i) {
String encodedOverlay = encodedSystemUiOverlay.getString(i);
SystemUiOverlay overlay = SystemUiOverlay.fromValue(encodedOverlay);
switch (overlay) {
case TOP_OVERLAYS:
overlays.add(SystemUiOverlay.TOP_OVERLAYS);
break;
case BOTTOM_OVERLAYS:
overlays.add(SystemUiOverlay.BOTTOM_OVERLAYS);
break;
}
}
return overlays;
}
public enum SystemUiOverlay {
TOP_OVERLAYS("SystemUiOverlay.top"),
BOTTOM_OVERLAYS("SystemUiOverlay.bottom");
@NonNull
static SystemUiOverlay fromValue(@NonNull String encodedName) throws NoSuchFieldException {
for (SystemUiOverlay overlay : SystemUiOverlay.values()) {
if (overlay.encodedName.equals(encodedName)) {
return overlay;
}
}
throw new NoSuchFieldException("No such SystemUiOverlay: " + encodedName);
}
@NonNull
private String encodedName;
SystemUiOverlay(@NonNull String encodedName) {
this.encodedName = encodedName;
}
}
private static int mEnabledOverlays;
private static SystemChromeStyle currentTheme;
/**
* The set of Android system fullscreen modes as perceived by the Flutter application.
*/
public enum SystemUiMode {
LEAN_BACK("SystemUiMode.leanBack"),
IMMERSIVE("SystemUiMode.immersive"),
IMMERSIVE_STICKY("SystemUiMode.immersiveSticky"),
EDGE_TO_EDGE("SystemUiMode.edgeToEdge");
/**
* Returns the SystemUiMode for the provided encoded value. @throws NoSuchFieldException if any
* of the given encoded overlay names are invalid.
*/
@NonNull
static SystemUiMode fromValue(@NonNull String encodedName) throws NoSuchFieldException {
for (SystemUiMode mode : SystemUiMode.values()) {
if (mode.encodedName.equals(encodedName)) {
return mode;
}
}
throw new NoSuchFieldException("No such SystemUiMode: " + encodedName);
}
@NonNull
private String encodedName;
/**
* Returns the encoded {@link SystemUiMode}
*/
SystemUiMode(@NonNull String encodedName) {
this.encodedName = encodedName;
}
}
private static void setSystemChromeEnabledSystemUIMode(Activity activity, SystemUiMode systemUiMode) {
int enabledOverlays;
if (systemUiMode == SystemUiMode.LEAN_BACK) {
// LEAN BACK
// Available starting at Android SDK 4.1 (API 16).
//
// If the Flutter Android app targets Android SDK 15 (API 35), then the Android
// system will ignore this value unless the app also follows the opt out
// instructions found in
// https://docs.flutter.dev/release/breaking-changes/default-systemuimode-edge-to-edge.
//
// If the Flutter Android app targets Android SDK 16 (API 36) or later, then the Android
// system will ignore this value.
//
// Should not show overlays, tap to reveal overlays, needs onChange callback
// When the overlays come in on tap, the app does not receive the gesture and does not know
// the system overlay has changed. The overlays cannot be dismissed, so adding the callback
// support will allow users to restore the system ui and dismiss the overlays.
// Not compatible with top/bottom overlays enabled.
enabledOverlays =
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_FULLSCREEN;
} else if (systemUiMode == SystemUiMode.IMMERSIVE) {
// IMMERSIVE
// Available starting at Android SDK 4.4 (API 19).
//
// If the Flutter Android app targets Android SDK 15 (API 35), then the Android
// system will ignore this value unless the app also follows the opt out
// instructions found in
// https://docs.flutter.dev/release/breaking-changes/default-systemuimode-edge-to-edge.
//
// If the Flutter Android app targets Android SDK 16 (API 36) or later, then the Android
// system will ignore this value.
//
// Should not show overlays, swipe from edges to reveal overlays, needs onChange callback
// When the overlays come in on swipe, the app does not receive the gesture and does not know
// the system overlay has changed. The overlays cannot be dismissed, so adding callback
// support will allow users to restore the system ui and dismiss the overlays.
// Not compatible with top/bottom overlays enabled.
enabledOverlays =
View.SYSTEM_UI_FLAG_IMMERSIVE
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_FULLSCREEN;
} else if (systemUiMode == SystemUiMode.IMMERSIVE_STICKY) {
// STICKY IMMERSIVE
// Available starting at Android SDK 4.4 (API 19).
//
// If the Flutter Android app targets Android SDK 15 (API 35), then the Android
// system will ignore this value unless the app also follows the opt out
// instructions found in
// https://docs.flutter.dev/release/breaking-changes/default-systemuimode-edge-to-edge.
//
// If the Flutter Android app targets Android SDK 16 (API 36) or later, then the Android
// system will ignore this value.
//
// Should not show overlays, swipe from edges to reveal overlays. The app will also receive
// the swipe gesture. The overlays cannot be dismissed, so adding callback support will
// allow users to restore the system ui and dismiss the overlays.
// Not compatible with top/bottom overlays enabled.
enabledOverlays =
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_FULLSCREEN;
} else if (systemUiMode == SystemUiMode.EDGE_TO_EDGE
&& Build.VERSION.SDK_INT >= API_LEVELS.API_29) {
// EDGE TO EDGE
//
// Available starting at Android SDK 10 (API 29).
//
// If the Flutter app targets Android SDK 15 (API 35) or later (Flutter does this by default),
// then this mode is used by default.
//
// SDK 29 and up will apply a translucent body scrim behind 2/3 button navigation bars
// to ensure contrast with buttons on the nav and status bars, unless the contrast is not
// enforced in the overlay styling.
enabledOverlays =
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
} else {
// When none of the conditions are matched, return without updating the system UI overlays.
return;
}
mEnabledOverlays = enabledOverlays;
updateSystemUiOverlays(activity);
}
public static void updateSystemUiOverlays(Activity activity) {
activity.getWindow().getDecorView().setSystemUiVisibility(mEnabledOverlays);
if (currentTheme != null) {
setSystemChromeSystemUIOverlayStyle(activity, currentTheme);
}
}
private static void setSystemChromeSystemUIOverlayStyle(Activity activity, SystemChromeStyle systemChromeStyle) {
Window window = activity.getWindow();
View view = window.getDecorView();
WindowInsetsControllerCompat windowInsetsControllerCompat =
new WindowInsetsControllerCompat(window, view);
if (Build.VERSION.SDK_INT < API_LEVELS.API_30) {
// Flag set to specify that this window is responsible for drawing the background for the
// system bars. Must be set for all operations on API < 30 (Android SDK < 11) excluding
// enforcing
// system bar contrasts. Deprecated in API 30.
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
// Flag set to dismiss any requests for translucent system bars to be provided in lieu of what
// is specified by systemChromeStyle. Must be set for all operations on API < 30 operations
// excluding enforcing system bar contrasts. Deprecated in API 30.
window.clearFlags(
WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
| WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
}
// SYSTEM STATUS BAR -------------------------------------------------------------------
// You can't change the color of the system status bar until SDK 21, and you can't change the
// color of the status icons until SDK 23. We only allow both starting at 23 to ensure buttons
// and icons can be visible when changing the background color.
// If transparent, SDK 29 and higher may apply a translucent scrim behind the bar to ensure
// proper contrast. This can be overridden with
// SystemChromeStyle.systemStatusBarContrastEnforced.
if (systemChromeStyle.statusBarIconBrightness != null) {
switch (systemChromeStyle.statusBarIconBrightness) {
case DARK:
// Dark status bar icon brightness.
// Light status bar appearance.
windowInsetsControllerCompat.setAppearanceLightStatusBars(true);
break;
case LIGHT:
// Light status bar icon brightness.
// Dark status bar appearance.
windowInsetsControllerCompat.setAppearanceLightStatusBars(false);
break;
}
}
if (systemChromeStyle.statusBarColor != null) {
// setStatusBarColor has no effect on Android 15 and above, meaning calls to this method will
// have no effect on those versions.
// Consider using the
// [WindowInsetsController](https://developer.android.com/reference/android/view/WindowInsetsController)
// or other Android 15+ APIs for system UI styling.
if (Build.VERSION.SDK_INT < API_LEVELS.API_35) {
window.setStatusBarColor(systemChromeStyle.statusBarColor);
}
}
// You can't override the enforced contrast for a transparent status bar until SDK 29.
// This overrides the translucent scrim that may be placed behind the bar on SDK 29+ to ensure
// contrast is appropriate when using full screen layout modes like Edge to Edge.
if (systemChromeStyle.systemStatusBarContrastEnforced != null
&& Build.VERSION.SDK_INT >= API_LEVELS.API_29) {
window.setStatusBarContrastEnforced(systemChromeStyle.systemStatusBarContrastEnforced);
}
// SYSTEM NAVIGATION BAR --------------------------------------------------------------
// You can't change the color of the system navigation bar until SDK 21, and you can't change
// the color of the navigation buttons until SDK 26. We only allow both starting at 26 to
// ensure buttons can be visible when changing the background color.
// If transparent, SDK 29 and higher may apply a translucent scrim behind 2/3 button navigation
// bars to ensure proper contrast. This can be overridden with
// SystemChromeStyle.systemNavigationBarContrastEnforced.
if (Build.VERSION.SDK_INT >= API_LEVELS.API_26) {
if (systemChromeStyle.systemNavigationBarIconBrightness != null) {
switch (systemChromeStyle.systemNavigationBarIconBrightness) {
case DARK:
// Dark navigation bar icon brightness.
// Light navigation bar appearance.
windowInsetsControllerCompat.setAppearanceLightNavigationBars(true);
break;
case LIGHT:
// Light navigation bar icon brightness.
// Dark navigation bar appearance.
windowInsetsControllerCompat.setAppearanceLightNavigationBars(false);
break;
}
}
if (systemChromeStyle.systemNavigationBarColor != null) {
// setNavigationBarColor has no effect on Android 15 and above, meaning calls to this method
// will have no effect on those versions.
// Consider using the
// [WindowInsetsController](https://developer.android.com/reference/android/view/WindowInsetsController)
// or other Android 15+ APIs for system UI styling.
if (Build.VERSION.SDK_INT < API_LEVELS.API_35) {
window.setNavigationBarColor(systemChromeStyle.systemNavigationBarColor);
}
}
}
// You can't change the color of the navigation bar divider color until SDK 28.
// setNavigationBarDividerColor has no effect on Android 15 and above, meaning calls to this
// method will have no effect on those versions.
// Consider using the
// [WindowInsetsController](https://developer.android.com/reference/android/view/WindowInsetsController)
// or other Android 15+ APIs for system UI styling.
if (systemChromeStyle.systemNavigationBarDividerColor != null
&& Build.VERSION.SDK_INT >= API_LEVELS.API_28
&& Build.VERSION.SDK_INT < API_LEVELS.API_35) {
window.setNavigationBarDividerColor(systemChromeStyle.systemNavigationBarDividerColor);
}
// You can't override the enforced contrast for a transparent navigation bar until SDK 29.
// This overrides the translucent scrim that may be placed behind 2/3 button navigation bars on
// SDK 29+ to ensure contrast is appropriate when using full screen layout modes like
// Edge to Edge.
if (systemChromeStyle.systemNavigationBarContrastEnforced != null
&& Build.VERSION.SDK_INT >= API_LEVELS.API_29) {
window.setNavigationBarContrastEnforced(
systemChromeStyle.systemNavigationBarContrastEnforced);
}
currentTheme = systemChromeStyle;
}
public static class SystemChromeStyle {
// TODO(mattcarroll): add color annotation
@Nullable
public final Integer statusBarColor;
@Nullable
public final Brightness statusBarIconBrightness;
@Nullable
public final Boolean systemStatusBarContrastEnforced;
// TODO(mattcarroll): add color annotation
@Nullable
public final Integer systemNavigationBarColor;
@Nullable
public final Brightness systemNavigationBarIconBrightness;
// TODO(mattcarroll): add color annotation
@Nullable
public final Integer systemNavigationBarDividerColor;
@Nullable
public final Boolean systemNavigationBarContrastEnforced;
public SystemChromeStyle(
@Nullable Integer statusBarColor,
@Nullable Brightness statusBarIconBrightness,
@Nullable Boolean systemStatusBarContrastEnforced,
@Nullable Integer systemNavigationBarColor,
@Nullable Brightness systemNavigationBarIconBrightness,
@Nullable Integer systemNavigationBarDividerColor,
@Nullable Boolean systemNavigationBarContrastEnforced) {
this.statusBarColor = statusBarColor;
this.statusBarIconBrightness = statusBarIconBrightness;
this.systemStatusBarContrastEnforced = systemStatusBarContrastEnforced;
this.systemNavigationBarColor = systemNavigationBarColor;
this.systemNavigationBarIconBrightness = systemNavigationBarIconBrightness;
this.systemNavigationBarDividerColor = systemNavigationBarDividerColor;
this.systemNavigationBarContrastEnforced = systemNavigationBarContrastEnforced;
}
}
public enum Brightness {
LIGHT("Brightness.light"),
DARK("Brightness.dark");
@NonNull
static Brightness fromValue(@NonNull String encodedName) throws NoSuchFieldException {
for (Brightness brightness : Brightness.values()) {
if (brightness.encodedName.equals(encodedName)) {
return brightness;
}
}
throw new NoSuchFieldException("No such Brightness: " + encodedName);
}
@NonNull
private String encodedName;
Brightness(@NonNull String encodedName) {
this.encodedName = encodedName;
}
}
public static class API_LEVELS {
@VisibleForTesting
public static final int FLUTTER_MIN = 24;
/**
* Android 5.0 (Lollipop)
*/
public static final int API_21 = 21;
/**
* Android 5.1 (Lollipop MR1)
*/
public static final int API_22 = 22;
/**
* Android 6.0 (Marshmallow)
*/
public static final int API_23 = 23;
/**
* Android 7.0 (Nougat)
*/
public static final int API_24 = 24;
/**
* Android 7.1 (Nougat MR1)
*/
public static final int API_25 = 25;
/**
* Android 8.0 (Oreo)
*/
public static final int API_26 = 26;
/**
* Android 8.1 (Oreo MR1)
*/
public static final int API_27 = 27;
/**
* Android 9 (Pie)
*/
public static final int API_28 = 28;
/**
* Android 10 (Q)
*/
public static final int API_29 = 29;
/**
* Android 11 (R)
*/
public static final int API_30 = 30;
/**
* Android 12 (S)
*/
public static final int API_31 = 31;
/**
* Android 12L (Sv2)
*/
public static final int API_32 = 32;
/**
* Android 13 (Tiramisu)
*/
public static final int API_33 = 33;
/**
* Android 14 (Upside Down Cake)
*/
public static final int API_34 = 34;
/**
* Android 15 (Vanilla Ice Cream)
*/
public static final int API_35 = 35;
/**
* Android 16
*/
public static final int API_36 = 36;
}
}

View File

@@ -16,6 +16,7 @@ import androidx.core.net.toUri
import com.ryanheise.audioservice.AudioServiceActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
import io.flutter.SystemChrome
class MainActivity : AudioServiceActivity() {
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
@@ -120,6 +121,22 @@ class MainActivity : AudioServiceActivity() {
result.success(Build.VERSION.SDK_INT)
}
"SystemChrome.setEnabledSystemUIMode" -> {
SystemChrome.onMethodCall(
this,
"SystemChrome.setEnabledSystemUIMode",
call.argument("arguments")
)
}
"SystemChrome.setEnabledSystemUIOverlays" -> {
SystemChrome.onMethodCall(
this,
"SystemChrome.setEnabledSystemUIOverlays",
call.argument("arguments")
)
}
else -> result.notImplemented()
}
}

View File

@@ -1,3 +1,5 @@
org.gradle.jvmargs=-Xmx4G -XX:MaxMetaspaceSize=2G -XX:+HeapDumpOnOutOfMemoryError
android.useAndroidX=true
android.enableJetifier=true
android.enableJetifier=true
android.builtInKotlin=false
android.newDsl=false