1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2025-12-10 09:32:29 +01:00

Update android targetsdk to 36 (#24843)

* Update targetsdk to 36

* Combine duplicate code into a method

* Update dependencies and cmake

* Update Android base image

* Add TODO note above all file access intent

---------

Co-authored-by: Michał Janiszewski <janisozaur@gmail.com>
This commit is contained in:
Ethan O'Brien
2025-08-02 04:26:33 -05:00
committed by GitHub
parent b8e163ffcf
commit 9b2657ac62
8 changed files with 74 additions and 36 deletions

View File

@@ -605,7 +605,7 @@ jobs:
name: Android
runs-on: ubuntu-latest
needs: [check-code-formatting, build_variables]
container: openrct2/openrct2-build:18-android
container: openrct2/openrct2-build:20-android
steps:
- name: Checkout
uses: actions/checkout@v4

View File

@@ -6,6 +6,7 @@
- Improved: [#24812] Taiwan Park has been added to the Extras tab if it is present.
- Improved: [OpenSFX#12] Add Brake Fix, Buy and Dinghy Slide running sounds.
- Change: [#24730] Security guards now only walk slowly in crowded areas.
- Change: [#24843] Update android targetSDK to 36.
- Fix: [#24598] Cannot load .park files that use official legacy footpaths by accident.
- Fix: [#24611] The confirmation prompt for track file deletion is not vertically aligned.
- Fix: [#24711] The map smoothing function only partially works for custom height map image files.

View File

@@ -1,14 +1,13 @@
apply plugin: 'com.android.application'
android {
compileSdk 35
buildToolsVersion "35.0.0"
ndkVersion "27.2.12479018" // Latest r27c (LTS), to be synced with CI container image
compileSdk 36
ndkVersion "27.3.13750724" // Latest r27d (LTS), to be synced with CI container image
namespace "io.openrct2"
defaultConfig {
applicationId 'io.openrct2'
minSdkVersion 24
targetSdkVersion 28
targetSdkVersion 36
versionCode 12
versionName '0.4.24'
@@ -35,6 +34,7 @@ android {
}
externalNativeBuild {
cmake {
version "4.0.3"
path 'src/main/CMakeLists.txt'
}
}
@@ -45,8 +45,12 @@ android {
}
dependencies {
implementation 'commons-io:commons-io:2.13.0'
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'commons-io:commons-io:2.20.0'
implementation 'androidx.appcompat:appcompat:1.7.1'
implementation fileTree(include: ['*.jar'], dir: 'libs')
}
configurations.implementation {
exclude group: 'org.jetbrains.kotlin', module: 'kotlin-stdlib-jdk8'
}

View File

@@ -1,10 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
tools:ignore="ScopedStorage" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
tools:ignore="ScopedStorage" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
tools:ignore="ScopedStorage" />
<application
android:name=".OpenRCT2App"
@@ -13,7 +18,7 @@
android:label="@string/app_name"
android:largeHeap="true"
android:theme="@style/AppTheme.Splash"
android:requestLegacyExternalStorage="true">
tools:targetApi="36">
<activity
android:name=".MainActivity"
android:theme="@style/AppTheme.Splash"

View File

@@ -1,5 +1,6 @@
package io.openrct2;
import android.annotation.SuppressLint;
import android.icu.util.Currency;
import android.icu.util.LocaleData;
import android.icu.util.ULocale;
@@ -16,13 +17,16 @@ public class GameActivity extends SDLActivity {
return getResources().getDisplayMetrics().density;
}
public String getDefaultLocale(String[] supportedTags) {
Locale deviceLocale;
@SuppressLint("ObsoleteSdkInt")
private Locale getDeviceLocale() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
deviceLocale = getResources().getConfiguration().getLocales().get(0);
return getResources().getConfiguration().getLocales().get(0);
} else {
deviceLocale = getResources().getConfiguration().locale;
return getResources().getConfiguration().locale;
}
}
public String getDefaultLocale(String[] supportedTags) {
Locale deviceLocale = getDeviceLocale();
for (String supportedTag : supportedTags) {
if (supportedTag.isEmpty()) continue;
@@ -51,26 +55,19 @@ public class GameActivity extends SDLActivity {
}
public String getLocaleCurrency() {
Locale deviceLocale;
Locale deviceLocale = getDeviceLocale();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
deviceLocale = getResources().getConfiguration().getLocales().get(0);
return Currency.getInstance(deviceLocale).getCurrencyCode();
} else {
deviceLocale = getResources().getConfiguration().locale;
return java.util.Currency.getInstance(deviceLocale).getCurrencyCode();
}
}
public boolean isImperialLocaleMeasurementFormat() {
Locale deviceLocale;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
return LocaleData.getMeasurementSystem(ULocale.forLocale(getResources().getConfiguration().getLocales().get(0))) == LocaleData.MeasurementSystem.US;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
deviceLocale = getResources().getConfiguration().getLocales().get(0);
} else {
deviceLocale = getResources().getConfiguration().locale;
}
Locale deviceLocale = getDeviceLocale();
String localeCountry = deviceLocale.getCountry();
return localeCountry.equals(Locale.US.getCountry()) || localeCountry.equals(new Locale("xx", "LR").getCountry()) || localeCountry.equals(new Locale("xx", "MM").getCountry());
}

View File

@@ -6,6 +6,7 @@ import android.content.pm.PackageManager;
import android.content.res.AssetManager;
import android.graphics.Point;
import android.graphics.PointF;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
@@ -94,22 +95,52 @@ public class MainActivity extends AppCompatActivity {
super.onStart();
if (!hasRequiredPermissions()) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
/*
TODO - This is a temporary solution
Ideally, OpenRCT2 assets should be shipped in the apk and we should ask
the user for their rct2 assets directory on boot (similar to windows).
Save data should be stored under the "external data directory",
which you can get via `getExternalFilesDir(null).getAbsolutePath()`
*/
Intent intent = new Intent(android.provider.Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION);
intent.addCategory("android.intent.category.DEFAULT");
intent.setData(Uri.fromParts("package", getPackageName(), null));
startActivity(intent);
} else {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
}
} else {
startGame();
}
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 0) {
if (!hasRequiredPermissions()) {
Log.d(TAG, "User denied storage permission!");
} else {
startGame();
}
}
}
private boolean hasRequiredPermissions() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_DENIED) {
return false;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
return Environment.isExternalStorageManager();
} else {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_DENIED) {
return false;
}
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_DENIED) {
return false;
}
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_DENIED) {
return false;
}
return true;
return true;
}
}
private void startGame() {
@@ -162,7 +193,7 @@ public class MainActivity extends AppCompatActivity {
for (String fileName : list) {
// This ternary expression makes sure that this string does not begin with a slash
String destination = destPath + (destPath.equals("") ? "" : File.separator) + fileName;
String destination = destPath + (destPath.isEmpty() ? "" : File.separator) + fileName;
copyAsset(assets, srcPath + File.separator + fileName, dataDir, destination);
}
}

View File

@@ -6,7 +6,7 @@ buildscript {
google()
}
dependencies {
classpath 'com.android.tools.build:gradle:8.7.3'
classpath 'com.android.tools.build:gradle:8.11.1'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
@@ -20,6 +20,6 @@ allprojects {
}
}
task clean(type: Delete) {
tasks.register('clean', Delete) {
delete rootProject.buildDir
}

View File

@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME