From 0eb1ab9c38191e1046038d8f1706ee1863584ad7 Mon Sep 17 00:00:00 2001 From: Anggrayudi Hardiannico Date: Sun, 9 Apr 2023 12:21:40 +0700 Subject: [PATCH 1/8] Updated AGP --- build.gradle | 6 +++--- gradle/wrapper/gradle-wrapper.properties | 2 +- sample/build.gradle | 3 ++- sample/src/main/AndroidManifest.xml | 3 +-- storage/build.gradle | 9 +++++---- storage/src/main/AndroidManifest.xml | 3 +-- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/build.gradle b/build.gradle index c56e9ab..64d921d 100644 --- a/build.gradle +++ b/build.gradle @@ -4,11 +4,11 @@ buildscript { addRepos(repositories) - ext.kotlin_version = '1.7.20' + ext.kotlin_version = '1.7.21' dependencies { - classpath 'com.android.tools:r8:3.3.75' - classpath 'com.android.tools.build:gradle:7.3.1' + classpath 'com.android.tools:r8:8.0.40' + classpath 'com.android.tools.build:gradle:7.4.2' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath 'com.vanniktech:gradle-maven-publish-plugin:0.22.0' classpath 'org.jetbrains.dokka:dokka-gradle-plugin:1.7.20' diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index fd3b04d..36fb0fe 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip diff --git a/sample/build.gradle b/sample/build.gradle index 8d070a7..184cd31 100644 --- a/sample/build.gradle +++ b/sample/build.gradle @@ -28,6 +28,7 @@ android { } } + namespace 'com.anggrayudi.storage.sample' defaultConfig { applicationId "com.anggrayudi.storage.sample" multiDexEnabled true @@ -48,7 +49,7 @@ android { } } - lintOptions { + lint { abortOnError false } diff --git a/sample/src/main/AndroidManifest.xml b/sample/src/main/AndroidManifest.xml index 9149141..c30c71a 100644 --- a/sample/src/main/AndroidManifest.xml +++ b/sample/src/main/AndroidManifest.xml @@ -1,7 +1,6 @@ + xmlns:tools="http://schemas.android.com/tools"> + xmlns:tools="http://schemas.android.com/tools"> Date: Sun, 9 Apr 2023 12:59:45 +0700 Subject: [PATCH 2/8] Fixed issue #116 --- .../com/anggrayudi/storage/SimpleStorage.kt | 3 ++- .../storage/file/DocumentFileCompat.kt | 15 ++++++++--- .../com/anggrayudi/storage/file/FileExt.kt | 6 ++++- .../anggrayudi/storage/file/FileFullPath.kt | 27 ++++++++++++++----- 4 files changed, 38 insertions(+), 13 deletions(-) diff --git a/storage/src/main/java/com/anggrayudi/storage/SimpleStorage.kt b/storage/src/main/java/com/anggrayudi/storage/SimpleStorage.kt index ed3accb..f058f1b 100644 --- a/storage/src/main/java/com/anggrayudi/storage/SimpleStorage.kt +++ b/storage/src/main/java/com/anggrayudi/storage/SimpleStorage.kt @@ -563,7 +563,8 @@ class SimpleStorage private constructor(private val wrapper: ComponentWrapper) { private const val KEY_LAST_VISITED_FOLDER = BuildConfig.LIBRARY_PACKAGE_NAME + ".lastVisitedFolder" private const val TAG = "SimpleStorage" - const val KITKAT_SD_CARD_PATH = "/storage/sdcard" + const val KITKAT_SD_CARD_ID = "sdcard" + const val KITKAT_SD_CARD_PATH = "/storage/$KITKAT_SD_CARD_ID" @JvmStatic @Suppress("DEPRECATION") diff --git a/storage/src/main/java/com/anggrayudi/storage/file/DocumentFileCompat.kt b/storage/src/main/java/com/anggrayudi/storage/file/DocumentFileCompat.kt index e736907..6abf04f 100644 --- a/storage/src/main/java/com/anggrayudi/storage/file/DocumentFileCompat.kt +++ b/storage/src/main/java/com/anggrayudi/storage/file/DocumentFileCompat.kt @@ -14,6 +14,7 @@ import androidx.core.content.ContextCompat import androidx.documentfile.provider.DocumentFile import com.anggrayudi.storage.FileWrapper import com.anggrayudi.storage.SimpleStorage +import com.anggrayudi.storage.SimpleStorage.Companion.KITKAT_SD_CARD_ID import com.anggrayudi.storage.SimpleStorage.Companion.KITKAT_SD_CARD_PATH import com.anggrayudi.storage.extension.* import com.anggrayudi.storage.file.StorageId.DATA @@ -64,10 +65,10 @@ object DocumentFileCompat { val SD_CARD_STORAGE_ID_REGEX = Regex("[A-Z0-9]{4}-[A-Z0-9]{4}") @RestrictTo(RestrictTo.Scope.LIBRARY) - val SD_CARD_STORAGE_PATH_REGEX = Regex("[A-Z0-9]{4}-[A-Z0-9]{4}(.*?)") + val SD_CARD_STORAGE_PATH_REGEX = Regex("/storage/$SD_CARD_STORAGE_ID_REGEX(.*?)") @RestrictTo(RestrictTo.Scope.LIBRARY) - fun getKitkatSdCardRootFile(basePath: String = "") = File(SimpleStorage.KITKAT_SD_CARD_PATH + "/$basePath".trimEnd('/')) + fun getKitkatSdCardRootFile(basePath: String = "") = File(KITKAT_SD_CARD_PATH + "/$basePath".trimEnd('/')) @JvmStatic fun isRootUri(uri: Uri): Boolean { @@ -86,7 +87,10 @@ object DocumentFileCompat { when { fullPath.startsWith(SimpleStorage.externalStoragePath) -> PRIMARY fullPath.startsWith(context.dataDirectory.path) -> DATA - else -> fullPath.substringAfter("/storage/", "").substringBefore('/') + fullPath.startsWith(KITKAT_SD_CARD_PATH) -> KITKAT_SD_CARD_ID + else -> if (fullPath.matches(SD_CARD_STORAGE_PATH_REGEX)) { + fullPath.substringAfter("/storage/", "").substringBefore('/') + } else "" } } else { fullPath.substringBefore(':', "").substringAfterLast('/') @@ -107,7 +111,10 @@ object DocumentFileCompat { when { fullPath.startsWith(externalStoragePath) -> fullPath.substringAfter(externalStoragePath) fullPath.startsWith(dataDir) -> fullPath.substringAfter(dataDir) - else -> fullPath.substringAfter("/storage/", "").substringAfter('/', "") + fullPath.startsWith(KITKAT_SD_CARD_PATH) -> fullPath.substringAfter(KITKAT_SD_CARD_PATH) + else -> if (fullPath.matches(SD_CARD_STORAGE_PATH_REGEX)) { + fullPath.substringAfter("/storage/", "").substringAfter('/', "") + } else "" } } else { fullPath.substringAfter(':', "") diff --git a/storage/src/main/java/com/anggrayudi/storage/file/FileExt.kt b/storage/src/main/java/com/anggrayudi/storage/file/FileExt.kt index e6509aa..82ea05a 100644 --- a/storage/src/main/java/com/anggrayudi/storage/file/FileExt.kt +++ b/storage/src/main/java/com/anggrayudi/storage/file/FileExt.kt @@ -18,6 +18,7 @@ import com.anggrayudi.storage.extension.trimFileSeparator import com.anggrayudi.storage.file.DocumentFileCompat.removeForbiddenCharsFromFilename import com.anggrayudi.storage.file.StorageId.DATA import com.anggrayudi.storage.file.StorageId.HOME +import com.anggrayudi.storage.file.StorageId.KITKAT_SDCARD import com.anggrayudi.storage.file.StorageId.PRIMARY import java.io.File import java.io.IOException @@ -34,7 +35,10 @@ import java.io.IOException fun File.getStorageId(context: Context) = when { path.startsWith(SimpleStorage.externalStoragePath) -> PRIMARY path.startsWith(context.dataDirectory.path) -> DATA - else -> path.substringAfter("/storage/", "").substringBefore('/') + path.startsWith(SimpleStorage.KITKAT_SD_CARD_PATH) -> KITKAT_SDCARD + else -> if (path.matches(DocumentFileCompat.SD_CARD_STORAGE_PATH_REGEX)) { + path.substringAfter("/storage/", "").substringBefore('/') + } else "" } val File.inPrimaryStorage: Boolean diff --git a/storage/src/main/java/com/anggrayudi/storage/file/FileFullPath.kt b/storage/src/main/java/com/anggrayudi/storage/file/FileFullPath.kt index de953d0..9d58460 100644 --- a/storage/src/main/java/com/anggrayudi/storage/file/FileFullPath.kt +++ b/storage/src/main/java/com/anggrayudi/storage/file/FileFullPath.kt @@ -6,8 +6,10 @@ import android.os.storage.StorageManager import androidx.annotation.RequiresApi import androidx.annotation.RestrictTo import com.anggrayudi.storage.SimpleStorage +import com.anggrayudi.storage.SimpleStorage.Companion.KITKAT_SD_CARD_PATH import com.anggrayudi.storage.extension.fromTreeUri import com.anggrayudi.storage.extension.trimFileSeparator +import com.anggrayudi.storage.file.StorageId.KITKAT_SDCARD import java.io.File /** @@ -48,23 +50,34 @@ class FileFullPath { when { fullPath.startsWith(SimpleStorage.externalStoragePath) -> { storageId = StorageId.PRIMARY - val externalPath = SimpleStorage.externalStoragePath - basePath = fullPath.substringAfter(externalPath, "").trimFileSeparator() + val rootPath = SimpleStorage.externalStoragePath + basePath = fullPath.substringAfter(rootPath, "").trimFileSeparator() simplePath = "$storageId:$basePath" - absolutePath = "$externalPath/$basePath".trimEnd('/') + absolutePath = "$rootPath/$basePath".trimEnd('/') } fullPath.startsWith(context.dataDirectory.path) -> { storageId = StorageId.DATA - val dataPath = context.dataDirectory.path - basePath = fullPath.substringAfter(dataPath, "").trimFileSeparator() + val rootPath = context.dataDirectory.path + basePath = fullPath.substringAfter(rootPath, "").trimFileSeparator() simplePath = "$storageId:$basePath" - absolutePath = "$dataPath/$basePath".trimEnd('/') + absolutePath = "$rootPath/$basePath".trimEnd('/') } - else -> { + fullPath.startsWith(KITKAT_SD_CARD_PATH) -> { + storageId = KITKAT_SDCARD + basePath = fullPath.substringAfter(KITKAT_SD_CARD_PATH, "").trimFileSeparator() + simplePath = "$storageId:$basePath" + absolutePath = "$KITKAT_SD_CARD_PATH/$basePath".trimEnd('/') + } + else -> if (fullPath.matches(DocumentFileCompat.SD_CARD_STORAGE_PATH_REGEX)) { storageId = fullPath.substringAfter("/storage/", "").substringBefore('/') basePath = fullPath.substringAfter("/storage/$storageId", "").trimFileSeparator() simplePath = "$storageId:$basePath" absolutePath = "/storage/$storageId/$basePath".trimEnd('/') + } else { + storageId = "" + basePath = "" + simplePath = "" + absolutePath = "" } } } else { From 4a5d0ad6e5e7ca2f7dc7296b1be24ec25091de5a Mon Sep 17 00:00:00 2001 From: Anggrayudi Hardiannico Date: Fri, 16 Jun 2023 19:41:25 +0700 Subject: [PATCH 3/8] Upgrade to AGP 8 --- .github/workflows/android.yml | 4 ++-- build.gradle | 9 ++++++--- gradle/wrapper/gradle-wrapper.properties | 2 +- .../anggrayudi/storage/sample/activity/JavaActivity.java | 2 +- .../anggrayudi/storage/sample/activity/MainActivity.kt | 2 +- 5 files changed, 11 insertions(+), 8 deletions(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 36170b8..cbaac5b 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -19,10 +19,10 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Setup JDK 11 + - name: Setup JDK 17 uses: actions/setup-java@v1 with: - java-version: 11 + java-version: 17 - name: Copy environment variables env: diff --git a/build.gradle b/build.gradle index 64d921d..73850d9 100644 --- a/build.gradle +++ b/build.gradle @@ -4,11 +4,10 @@ buildscript { addRepos(repositories) - ext.kotlin_version = '1.7.21' + ext.kotlin_version = '1.8.22' dependencies { - classpath 'com.android.tools:r8:8.0.40' - classpath 'com.android.tools.build:gradle:7.4.2' + classpath 'com.android.tools.build:gradle:8.0.2' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath 'com.vanniktech:gradle-maven-publish-plugin:0.22.0' classpath 'org.jetbrains.dokka:dokka-gradle-plugin:1.7.20' @@ -57,6 +56,10 @@ subprojects { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } + + buildFeatures { + buildConfig true + } } configurations.all { resolutionStrategy { diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 36fb0fe..f0d76de 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-all.zip diff --git a/sample/src/main/java/com/anggrayudi/storage/sample/activity/JavaActivity.java b/sample/src/main/java/com/anggrayudi/storage/sample/activity/JavaActivity.java index 7b06022..f79a707 100644 --- a/sample/src/main/java/com/anggrayudi/storage/sample/activity/JavaActivity.java +++ b/sample/src/main/java/com/anggrayudi/storage/sample/activity/JavaActivity.java @@ -80,7 +80,7 @@ private void setupSimpleStorage(Bundle savedState) { String absolutePath = DocumentFileUtils.getAbsolutePath(root, getBaseContext()); Toast.makeText( getBaseContext(), - getString(R.string.ss_selecting_root_path_success_without_open_folder_picker, absolutePath), + getString(com.anggrayudi.storage.R.string.ss_selecting_root_path_success_without_open_folder_picker, absolutePath), Toast.LENGTH_SHORT ).show(); return null; diff --git a/sample/src/main/java/com/anggrayudi/storage/sample/activity/MainActivity.kt b/sample/src/main/java/com/anggrayudi/storage/sample/activity/MainActivity.kt index 793a1b9..1736502 100644 --- a/sample/src/main/java/com/anggrayudi/storage/sample/activity/MainActivity.kt +++ b/sample/src/main/java/com/anggrayudi/storage/sample/activity/MainActivity.kt @@ -145,7 +145,7 @@ class MainActivity : AppCompatActivity() { storageHelper.onStorageAccessGranted = { _, root -> Toast.makeText( this, - getString(R.string.ss_selecting_root_path_success_without_open_folder_picker, root.getAbsolutePath(this)), + getString(com.anggrayudi.storage.R.string.ss_selecting_root_path_success_without_open_folder_picker, root.getAbsolutePath(this)), Toast.LENGTH_SHORT ).show() } From bff61c2751046b1e12eb1d38b3153f8f6f9b4956 Mon Sep 17 00:00:00 2001 From: Anggrayudi Hardiannico Date: Fri, 16 Jun 2023 20:08:39 +0700 Subject: [PATCH 4/8] fixed unit test error --- storage/build.gradle | 8 ++++---- .../java/com/anggrayudi/storage/file/FileExtKtTest.kt | 2 ++ versions.gradle | 4 ++-- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/storage/build.gradle b/storage/build.gradle index e54495d..1e17cfa 100644 --- a/storage/build.gradle +++ b/storage/build.gradle @@ -41,10 +41,10 @@ dependencies { testImplementation deps.robolectric // TODO: Replace with MockK after feature "mock java.io.File" has been fixed: https://github.com/mockk/mockk/issues/603 - testImplementation "org.mockito:mockito-core:3.3.3" - testImplementation "org.mockito:mockito-inline:3.3.3" + testImplementation "org.mockito:mockito-core:3.10.0" + testImplementation "org.mockito:mockito-inline:3.10.0" testImplementation "org.mockito:mockito-all:1.10.19" testImplementation "com.nhaarman.mockitokotlin2:mockito-kotlin:2.2.0" - testImplementation "org.powermock:powermock-api-mockito2:2.0.5" - testImplementation "org.powermock:powermock-module-junit4:2.0.5" + testImplementation "org.powermock:powermock-api-mockito2:2.0.9" + testImplementation "org.powermock:powermock-module-junit4:2.0.9" } diff --git a/storage/src/test/java/com/anggrayudi/storage/file/FileExtKtTest.kt b/storage/src/test/java/com/anggrayudi/storage/file/FileExtKtTest.kt index bdd5439..51f4774 100644 --- a/storage/src/test/java/com/anggrayudi/storage/file/FileExtKtTest.kt +++ b/storage/src/test/java/com/anggrayudi/storage/file/FileExtKtTest.kt @@ -3,6 +3,7 @@ package com.anggrayudi.storage.file import com.nhaarman.mockitokotlin2.mock import com.nhaarman.mockitokotlin2.whenever import org.junit.Assert.assertEquals +import org.junit.Ignore import org.junit.Test import org.junit.runner.RunWith import org.powermock.api.mockito.PowerMockito.whenNew @@ -19,6 +20,7 @@ import java.io.File @PrepareForTest(File::class, FileExtKtTest::class) class FileExtKtTest { + @Ignore("JDK 17 cannot mock File object due to protected clone() method") @Test fun autoIncrementFileName() { val videoPath = "/stroage/emulated/0/Video" diff --git a/versions.gradle b/versions.gradle index 46134e1..9caa4ec 100644 --- a/versions.gradle +++ b/versions.gradle @@ -13,9 +13,9 @@ versions.fragment = "1.5.3" versions.junit = "5.9.1" versions.material_dialogs = "3.3.0" versions.material_progressbar = "1.6.1" -versions.mockk = "1.13.2" +versions.mockk = "1.13.5" versions.multidex = "2.0.1" -versions.robolectric = "4.4" +versions.robolectric = "4.10.3" versions.timber = "5.0.1" ext.versions = versions From d7b53b0a0d821c42e2f58716f34610b5ed0aff4d Mon Sep 17 00:00:00 2001 From: Anggrayudi Hardiannico Date: Fri, 16 Jun 2023 21:33:00 +0700 Subject: [PATCH 5/8] removed release keystore --- .github/scripts/copy_env_variables.sh | 11 +---------- sample/build.gradle | 15 ++++----------- 2 files changed, 5 insertions(+), 21 deletions(-) diff --git a/.github/scripts/copy_env_variables.sh b/.github/scripts/copy_env_variables.sh index c0d8eee..06b5d4d 100755 --- a/.github/scripts/copy_env_variables.sh +++ b/.github/scripts/copy_env_variables.sh @@ -6,18 +6,9 @@ fi mkdir "$HOME/.android" keytool -genkey -v -keystore "$HOME/.android/debug.keystore" -storepass android -alias androiddebugkey -keypass android -keyalg RSA -keysize 2048 -validity 10000 -dname "C=US, O=Android, CN=Android Debug" -echo "$RELEASE_KEYSTORE_BASE64" | base64 --decode >"sample/keystore.jks" -if [ -n "$RELEASE_KEYSTORE_ALIAS" ]; then - { - printf "\nkeyAlias=%s" "$RELEASE_KEYSTORE_ALIAS" - printf "\nkeyPassword=%s" "$RELEASE_KEYSTORE_PASSWORD" - printf "\nstorePassword=%s" "$RELEASE_KEYSTORE_PASSWORD" - } >>local.properties -else - { +{ printf "\nkeyAlias=androiddebugkey" printf "\nkeyPassword=android" printf "\nstorePassword=android" } >>local.properties -fi diff --git a/sample/build.gradle b/sample/build.gradle index 184cd31..edf2f34 100644 --- a/sample/build.gradle +++ b/sample/build.gradle @@ -14,17 +14,10 @@ android { storeFile debugKeystore } release { - if (properties['keyAlias'] != null) { - keyAlias properties['keyAlias'] - keyPassword properties['keyPassword'] - storePassword properties['storePassword'] - storeFile file('keystore.jks') - } else { - keyAlias 'androiddebugkey' - keyPassword 'android' - storePassword 'android' - storeFile debugKeystore - } + keyAlias 'androiddebugkey' + keyPassword 'android' + storePassword 'android' + storeFile debugKeystore } } From a93b003fa8ab698a4dd899a3bb56e9f52dd1a24f Mon Sep 17 00:00:00 2001 From: gee12 Date: Fri, 16 Jun 2023 17:41:53 +0300 Subject: [PATCH 6/8] Russian translate (#122) --- storage/src/main/res/values-ru/strings.xml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 storage/src/main/res/values-ru/strings.xml diff --git a/storage/src/main/res/values-ru/strings.xml b/storage/src/main/res/values-ru/strings.xml new file mode 100644 index 0000000..484e87d --- /dev/null +++ b/storage/src/main/res/values-ru/strings.xml @@ -0,0 +1,18 @@ + + + Пожалуйста, предоставьте разрешения на чтение и запись для внешнего хранилища. + Чтобы предоставить доступ к хранилищу, пожалуйста, сначала выберите корневой путь к внутреннему хранилищу. + Чтобы предоставить доступ к хранилищу, пожалуйста, сначала выберите корневой путь к внутреннему хранилищу, расположенный в %s + Чтобы предоставить доступ к хранилищу, пожалуйста, сначала выберите корневой путь SD-карты. + Чтобы предоставить доступ к хранилищу, пожалуйста, сначала выберите корневой путь SD-карты, расположенный в %s + Теперь вы можете выбрать любые папки в разделе %s + Доступ к хранилищу был предоставлен для %s + У вас нет доступа на запись к этому хранилищу, поэтому выбирать эту папку бесполезно. + Хотели бы вы предоставить доступ к этому хранилищу, выбрав его корневой путь? + Storage Access Framework в данный момент недоступен. + Разрешение на хранение было отключено навсегда. + Вы хотите включить его в системных настройках? + Пожалуйста, выберите путь: %s + Пожалуйста, выберите внутреннее хранилище с указанием пути: %s + Пожалуйста, выберите SD-карту с указанием пути: %s + \ No newline at end of file From 9ca05ab15b460c3084d238af349edd66e3a75c69 Mon Sep 17 00:00:00 2001 From: Anggrayudi Hardiannico Date: Fri, 16 Jun 2023 21:57:20 +0700 Subject: [PATCH 7/8] fixed issue #119 --- .../src/main/java/com/anggrayudi/storage/SimpleStorage.kt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/storage/src/main/java/com/anggrayudi/storage/SimpleStorage.kt b/storage/src/main/java/com/anggrayudi/storage/SimpleStorage.kt index f058f1b..f497001 100644 --- a/storage/src/main/java/com/anggrayudi/storage/SimpleStorage.kt +++ b/storage/src/main/java/com/anggrayudi/storage/SimpleStorage.kt @@ -619,8 +619,9 @@ class SimpleStorage private constructor(private val wrapper: ComponentWrapper) { @JvmStatic @JvmOverloads fun hasStorageAccess(context: Context, fullPath: String, requiresWriteAccess: Boolean = true): Boolean { - return (requiresWriteAccess && hasStoragePermission(context) || !requiresWriteAccess && hasStorageReadPermission(context)) - && DocumentFileCompat.getAccessibleRootDocumentFile(context, fullPath, requiresWriteAccess) != null + return DocumentFileCompat.getAccessibleRootDocumentFile(context, fullPath, requiresWriteAccess) != null + && (Build.VERSION.SDK_INT > Build.VERSION_CODES.P + || requiresWriteAccess && hasStoragePermission(context) || !requiresWriteAccess && hasStorageReadPermission(context)) } /** From efbd0a599e76d8e74cbc735498d55cd3ca004248 Mon Sep 17 00:00:00 2001 From: Anggrayudi Hardiannico Date: Mon, 19 Jun 2023 18:11:01 +0700 Subject: [PATCH 8/8] fixed issue #125 --- gradle.properties | 2 +- sample/src/main/AndroidManifest.xml | 2 +- storage/src/main/AndroidManifest.xml | 3 ++- .../com/anggrayudi/storage/SimpleStorage.kt | 26 +++++++++---------- .../permission/ActivityPermissionRequest.kt | 4 +++ .../permission/FragmentPermissionRequest.kt | 4 +++ .../storage/permission/PermissionCallback.kt | 7 +++++ 7 files changed, 31 insertions(+), 17 deletions(-) diff --git a/gradle.properties b/gradle.properties index 0214b08..91904d1 100644 --- a/gradle.properties +++ b/gradle.properties @@ -22,7 +22,7 @@ kotlin.code.style=official # For publishing: GROUP=com.anggrayudi POM_ARTIFACT_ID=storage -VERSION_NAME=1.5.4-SNAPSHOT +VERSION_NAME=1.5.5-SNAPSHOT RELEASE_SIGNING_ENABLED=true SONATYPE_AUTOMATIC_RELEASE=true SONATYPE_HOST=DEFAULT diff --git a/sample/src/main/AndroidManifest.xml b/sample/src/main/AndroidManifest.xml index c30c71a..cdb7483 100644 --- a/sample/src/main/AndroidManifest.xml +++ b/sample/src/main/AndroidManifest.xml @@ -15,7 +15,7 @@ android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme" - tools:ignore="AllowBackup"> + tools:ignore="AllowBackup,LockedOrientationActivity"> - + diff --git a/storage/src/main/java/com/anggrayudi/storage/SimpleStorage.kt b/storage/src/main/java/com/anggrayudi/storage/SimpleStorage.kt index f497001..66f63ed 100644 --- a/storage/src/main/java/com/anggrayudi/storage/SimpleStorage.kt +++ b/storage/src/main/java/com/anggrayudi/storage/SimpleStorage.kt @@ -634,20 +634,18 @@ class SimpleStorage private constructor(private val wrapper: ComponentWrapper) { * Read [Count Your SAF Uri Persisted Permissions!](https://commonsware.com/blog/2020/06/13/count-your-saf-uri-permission-grants.html) */ @JvmStatic - fun cleanupRedundantUriPermissions(context: Context) { - thread { - val resolver = context.contentResolver - // e.g. content://com.android.externalstorage.documents/tree/primary%3AMusic - val persistedUris = resolver.persistedUriPermissions - .filter { it.isReadPermission && it.isWritePermission && it.uri.isExternalStorageDocument } - .map { it.uri } - val writeFlags = Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION - val uniqueUriParents = DocumentFileCompat.findUniqueParents(context, persistedUris.mapNotNull { it.path?.substringAfter("/tree/") }) - persistedUris.forEach { - if (DocumentFileCompat.buildAbsolutePath(context, it.path.orEmpty().substringAfter("/tree/")) !in uniqueUriParents) { - resolver.releasePersistableUriPermission(it, writeFlags) - Log.d(TAG, "Removed redundant URI permission => $it") - } + fun cleanupRedundantUriPermissions(context: Context) = thread { + val resolver = context.contentResolver + // e.g. content://com.android.externalstorage.documents/tree/primary%3AMusic + val persistedUris = resolver.persistedUriPermissions + .filter { it.isReadPermission && it.isWritePermission && it.uri.isExternalStorageDocument } + .map { it.uri } + val writeFlags = Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION + val uniqueUriParents = DocumentFileCompat.findUniqueParents(context, persistedUris.mapNotNull { it.path?.substringAfter("/tree/") }) + persistedUris.forEach { + if (DocumentFileCompat.buildAbsolutePath(context, it.path.orEmpty().substringAfter("/tree/")) !in uniqueUriParents) { + resolver.releasePersistableUriPermission(it, writeFlags) + Log.d(TAG, "Removed redundant URI permission => $it") } } } diff --git a/storage/src/main/java/com/anggrayudi/storage/permission/ActivityPermissionRequest.kt b/storage/src/main/java/com/anggrayudi/storage/permission/ActivityPermissionRequest.kt index 8407af5..c96833f 100644 --- a/storage/src/main/java/com/anggrayudi/storage/permission/ActivityPermissionRequest.kt +++ b/storage/src/main/java/com/anggrayudi/storage/permission/ActivityPermissionRequest.kt @@ -62,6 +62,10 @@ class ActivityPermissionRequest private constructor( } private fun reportResult(reports: List) { + if (reports.isEmpty()) { + callback.onPermissionRequestInterrupted(permissions) + return + } val blockedPermissions = reports.filter { it.deniedPermanently } if (blockedPermissions.isEmpty()) { callback.onPermissionsChecked(PermissionResult(reports), true) diff --git a/storage/src/main/java/com/anggrayudi/storage/permission/FragmentPermissionRequest.kt b/storage/src/main/java/com/anggrayudi/storage/permission/FragmentPermissionRequest.kt index 6e244f0..b5f70d8 100644 --- a/storage/src/main/java/com/anggrayudi/storage/permission/FragmentPermissionRequest.kt +++ b/storage/src/main/java/com/anggrayudi/storage/permission/FragmentPermissionRequest.kt @@ -36,6 +36,10 @@ class FragmentPermissionRequest private constructor( } private fun onRequestPermissionsResult(result: Map) { + if (result.isEmpty()) { + callback.onPermissionRequestInterrupted(permissions) + return + } val activity = fragment.requireActivity() val reports = result.map { PermissionReport(it.key, it.value, !it.value && !ActivityCompat.shouldShowRequestPermissionRationale(activity, it.key)) diff --git a/storage/src/main/java/com/anggrayudi/storage/permission/PermissionCallback.kt b/storage/src/main/java/com/anggrayudi/storage/permission/PermissionCallback.kt index 21fddc2..e6d4dff 100644 --- a/storage/src/main/java/com/anggrayudi/storage/permission/PermissionCallback.kt +++ b/storage/src/main/java/com/anggrayudi/storage/permission/PermissionCallback.kt @@ -18,4 +18,11 @@ interface PermissionCallback { fun onShouldRedirectToSystemSettings(blockedPermissions: List) { // default implementation } + + /** + * Triggered when you request another permission when a permission request dialog is showing. + */ + fun onPermissionRequestInterrupted(permissions: Array) { + // default implementation + } } \ No newline at end of file