diff --git a/platform/android/app/build.gradle.kts b/platform/android/app/build.gradle.kts index a101087e1..6b67be198 100644 --- a/platform/android/app/build.gradle.kts +++ b/platform/android/app/build.gradle.kts @@ -131,7 +131,7 @@ val parsedBuildProperties: JsonObject = run { } extra["minSdkVersion"] = parsedBuildProperties.lookup("buildSettings.android.minSdkVersion").firstOrNull()?.toString()?.toIntOrNull() - ?: 15 + ?: 21 val coronaBuilder = if (windows) { "$nativeDir/Corona/win/bin/CoronaBuilder.exe" @@ -195,10 +195,10 @@ android { lintOptions { isCheckReleaseBuilds = true } - compileSdk = 35 + compileSdk = 36 defaultConfig { applicationId = coronaAppPackage - targetSdk = 35 + targetSdk = 36 minSdk = (extra["minSdkVersion"] as Int) versionCode = coronaVersionCode versionName = coronaVersionName @@ -1150,4 +1150,5 @@ dependencies { implementation(project(":plugin")) } implementation("androidx.multidex:multidex:2.0.1") + implementation("androidx.core:core:1.17.0") } diff --git a/platform/android/build.gradle.kts b/platform/android/build.gradle.kts index 0e42ccfc8..5354b56f4 100644 --- a/platform/android/build.gradle.kts +++ b/platform/android/build.gradle.kts @@ -6,8 +6,8 @@ buildscript { } dependencies { classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.21") - classpath("com.android.tools.build:gradle:8.8.0") - classpath("com.beust:klaxon:5.5") + classpath("com.android.tools.build:gradle:8.13.0") + classpath("com.beust:klaxon:5.6") } } diff --git a/platform/android/gradle/wrapper/gradle-wrapper.properties b/platform/android/gradle/wrapper/gradle-wrapper.properties index 79eb9d003..ed4c299ad 100644 --- a/platform/android/gradle/wrapper/gradle-wrapper.properties +++ b/platform/android/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-all.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/platform/android/sdk/build.gradle.kts b/platform/android/sdk/build.gradle.kts index b96c4246b..7e998e282 100644 --- a/platform/android/sdk/build.gradle.kts +++ b/platform/android/sdk/build.gradle.kts @@ -7,10 +7,10 @@ val buildDirectory = layout.buildDirectory.asFile.get() android { namespace = "com.ansca.corona" ndkVersion = "18.1.5063045" - compileSdk = 35 + compileSdk = 36 defaultConfig { - minSdk = 15 + minSdk = 21 version = 1 } sourceSets["main"].manifest.srcFile(file("AndroidManifest-New.xml")) @@ -27,6 +27,11 @@ android { } +// Need for Android Edge To Edge +dependencies { + implementation("androidx.core:core:1.17.0") +} + tasks.create("updateWidgetResources") { group = "Corona" val widgetResLocation = "$buildDirectory/generated/widgetResources" diff --git a/platform/android/sdk/src/com/ansca/corona/CoronaActivity.java b/platform/android/sdk/src/com/ansca/corona/CoronaActivity.java index 91b465441..6c4ad2fca 100644 --- a/platform/android/sdk/src/com/ansca/corona/CoronaActivity.java +++ b/platform/android/sdk/src/com/ansca/corona/CoronaActivity.java @@ -38,6 +38,9 @@ import com.ansca.corona.storage.ResourceServices; import android.view.DisplayCutout; import android.view.ViewTreeObserver; + +import androidx.core.view.WindowCompat; + /** * The activity window that hosts the Corona project. * @see Activity @@ -190,6 +193,7 @@ protected void onCreate(Bundle savedInstanceState) { fStartTime = System.currentTimeMillis(); + // Work around FileProvider issue in level 25: // http://stackoverflow.com/questions/38200282/android-os-fileuriexposedexception-file-storage-emulated-0-test-txt-exposed // TODO: Fix this properly by using FileProvider appropriately @@ -281,6 +285,21 @@ protected void onCreate(Bundle savedInstanceState) { ex.printStackTrace(); } + // Set edgeToEdge before splashScreen comes up + try { + android.content.pm.ActivityInfo activityInfo; + activityInfo = getPackageManager().getActivityInfo(getComponentName(), android.content.pm.PackageManager.GET_META_DATA); + if ((activityInfo != null) && (activityInfo.metaData != null)) { + Boolean edgeToEdge = activityInfo.metaData.getBoolean("edgeToEdge"); + if (edgeToEdge == true) { + WindowCompat.enableEdgeToEdge(getWindow()); + } + } + } + catch (Exception ex) { + ex.printStackTrace(); + } + // fCoronaRuntime = new CoronaRuntime(this, false); // for Tegra debugging showCoronaSplashScreen(); diff --git a/platform/android/sdk/src/com/ansca/corona/NativeToJavaBridge.java b/platform/android/sdk/src/com/ansca/corona/NativeToJavaBridge.java index 5199f7b1c..0788e7714 100644 --- a/platform/android/sdk/src/com/ansca/corona/NativeToJavaBridge.java +++ b/platform/android/sdk/src/com/ansca/corona/NativeToJavaBridge.java @@ -3303,24 +3303,25 @@ protected static void callSetNavigationBarColor(CoronaRuntime runtime, double re (int)(255 * blue) ); + Window window = activity.getWindow(); + View decorView = window.getDecorView(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM) { // Android 15+ - Window window = activity.getWindow(); - View decorView = window.getDecorView(); - // Add bottom insert - decorView.setOnApplyWindowInsetsListener((view, insets) -> { - Insets navBarInsets = insets.getInsets(WindowInsets.Type.navigationBars()); - view.setBackgroundColor(color); - view.setPadding(0, 0, 0, navBarInsets.bottom); - return insets; - }); + decorView.setOnApplyWindowInsetsListener(new View.OnApplyWindowInsetsListener() { + @Override + public WindowInsets onApplyWindowInsets(View view, WindowInsets insets) { + Insets statusBarInsets = insets.getInsets(WindowInsets.Type.statusBars()); + view.setBackgroundColor(color); - window.setNavigationBarColor(color); - // Update Insert - decorView.post(() -> { - decorView.requestApplyInsets(); + // Adjust padding to avoid overlap + view.setPadding(0, statusBarInsets.top, 0, 0); + return insets; + } }); + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + // For Android 14 and below + window.setStatusBarColor(color); } else { - CoronaEnvironment.getCoronaActivity().setNavigationBarColor(red, green, blue); + Log.i( "Corona", "WARNING: SetNavigationBarColor is not support on this version of Android" ); } } } diff --git a/platform/android/sdk/src/com/ansca/corona/purchasing/StoreActivity.java b/platform/android/sdk/src/com/ansca/corona/purchasing/StoreActivity.java index 55da23a61..fdeac8de9 100644 --- a/platform/android/sdk/src/com/ansca/corona/purchasing/StoreActivity.java +++ b/platform/android/sdk/src/com/ansca/corona/purchasing/StoreActivity.java @@ -51,22 +51,11 @@ public class StoreActivity extends android.app.Activity { protected void onCreate(android.os.Bundle savedInstanceState) { super.onCreate(savedInstanceState); - // Do not continue if a Nook EAN was not provided. if (getIntent().getStringExtra(EXTRA_NOOK_APP_EAN) == null) { finish(); return; } - // Only lock orientation on devices that don’t support multi-window / resizable - if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.N) { - int orientation = android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT; - if (android.os.Build.VERSION.SDK_INT >= 9) { - orientation = android.content.pm.ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT; - } - setRequestedOrientation(orientation); - } - - // Display this activity full screen if requested boolean isFullScreen = getIntent().getBooleanExtra(EXTRA_FULL_SCREEN, false); if (isFullScreen) { getWindow().addFlags(android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN); @@ -76,9 +65,9 @@ protected void onCreate(android.os.Bundle savedInstanceState) { getWindow().clearFlags(android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN); } - // Initialize this flag to false fHasShownStore = false; } + /** This method is called when this activity can be interacted with. */ @Override protected void onResume() { diff --git a/platform/android/template/AndroidManifest.template.xml b/platform/android/template/AndroidManifest.template.xml index b8a5fd8ac..b84956849 100644 --- a/platform/android/template/AndroidManifest.template.xml +++ b/platform/android/template/AndroidManifest.template.xml @@ -41,6 +41,7 @@ @USER_CORONA_WINDOW_MOVES_WHEN_KEYBOARD_APPEARS@ @USER_INITIAL_SYSTEM_UI_VISIBILITY@ @USER_REQUESTED_DEFAULT_ORIENTATION@ + @USER_EDGE_TO_EDGE@ @USER_MAIN_INTENT_FILTER_CATEGORIES@ diff --git a/platform/android/template/AndroidManifest.xml b/platform/android/template/AndroidManifest.xml index d272b2d2e..d1d1e10ba 100644 --- a/platform/android/template/AndroidManifest.xml +++ b/platform/android/template/AndroidManifest.xml @@ -55,6 +55,7 @@ @USER_CORONA_WINDOW_MOVES_WHEN_KEYBOARD_APPEARS@ @USER_INITIAL_SYSTEM_UI_VISIBILITY@ @USER_REQUESTED_DEFAULT_ORIENTATION@ + @USER_EDGE_TO_EDGE@ @USER_MAIN_INTENT_FILTER_CATEGORIES@ diff --git a/platform/android/template/update_manifest.lua b/platform/android/template/update_manifest.lua index fd9aa29ce..d8a4ef187 100644 --- a/platform/android/template/update_manifest.lua +++ b/platform/android/template/update_manifest.lua @@ -96,6 +96,7 @@ local googlePlayGamesAppId = false local facebookAppId = false local coronaWindowMovesWhenKeyboardAppears = false local initialSystemUiVisibility = nil +local edgeToEdge = true local allowAppsReadOnlyAccessToFiles = true local strings = {} local apkFiles = { "...NONE..." } -- necessary due to the way ant treats empty filelists @@ -528,6 +529,11 @@ if "table" == type(buildSettings) then initialSystemUiVisibility = buildSettings.android.initialSystemUiVisibility end + -- Fetch the "EdgeToEdge" flag used to set the edge to edge before the splashScreen is shown. + if type(buildSettings.android.edgeToEdge) == "boolean" then + edgeToEdge = buildSettings.android.edgeToEdge + end + -- Fetch a flag indicating if Corona's FileContentProvider should provide public read-only access to files. if type(buildSettings.android.allowAppsReadOnlyAccessToFiles) == "boolean" then allowAppsReadOnlyAccessToFiles = buildSettings.android.allowAppsReadOnlyAccessToFiles @@ -714,6 +720,16 @@ if initialSystemUiVisibility then end manifestKeys.USER_INITIAL_SYSTEM_UI_VISIBILITY = stringBuffer + +-- Create a meta-data tag for the "Edge to Edge" setting, if provided. +stringBuffer = "" +if edgeToEdge then + stringBuffer = '' +else + stringBuffer = '' +end +manifestKeys.USER_EDGE_TO_EDGE = stringBuffer + -- Create a "largeHeap" application tag attribute if set. stringBuffer = "" if largeHeap == true then