From b77fc22371623f50d0ed53e24cc4a821ec58b28c Mon Sep 17 00:00:00 2001 From: Synced Synapse Date: Thu, 16 Nov 2023 16:13:19 +0000 Subject: [PATCH] Upgrade to Android 13, Sdk Version 33 (#985) - Add notification permission to manifest, though it is not strickly needed as all notifications are attached to a MediaSession and those are exempt from Android's 13 new requirements on notification permissions https://developer.android.com/develop/ui/views/notifications/notification-permission - Use granular media permissions, switching from READ_EXTERNAL_STORAGE to READ_MEDIA_{IMAGES|VIDEO|AUDIO} https://developer.android.com/about/versions/13/behavior-changes-13#granular-media-permissions --- app/build.gradle | 2 +- app/src/main/AndroidManifest.xml | 12 ++++- .../localfile/LocalMediaFileListFragment.java | 53 ++++++++++--------- .../main/java/org/xbmc/kore/utils/Utils.java | 8 +-- 4 files changed, 44 insertions(+), 31 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 48d89ecc7..902c87291 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -15,7 +15,7 @@ android { defaultConfig { applicationId "org.xbmc.kore" minSdkVersion 24 - targetSdkVersion 32 + targetSdkVersion 33 versionCode 31 versionName = getVersionName() testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner' diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index fd7465cbb..0e73631ea 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -9,9 +9,19 @@ + + - + + + + + diff --git a/app/src/main/java/org/xbmc/kore/ui/sections/localfile/LocalMediaFileListFragment.java b/app/src/main/java/org/xbmc/kore/ui/sections/localfile/LocalMediaFileListFragment.java index 6a76c6c16..692eab1d8 100644 --- a/app/src/main/java/org/xbmc/kore/ui/sections/localfile/LocalMediaFileListFragment.java +++ b/app/src/main/java/org/xbmc/kore/ui/sections/localfile/LocalMediaFileListFragment.java @@ -51,10 +51,10 @@ import org.xbmc.kore.jsonrpc.type.PlayerType; import org.xbmc.kore.jsonrpc.type.PlaylistType; import org.xbmc.kore.ui.AbstractListFragment; -import org.xbmc.kore.ui.viewgroups.GridRecyclerView; import org.xbmc.kore.utils.CharacterDrawable; import org.xbmc.kore.utils.LogUtils; import org.xbmc.kore.utils.UIUtils; +import org.xbmc.kore.utils.Utils; import java.io.File; import java.io.IOException; @@ -82,13 +82,10 @@ public class LocalMediaFileListFragment extends AbstractListFragment { private LocalFileLocation currentDirLocation = null; // Permission check callback - private final ActivityResultLauncher filesPermissionLauncher = - registerForActivityResult(new ActivityResultContracts.RequestPermission(), isGranted -> { - if (isGranted) { - browseDirectory(currentDirLocation); - } else { - showStatusMessage(null, getString(R.string.read_storage_permission_denied)); - } + private final ActivityResultLauncher filesPermissionLauncher = + registerForActivityResult(new ActivityResultContracts.RequestMultiplePermissions(), permissionsGranted -> { + // Call on refresh, which checks if premissions were granted and shows results + onRefresh(); }); @Override @@ -107,7 +104,7 @@ public void onCreate(@Nullable Bundle savedInstanceState) { rootPath = (args != null)? args.getString(ROOT_PATH) : (savedInstanceState != null) ? - savedInstanceState.getParcelable(ROOT_PATH) : + savedInstanceState.getString(ROOT_PATH) : Environment.getExternalStorageDirectory().getAbsolutePath(); if (rootPath != null && !rootPath.endsWith("/")) rootPath += "/"; currentDirLocation = (savedInstanceState != null) ? @@ -123,7 +120,7 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat @Override public void onStart() { super.onStart(); - if (checkReadStoragePermission()) + if (checkReadStoragePermission(true)) browseDirectory(currentDirLocation); } @@ -136,7 +133,11 @@ public void onSaveInstanceState(@NonNull Bundle outState) { @Override public void onRefresh() { - browseDirectory(currentDirLocation); + if (checkReadStoragePermission(false)){ + browseDirectory(currentDirLocation); + } else { + showStatusMessage(null, getString(R.string.read_storage_permission_denied)); + } hideRefreshAnimation(); } @@ -167,12 +168,18 @@ public void onConnectionStatusSuccess() {} @Override public void onConnectionStatusNoResultsYet() {} - private boolean checkReadStoragePermission() { - boolean hasStoragePermission = - ContextCompat.checkSelfPermission(requireContext(), Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED; + private boolean checkReadStoragePermission(boolean askIfNotGranted) { + String[] permissions = Utils.isTiramisuOrLater() ? + new String[]{Manifest.permission.READ_MEDIA_AUDIO, + Manifest.permission.READ_MEDIA_VIDEO, + Manifest.permission.READ_MEDIA_IMAGES} : + new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}; - if (!hasStoragePermission) { - filesPermissionLauncher.launch(Manifest.permission.READ_EXTERNAL_STORAGE); + boolean hasStoragePermission = Arrays.stream(permissions) + .allMatch(p -> ContextCompat.checkSelfPermission(requireContext(), p) == PackageManager.PERMISSION_GRANTED); + + if (!hasStoragePermission && askIfNotGranted) { + filesPermissionLauncher.launch(permissions); } return hasStoragePermission; } @@ -200,7 +207,7 @@ public boolean navigateToParentDir() { } public boolean isRootDirectory(LocalFileLocation dir) { - return dir.fullPath.equals(rootPath); + return (dir.fullPath != null) && (dir.fullPath.equals(rootPath)); } /** @@ -333,10 +340,8 @@ public void onError(int errorCode, String description) { */ public static String getParentDirectory(final String path) { String p = path; - String pathSymbol = "/"; // unix style - if (path.contains("\\")) { - pathSymbol = "\\"; // windows style - } + // windows / unix style + String pathSymbol = (path.contains("\\")) ? "\\" : "/"; // if path ends with /, remove it before removing the directory name if (path.endsWith(pathSymbol)) { @@ -357,10 +362,8 @@ public static String getParentDirectory(final String path) { */ public static String getFilenameFromPath(final String path) { String p = path; - String pathSymbol = "/"; // unix style - if (path.contains("\\")) { - pathSymbol = "\\"; // windows style - } + // windows / unix style + String pathSymbol = (path.contains("\\")) ? "\\" : "/"; // if path ends with /, remove it if (path.endsWith(pathSymbol)) { p = path.substring(0, path.length() - 1); diff --git a/app/src/main/java/org/xbmc/kore/utils/Utils.java b/app/src/main/java/org/xbmc/kore/utils/Utils.java index bd1f4bfa5..b4719c2b4 100644 --- a/app/src/main/java/org/xbmc/kore/utils/Utils.java +++ b/app/src/main/java/org/xbmc/kore/utils/Utils.java @@ -27,10 +27,6 @@ import android.os.Build; import android.text.TextUtils; -import androidx.preference.PreferenceManager; - -import org.xbmc.kore.Settings; - import java.util.List; import java.util.Locale; @@ -52,6 +48,10 @@ public static boolean isSOrLater() { return Build.VERSION.SDK_INT >= Build.VERSION_CODES.S; } + public static boolean isTiramisuOrLater() { + return Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU; + } + /** * Concats a list of strings * @param list List to concatenate