From 23457854b7d7044ea5e825bdaaffff28b1afe21f Mon Sep 17 00:00:00 2001 From: Sylvia van Os Date: Thu, 1 Jan 2026 17:16:45 +0100 Subject: [PATCH] Remove Android 5 support Newer dependencies need at least Android 6, so no use in keeping this --- .github/workflows/android.yml | 4 +-- app/build.gradle.kts | 2 +- .../card_locker/CatimaAppCompatActivity.java | 16 +++-------- .../java/protect/card_locker/ListWidget.kt | 3 +-- .../protect/card_locker/PermissionUtils.java | 27 +++---------------- .../java/protect/card_locker/ScanActivity.kt | 8 ------ .../java/protect/card_locker/UCropWrapper.kt | 13 +++------ .../contentprovider/CardsContentProvider.java | 7 ----- .../importexport/CatimaImporter.java | 1 + .../preferences/SettingsActivity.kt | 6 ----- 10 files changed, 16 insertions(+), 71 deletions(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index ac21c24dd9..0231ad224f 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -50,10 +50,10 @@ jobs: echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules sudo udevadm control --reload-rules sudo udevadm trigger --name-match=kvm - - name: Run instrumented tests (API 21) + - name: Run instrumented tests (API 23) uses: ReactiveCircus/android-emulator-runner@v2 with: - api-level: 21 + api-level: 23 arch: x86_64 script: ./gradlew connected${{ matrix.flavor }}DebugAndroidTest - name: Run instrumented tests (API 35) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 120b207bc8..ccd8159dfb 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -17,7 +17,7 @@ android { defaultConfig { applicationId = "me.hackerchick.catima" - minSdk = 21 + minSdk = 23 targetSdk = 36 versionCode = 158 versionName = "2.41.1" diff --git a/app/src/main/java/protect/card_locker/CatimaAppCompatActivity.java b/app/src/main/java/protect/card_locker/CatimaAppCompatActivity.java index c44a19fc4a..50f5dd852b 100644 --- a/app/src/main/java/protect/card_locker/CatimaAppCompatActivity.java +++ b/app/src/main/java/protect/card_locker/CatimaAppCompatActivity.java @@ -38,15 +38,10 @@ protected void onPostCreate(@Nullable Bundle savedInstanceState) { Window window = getWindow(); if (window != null) { boolean darkMode = Utils.isDarkModeEnabled(this); - if (Build.VERSION.SDK_INT >= 23) { - View decorView = window.getDecorView(); - WindowInsetsControllerCompat wic = new WindowInsetsControllerCompat(window, decorView); - wic.setAppearanceLightStatusBars(!darkMode); - window.setStatusBarColor(Color.TRANSPARENT); - } else { - // icons are always white back then - window.setStatusBarColor(darkMode ? Color.TRANSPARENT : Color.argb(127, 0, 0, 0)); - } + View decorView = window.getDecorView(); + WindowInsetsControllerCompat wic = new WindowInsetsControllerCompat(window, decorView); + wic.setAppearanceLightStatusBars(!darkMode); + window.setStatusBarColor(Color.TRANSPARENT); } // XXX android 9 and below has a nasty rendering bug if the theme was patched earlier Utils.postPatchColors(this); @@ -66,7 +61,4 @@ protected void enableToolbarBackButton() { actionBar.setDisplayHomeAsUpEnabled(true); } } - - public void onMockedRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { - } } diff --git a/app/src/main/java/protect/card_locker/ListWidget.kt b/app/src/main/java/protect/card_locker/ListWidget.kt index 3a741fcb60..d6242eca7d 100644 --- a/app/src/main/java/protect/card_locker/ListWidget.kt +++ b/app/src/main/java/protect/card_locker/ListWidget.kt @@ -100,8 +100,7 @@ class ListWidget : AppWidgetProvider() { val foreground = if (Utils.needsDarkForeground(headerColor)) Color.BLACK else Color.WHITE setInt(R.id.item_container_foreground, "setBackgroundColor", headerColor) val icon = loyaltyCard.getImageThumbnail(context) - // setImageViewIcon is not supported on Android 5, so force Android 5 down the text path - // FIXME: The icon flow causes a crash up to Android 12L, so SDK_INT is forced up from 23 to 33 + // FIXME: The icon flow causes a crash up to Android 12L, so force anything below 33 down this path if (icon != null && Build.VERSION.SDK_INT >= 32) { setInt(R.id.item_container_foreground, "setBackgroundColor", foreground) setImageViewIcon(R.id.item_image, Icon.createWithBitmap(icon)) diff --git a/app/src/main/java/protect/card_locker/PermissionUtils.java b/app/src/main/java/protect/card_locker/PermissionUtils.java index 71cf75f523..583da8e14d 100644 --- a/app/src/main/java/protect/card_locker/PermissionUtils.java +++ b/app/src/main/java/protect/card_locker/PermissionUtils.java @@ -34,11 +34,6 @@ private static boolean needsStorageReadPermission(Activity activity) { * @return */ public static boolean needsCameraPermission(Activity activity) { - // Android only introduced the runtime permission system in Marshmallow (Android 6.0) - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { - return false; - } - return ContextCompat.checkSelfPermission(activity, android.Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED; } @@ -49,21 +44,14 @@ public static boolean needsCameraPermission(Activity activity) { * @param activity * @param requestCode */ - public static void requestStorageReadPermission(CatimaAppCompatActivity activity, int requestCode) { + public static void requestStorageReadPermission(Activity activity, int requestCode) { String[] permissions = new String[]{ android.Manifest.permission.READ_EXTERNAL_STORAGE }; int[] mockedResults = new int[]{ PackageManager.PERMISSION_GRANTED }; if (needsStorageReadPermission(activity)) { ActivityCompat.requestPermissions(activity, permissions, requestCode); } else { - // FIXME: This points to onMockedRequestPermissionResult instead of to - // onRequestPermissionResult because onRequestPermissionResult was only introduced in - // Android 6.0 (SDK 23) and we and to support Android 5.0 (SDK 21) too. - // - // When minSdk becomes 23, this should point to onRequestPermissionResult directly and - // the activity input variable should be changed from CatimaAppCompatActivity to - // Activity. - activity.onMockedRequestPermissionsResult(requestCode, permissions, mockedResults); + activity.onRequestPermissionsResult(requestCode, permissions, mockedResults); } } @@ -74,21 +62,14 @@ public static void requestStorageReadPermission(CatimaAppCompatActivity activity * @param activity * @param requestCode */ - public static void requestCameraPermission(CatimaAppCompatActivity activity, int requestCode) { + public static void requestCameraPermission(Activity activity, int requestCode) { String[] permissions = new String[]{ Manifest.permission.CAMERA }; int[] mockedResults = new int[]{ PackageManager.PERMISSION_GRANTED }; if (needsCameraPermission(activity)) { ActivityCompat.requestPermissions(activity, permissions, requestCode); } else { - // FIXME: This points to onMockedRequestPermissionResult instead of to - // onRequestPermissionResult because onRequestPermissionResult was only introduced in - // Android 6.0 (SDK 23) and we and to support Android 5.0 (SDK 21) too. - // - // When minSdk becomes 23, this should point to onRequestPermissionResult directly and - // the activity input variable should be changed from CatimaAppCompatActivity to - // Activity. - activity.onMockedRequestPermissionsResult(requestCode, permissions, mockedResults); + activity.onRequestPermissionsResult(requestCode, permissions, mockedResults); } } } \ No newline at end of file diff --git a/app/src/main/java/protect/card_locker/ScanActivity.kt b/app/src/main/java/protect/card_locker/ScanActivity.kt index 52beb68eaf..952dac3c30 100644 --- a/app/src/main/java/protect/card_locker/ScanActivity.kt +++ b/app/src/main/java/protect/card_locker/ScanActivity.kt @@ -543,14 +543,6 @@ class ScanActivity : CatimaAppCompatActivity() { ) { super.onRequestPermissionsResult(requestCode, permissions, grantResults) - onMockedRequestPermissionsResult(requestCode, permissions, grantResults) - } - - override fun onMockedRequestPermissionsResult( - requestCode: Int, - permissions: Array, - grantResults: IntArray - ) { val granted = grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED diff --git a/app/src/main/java/protect/card_locker/UCropWrapper.kt b/app/src/main/java/protect/card_locker/UCropWrapper.kt index caa326c763..352fb52665 100644 --- a/app/src/main/java/protect/card_locker/UCropWrapper.kt +++ b/app/src/main/java/protect/card_locker/UCropWrapper.kt @@ -40,16 +40,9 @@ class UCropWrapper : UCropActivity() { return } - if (Build.VERSION.SDK_INT >= 23) { - val decorView = window.decorView - val wic = WindowInsetsControllerCompat(window, decorView) - wic.isAppearanceLightStatusBars = !darkMode - } else if (!darkMode) { - window.statusBarColor = ColorUtils.compositeColors( - Color.argb(127, 0, 0, 0), - window.statusBarColor - ) - } + val decorView = window.decorView + val wic = WindowInsetsControllerCompat(window, decorView) + wic.isAppearanceLightStatusBars = !darkMode } private fun checkViews(darkMode: Boolean) { diff --git a/app/src/main/java/protect/card_locker/contentprovider/CardsContentProvider.java b/app/src/main/java/protect/card_locker/contentprovider/CardsContentProvider.java index 77c6ccb37a..04807eb245 100644 --- a/app/src/main/java/protect/card_locker/contentprovider/CardsContentProvider.java +++ b/app/src/main/java/protect/card_locker/contentprovider/CardsContentProvider.java @@ -77,13 +77,6 @@ public Cursor query(@NonNull final Uri uri, @Nullable final String selection, @Nullable final String[] selectionArgs, @Nullable final String sortOrder) { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { - // Disable the content provider on SDK < 23 since it grants dangerous - // permissions at install-time - Log.w(TAG, "Content provider read is only available for SDK >= 23"); - return null; - } - final Settings settings = new Settings(getContext()); if (!settings.getAllowContentProviderRead()) { Log.w(TAG, "Content provider read is disabled"); diff --git a/app/src/main/java/protect/card_locker/importexport/CatimaImporter.java b/app/src/main/java/protect/card_locker/importexport/CatimaImporter.java index a6567dd44e..82af0f1dd3 100644 --- a/app/src/main/java/protect/card_locker/importexport/CatimaImporter.java +++ b/app/src/main/java/protect/card_locker/importexport/CatimaImporter.java @@ -459,6 +459,7 @@ private LoyaltyCard importLoyaltyCard(CSVRecord record) throws FormatException { barcodeType = CatimaBarcode.fromName(unparsedBarcodeType); } + // This field did not exist in version 2.40.0 and before Charset barcodeEncoding = null; String unparsedBarcodeEncoding = CSVHelpers.extractString(DBHelper.LoyaltyCardDbIds.BARCODE_ENCODING, record, ""); if (!unparsedBarcodeEncoding.isEmpty()) { diff --git a/app/src/main/java/protect/card_locker/preferences/SettingsActivity.kt b/app/src/main/java/protect/card_locker/preferences/SettingsActivity.kt index 06b7377ecb..8d48320d22 100644 --- a/app/src/main/java/protect/card_locker/preferences/SettingsActivity.kt +++ b/app/src/main/java/protect/card_locker/preferences/SettingsActivity.kt @@ -157,12 +157,6 @@ class SettingsActivity : CatimaAppCompatActivity() { true } - // Disable content provider on SDK < 23 since dangerous permissions - // are granted at install-time - val contentProviderReadPreference = findPreference(getString(R.string.settings_key_allow_content_provider_read)) - contentProviderReadPreference!!.isVisible = - Build.VERSION.SDK_INT >= Build.VERSION_CODES.M - // Hide crash reporter settings on builds it's not enabled on val crashReporterPreference = findPreference("acra.enable") crashReporterPreference!!.isVisible = BuildConfig.useAcraCrashReporter