Fixed: Set minSdkVersion and maxSdkVersion depending on apk bootstrap variant and abort bootstrap installation if trying to install wrong variant

- `apt-android-7` variant will set `minSdkVersion=24` (Android `7.0`) and bootstrap installation will fail if installing on Android `< 7`. Normally, APK installation will fail with `INSTALL_FAILED_OLDER_SDK` if trying to install on an old version, or if APK is manually installed in `/data/app`, it should fail to run and app will be disabled/removed on reboot.
- `apt-android-5` variant will set `minSdkVersion=21` (Android `5.0`) and `maxSdkVersion=23` (Android `6.0`) and bootstrap installation will fail if installing on Android `>= 7`. Android does not care for `maxSdkVersion` value and will still allow installation on higher Android versions as the OS provides backward compatibility for apps, but Termux packages do not provide that, so must not be installed on higher Android versions.

This should solve the issue for `0.119.0*` releases showing on F-Droid for Android `5`/`6` users as previously the `apt-android-7` variant was still using `minSdkVersion=21`. Android `5`/`6` releases with `apt-android-5` variant are only to be provided from GitHub.
This commit is contained in:
agnostic-apollo
2025-03-28 13:12:58 +05:00
parent 97f2537c31
commit 46cd514343
3 changed files with 68 additions and 3 deletions

View File

