diff --git a/app/src/main/java/protect/card_locker/CardsOnPowerScreenService.java b/app/src/main/java/protect/card_locker/CardsOnPowerScreenService.java index c86c62d251..9cce5a1e25 100644 --- a/app/src/main/java/protect/card_locker/CardsOnPowerScreenService.java +++ b/app/src/main/java/protect/card_locker/CardsOnPowerScreenService.java @@ -137,7 +137,7 @@ public void performControlAction(@NonNull String controlId, @NonNull ControlActi closePowerScreenOnAndroid11(); } - @SuppressLint({"MissingPermission", "deprecation"}) + @SuppressWarnings({"MissingPermission", "deprecation"}) private void closePowerScreenOnAndroid11() { // Android 12 will auto-close the power screen, but earlier versions won't // Lint complains about this but on Android 11 the permission is not needed diff --git a/app/src/main/java/protect/card_locker/CatimaAppCompatActivity.java b/app/src/main/java/protect/card_locker/CatimaAppCompatActivity.java index 8fc5d9409e..37cd5671ac 100644 --- a/app/src/main/java/protect/card_locker/CatimaAppCompatActivity.java +++ b/app/src/main/java/protect/card_locker/CatimaAppCompatActivity.java @@ -8,6 +8,7 @@ import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; +import androidx.core.view.WindowInsetsControllerCompat; public class CatimaAppCompatActivity extends AppCompatActivity { @Override @@ -29,8 +30,10 @@ protected void onPostCreate(@Nullable Bundle savedInstanceState) { // XXX changing this in onCreate causes issues with the splash screen activity, so doing this here boolean darkMode = Utils.isDarkModeEnabled(this); if (Build.VERSION.SDK_INT >= 23) { + View decorView = getWindow().getDecorView(); + WindowInsetsControllerCompat wic = new WindowInsetsControllerCompat(getWindow(), decorView); + wic.setAppearanceLightStatusBars(!darkMode); getWindow().setStatusBarColor(Color.TRANSPARENT); - getWindow().getDecorView().setSystemUiVisibility(darkMode ? 0 : View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR); } else { // icons are always white back then getWindow().setStatusBarColor(darkMode ? Color.TRANSPARENT : Color.argb(127, 0, 0, 0)); diff --git a/app/src/main/java/protect/card_locker/LoyaltyCardViewActivity.java b/app/src/main/java/protect/card_locker/LoyaltyCardViewActivity.java index 7ad403bea2..9192d4416f 100644 --- a/app/src/main/java/protect/card_locker/LoyaltyCardViewActivity.java +++ b/app/src/main/java/protect/card_locker/LoyaltyCardViewActivity.java @@ -28,6 +28,8 @@ import android.view.ViewOutlineProvider; import android.view.ViewTreeObserver; import android.view.Window; +import android.view.WindowInsets; +import android.view.WindowInsetsController; import android.view.WindowManager; import android.widget.ImageButton; import android.widget.ImageView; @@ -49,6 +51,8 @@ import androidx.core.graphics.BlendModeCompat; import androidx.core.graphics.ColorUtils; import androidx.core.graphics.drawable.DrawableCompat; +import androidx.core.view.WindowCompat; +import androidx.core.view.WindowInsetsControllerCompat; import androidx.core.widget.TextViewCompat; import com.google.android.material.appbar.AppBarLayout; @@ -189,8 +193,7 @@ private void openCurrentMainImageInGallery() { .setDataAndType(FileProvider.getUriForFile(this, BuildConfig.APPLICATION_ID, file), "image/*") .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); startActivity(intent); - } - catch (ActivityNotFoundException e) { + } catch (ActivityNotFoundException e) { // Display a toast message if an image viewer is not installed on device Toast.makeText(this, R.string.failedLaunchingPhotoPicker, Toast.LENGTH_SHORT).show(); e.printStackTrace(); @@ -610,8 +613,11 @@ public void onResume() { } if (settings.getDisableLockscreenWhileViewingCard()) { - window.addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD | - WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) { + setShowWhenLocked(true); + } else { + showWhenLockedSdkLessThan27(window); + } } window.setAttributes(attributes); @@ -707,7 +713,9 @@ public void onResume() { // Make notification area light if dark icons are needed if (Build.VERSION.SDK_INT >= 23) { - window.getDecorView().setSystemUiVisibility(backgroundNeedsDarkIcons ? View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR : 0); + View decorView = getWindow().getDecorView(); + WindowInsetsControllerCompat wic = new WindowInsetsControllerCompat(getWindow(), decorView); + wic.setAppearanceLightStatusBars(backgroundNeedsDarkIcons); window.setStatusBarColor(Color.TRANSPARENT); } else { // Darken statusbar if icons won't be visible otherwise @@ -748,6 +756,12 @@ public void onResume() { DBHelper.updateLoyaltyCardLastUsed(database, loyaltyCard.id); } + @SuppressWarnings("deprecation") + private void showWhenLockedSdkLessThan27(Window window) { + window.addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD | + WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED); + } + private void fixImageButtonColor(ImageButton imageButton) { imageButton.setColorFilter(BlendModeColorFilterCompat.createBlendModeColorFilterCompat(backgroundNeedsDarkIcons ? Color.BLACK : Color.WHITE, BlendModeCompat.SRC_ATOP)); } @@ -1047,11 +1061,15 @@ private void setFullscreen(boolean enabled) { editButton.setVisibility(View.GONE); // Set Android to fullscreen mode - getWindow().getDecorView().setSystemUiVisibility( - getWindow().getDecorView().getSystemUiVisibility() - | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY - | View.SYSTEM_UI_FLAG_FULLSCREEN - ); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + getWindow().setDecorFitsSystemWindows(false); + if (getWindow().getInsetsController() != null) { + getWindow().getInsetsController().hide(WindowInsets.Type.statusBars() | WindowInsets.Type.navigationBars()); + getWindow().getInsetsController().setSystemBarsBehavior(WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE); + } + } else { + setFullscreenModeSdkLessThan30(); + } } else { Log.d(TAG, "Move out of fullscreen"); @@ -1082,13 +1100,34 @@ private void setFullscreen(boolean enabled) { bottomAppBar.setVisibility(View.VISIBLE); // Unset fullscreen mode - getWindow().getDecorView().setSystemUiVisibility( - getWindow().getDecorView().getSystemUiVisibility() - & ~View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY - & ~View.SYSTEM_UI_FLAG_FULLSCREEN - ); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + getWindow().setDecorFitsSystemWindows(true); + if (getWindow().getInsetsController() != null) { + getWindow().getInsetsController().show(WindowInsets.Type.statusBars() | WindowInsets.Type.navigationBars()); + } + } else { + unsetFullscreenModeSdkLessThan30(); + } } Log.d("setFullScreen", "Is full screen enabled? " + enabled + " Zoom Level = " + barcodeScaler.getProgress()); } + + @SuppressWarnings("deprecation") + private void unsetFullscreenModeSdkLessThan30() { + getWindow().getDecorView().setSystemUiVisibility( + getWindow().getDecorView().getSystemUiVisibility() + & ~View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY + & ~View.SYSTEM_UI_FLAG_FULLSCREEN + ); + } + + @SuppressWarnings("deprecation") + private void setFullscreenModeSdkLessThan30() { + getWindow().getDecorView().setSystemUiVisibility( + getWindow().getDecorView().getSystemUiVisibility() + | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY + | View.SYSTEM_UI_FLAG_FULLSCREEN + ); + } } diff --git a/app/src/main/java/protect/card_locker/UCropWrapper.java b/app/src/main/java/protect/card_locker/UCropWrapper.java index af5f3c07ce..3c5fea3a5f 100644 --- a/app/src/main/java/protect/card_locker/UCropWrapper.java +++ b/app/src/main/java/protect/card_locker/UCropWrapper.java @@ -18,6 +18,7 @@ import androidx.appcompat.widget.AppCompatImageView; import androidx.core.content.ContextCompat; import androidx.core.graphics.ColorUtils; +import androidx.core.view.WindowInsetsControllerCompat; public class UCropWrapper extends UCropActivity { public static final String UCROP_TOOLBAR_TYPEFACE_STYLE = "ucop_toolbar_typeface_style"; @@ -28,7 +29,9 @@ protected void onPostCreate(@Nullable Bundle savedInstanceState) { boolean darkMode = Utils.isDarkModeEnabled(this); // setup status bar to look like the rest of the app if (Build.VERSION.SDK_INT >= 23) { - getWindow().getDecorView().setSystemUiVisibility(darkMode ? 0 : View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR); + View decorView = getWindow().getDecorView(); + WindowInsetsControllerCompat wic = new WindowInsetsControllerCompat(getWindow(), decorView); + wic.setAppearanceLightStatusBars(!darkMode); } else { // icons are always white back then if (!darkMode) { diff --git a/app/src/main/java/protect/card_locker/Utils.java b/app/src/main/java/protect/card_locker/Utils.java index 5db5f5214a..fe98efa7cd 100644 --- a/app/src/main/java/protect/card_locker/Utils.java +++ b/app/src/main/java/protect/card_locker/Utils.java @@ -122,7 +122,7 @@ static public BarcodeValues parseSetBarcodeActivityResult(int requestCode, int r ImageDecoder.Source image_source = ImageDecoder.createSource(context.getContentResolver(), intent.getData()); bitmap = ImageDecoder.decodeBitmap(image_source, (decoder, info, source) -> decoder.setMutableRequired(true)); } else { - bitmap = MediaStore.Images.Media.getBitmap(context.getContentResolver(), intent.getData()); + bitmap = getBitmapSdkLessThan29(intent, context); } } catch (IOException e) { Log.e(TAG, "Error getting data from image file"); @@ -163,6 +163,11 @@ static public BarcodeValues parseSetBarcodeActivityResult(int requestCode, int r throw new UnsupportedOperationException("Unknown request code for parseSetBarcodeActivityResult"); } + @SuppressWarnings("deprecation") + private static Bitmap getBitmapSdkLessThan29(Intent intent, Context context) throws IOException { + return MediaStore.Images.Media.getBitmap(context.getContentResolver(), intent.getData()); + } + static public BarcodeValues getBarcodeFromBitmap(Bitmap bitmap) { // This function is vulnerable to OOM, so we try again with a smaller bitmap is we get OOM for (int i = 0; i < 10; i++) { @@ -396,8 +401,7 @@ static public Context updateBaseContextLocale(Context context) { Resources res = context.getResources(); Configuration configuration = res.getConfiguration(); if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) { - configuration.locale = chosenLocale != null ? chosenLocale : Locale.getDefault(); - res.updateConfiguration(configuration, res.getDisplayMetrics()); + setLocalesSdkLessThan24(chosenLocale, configuration, res); return context; } @@ -407,6 +411,12 @@ static public Context updateBaseContextLocale(Context context) { return context.createConfigurationContext(configuration); } + @SuppressWarnings("deprecation") + private static void setLocalesSdkLessThan24(Locale chosenLocale, Configuration configuration, Resources res) { + configuration.locale = chosenLocale != null ? chosenLocale : Locale.getDefault(); + res.updateConfiguration(configuration, res.getDisplayMetrics()); + } + static public long getUnixTime() { return System.currentTimeMillis() / 1000; } @@ -488,7 +498,7 @@ public static void patchColors(AppCompatActivity activity) { } else { // final catch all in case of invalid theme value from older versions // also handles R.string.settings_key_system_theme - DynamicColors.applyIfAvailable(activity); + DynamicColors.applyToActivityIfAvailable(activity); } if (isDarkModeEnabled(activity) && settings.getOledDark()) { diff --git a/app/src/main/java/protect/card_locker/preferences/SettingsActivity.java b/app/src/main/java/protect/card_locker/preferences/SettingsActivity.java index 4cc47c1a36..25e0226fd5 100644 --- a/app/src/main/java/protect/card_locker/preferences/SettingsActivity.java +++ b/app/src/main/java/protect/card_locker/preferences/SettingsActivity.java @@ -17,9 +17,12 @@ import androidx.appcompat.app.AppCompatDelegate; import androidx.appcompat.widget.Toolbar; import androidx.fragment.app.DialogFragment; +import androidx.fragment.app.FragmentResultListener; import androidx.preference.ListPreference; import androidx.preference.Preference; import androidx.preference.PreferenceFragmentCompat; + +import kotlin.Suppress; import nl.invissvenska.numberpickerpreference.NumberDialogPreference; import nl.invissvenska.numberpickerpreference.NumberPickerPreferenceDialogFragment; import protect.card_locker.CatimaAppCompatActivity; @@ -166,6 +169,11 @@ private void refreshActivity(boolean reloadMain) { } @Override + @SuppressWarnings("deprecation") // setTargetFragment + // androidx.preference.PreferenceDialogFragmentCompat uses the deprecated method + // `getTargetFragment()`, which throws if `setTargetFragment()` isn't used before. + // While this isn't fixed on upstream, suppress the deprecation warning + // https://issuetracker.google.com/issues/181793702 public void onDisplayPreferenceDialog(Preference preference) { if (preference instanceof NumberDialogPreference) { NumberDialogPreference dialogPreference = (NumberDialogPreference) preference;