@@ -10,6 +10,13 @@ ext {
// by replacing $PREFIX since app code is dependant on the variant used to build the APK.
// Currently supported values are: [ "apt-android-7" "apt-android-5" ]
packageVariant = System.getenv("TERMUX_PACKAGE_VARIANT") ?: "apt-android-7" // Default: "apt-android-7"
bootstrapMinSdk = packageVariant == "apt-android-5" ? 21 : 24
bootstrapMinRelease = packageVariant == "apt-android-5" ? "5.0" : "7.0"
bootstrapMaxSdk = packageVariant == "apt-android-5" ? 23 : null
bootstrapMaxRelease = packageVariant == "apt-android-5" ? "6.0" : null
buildMinSdk = bootstrapMinSdk
buildTargetSdk = project.properties.targetSdkVersion.toInteger()
}
android {
@@ -39,14 +46,20 @@ android {
defaultConfig {
applicationId "com.termux"
minSdkVersion project.properties.minSdkVersion.toInteger()
targetSdkVersion project.properties.targetSdkVersion.toInteger()
minSdk buildMinSdk
targetSdk buildTargetSdk
versionCode 1020
versionName "0.119.0-beta.1"
if (appVersionName) versionName = appVersionName
validateVersionName(versionName)
buildConfigField "Integer", "TERMUX_APP__BOOTSTRAP_MIN_SDK", project.ext.bootstrapMinSdk.toString()
buildConfigField "String", "TERMUX_APP__BOOTSTRAP_MIN_RELEASE",
project.ext.bootstrapMinRelease ? "\"" + project.ext.bootstrapMinRelease + "\"" : "null"
buildConfigField "Integer", "TERMUX_APP__BOOTSTRAP_MAX_SDK", project.ext.bootstrapMaxSdk.toString()
buildConfigField "String", "TERMUX_APP__BOOTSTRAP_MAX_RELEASE",
project.ext.bootstrapMaxRelease ? "\"" + project.ext.bootstrapMaxRelease + "\"" : "null"
buildConfigField "String", "TERMUX_PACKAGE_VARIANT", "\"" + project.ext.packageVariant + "\"" // Used by TermuxApplication class
manifestPlaceholders.TERMUX_PACKAGE_NAME = "com.termux"

View File

@@ -10,10 +10,12 @@ import android.system.Os;
import android.util.Pair;
import android.view.WindowManager;
import com.termux.BuildConfig;
import com.termux.R;
import com.termux.shared.file.FileUtils;
import com.termux.shared.shell.command.ExecutionCommand;
import com.termux.shared.shell.command.runner.app.AppShell;
import com.termux.shared.termux.TermuxBootstrap;
import com.termux.shared.termux.crash.TermuxCrashUtils;
import com.termux.shared.termux.file.TermuxFileUtils;
import com.termux.shared.interact.MessageDialogUtils;
@@ -104,6 +106,12 @@ final class TermuxInstaller {
return;
}
if (!checkIfMinOrMaxSdkVersionIsIncompatible(activity,
BuildConfig.TERMUX_APP__BOOTSTRAP_MIN_SDK, BuildConfig.TERMUX_APP__BOOTSTRAP_MIN_RELEASE,
BuildConfig.TERMUX_APP__BOOTSTRAP_MAX_SDK, BuildConfig.TERMUX_APP__BOOTSTRAP_MAX_RELEASE)) {
return;
}
// If prefix directory exists, even if its a symlink to a valid directory and symlink is not broken/dangling
if (FileUtils.directoryFileExists(TERMUX_PREFIX_DIR_PATH, true)) {
if (TermuxFileUtils.isTermuxPrefixDirectoryEmpty()) {
@@ -271,6 +279,42 @@ final class TermuxInstaller {
}.start();
}
public static boolean checkIfMinOrMaxSdkVersionIsIncompatible(Activity activity,
Integer minSdk, String minRelease,
Integer maxSdk, String maxRelease) {
if (minSdk != null && Build.VERSION.SDK_INT < minSdk) {
String bootstrapErrorMessage = activity.getString(R.string.bootstrap_error_apk_bootstrap_variant_min_sdk_incompatible,
MarkdownUtils.getMarkdownCodeForString(TermuxBootstrap.TERMUX_APP_PACKAGE_VARIANT.getName(), false),
MarkdownUtils.getMarkdownCodeForString(Build.VERSION.RELEASE, false),
Build.VERSION.SDK_INT,
MarkdownUtils.getMarkdownCodeForString(minRelease, false),
minSdk);
Logger.logError(LOG_TAG, bootstrapErrorMessage);
sendBootstrapCrashReportNotification(activity, bootstrapErrorMessage);
MessageDialogUtils.exitAppWithErrorMessage(activity,
activity.getString(R.string.bootstrap_error_title),
bootstrapErrorMessage);
return false;
}
if (maxSdk != null && Build.VERSION.SDK_INT > maxSdk) {
String bootstrapErrorMessage = activity.getString(R.string.bootstrap_error_apk_bootstrap_variant_max_sdk_incompatible,
MarkdownUtils.getMarkdownCodeForString(TermuxBootstrap.TERMUX_APP_PACKAGE_VARIANT.getName(), false),
MarkdownUtils.getMarkdownCodeForString(Build.VERSION.RELEASE, false),
Build.VERSION.SDK_INT,
MarkdownUtils.getMarkdownCodeForString(maxRelease, false),
maxSdk);
Logger.logError(LOG_TAG, bootstrapErrorMessage);
sendBootstrapCrashReportNotification(activity, bootstrapErrorMessage);
MessageDialogUtils.exitAppWithErrorMessage(activity,
activity.getString(R.string.bootstrap_error_title),
bootstrapErrorMessage);
return false;
}
return true;
}
public static void showBootstrapErrorDialog(Activity activity, Runnable whenDone, String message) {
Logger.logErrorExtended(LOG_TAG, "Bootstrap Error:\n" + message);

View File

@@ -27,10 +27,18 @@
<!-- Termux Bootstrap Packages Installation -->
<string name="bootstrap_installer_body">Installing bootstrap packages…</string>
<string name="bootstrap_error_title">Unable to install bootstrap</string>
<string name="bootstrap_error_title">&TERMUX_APP_NAME; Bootstrap Error</string>
<string name="bootstrap_error_body">&TERMUX_APP_NAME; was unable to install the bootstrap packages.</string>
<string name="bootstrap_error_abort">Abort</string>
<string name="bootstrap_error_try_again">Try again</string>
<string name="bootstrap_error_apk_bootstrap_variant_min_sdk_incompatible">The APK bootstrap variant %1$s
of currently installed &TERMUX_APP_NAME; app is not compatible with the Android version %2$s
(sdk `%3$d`) of the device and it requires minimum Android version %4$s (sdk `%5$d`).
\n\nUninstall the &TERMUX_APP_NAME; app and reinstall the correct APK build variant.</string>
<string name="bootstrap_error_apk_bootstrap_variant_max_sdk_incompatible">The APK bootstrap variant %1$s
of currently installed &TERMUX_APP_NAME; app is not compatible with the Android version %2$s
(sdk `%3$d`) of the device and it requires maximum Android version %4$s (sdk `%5$d`).
\n\nUninstall the &TERMUX_APP_NAME; app and reinstall the correct APK build variant.</string>
<string name="bootstrap_error_not_primary_user_message">&TERMUX_APP_NAME; can only be run as the primary user.
\nBootstrap binaries compiled for &TERMUX_APP_NAME; have hardcoded $PREFIX path and cannot be installed
under any path other than:\n%1$s.</string>