diff --git a/android/build.gradle b/android/build.gradle index 8ad2194..a2ed0ca 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -1,53 +1,30 @@ group 'io.alexrintt.sharedstorage' version '1.0-SNAPSHOT' -buildscript { - ext.kotlin_version = '1.8.10' - repositories { - google() - mavenCentral() - maven { url "https://oss.sonatype.org/content/repositories/snapshots" } - } +apply plugin: 'com.android.library' + +android { + namespace 'io.alexrintt.sharedstorage' + compileSdk 36 - dependencies { - classpath 'com.android.tools.build:gradle:7.2.0' - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + defaultConfig { + minSdk 19 } -} -rootProject.allprojects { - repositories { - google() - mavenCentral() + compileOptions { + sourceCompatibility JavaVersion.VERSION_17 + targetCompatibility JavaVersion.VERSION_17 } } -apply plugin: 'com.android.library' -apply plugin: 'kotlin-android' - -android { - compileSdkVersion 33 - - sourceSets { - main.java.srcDirs += 'src/main/kotlin' - } - defaultConfig { - minSdkVersion 19 +kotlin { + compilerOptions { + jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17 } } dependencies { - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" - implementation "androidx.documentfile:documentfile:1.0.1" - - /** - * Allow usage of `CoroutineScope` to run heavy - * computation and queries outside the Main (UI) Thread - */ - implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1" - - /** - * `SimpleStorage` library - */ - implementation "com.anggrayudi:storage:1.3.0" + implementation 'androidx.documentfile:documentfile:1.0.1' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + implementation 'com.anggrayudi:storage:1.3.0' } diff --git a/android/gradle.properties b/android/gradle.properties index 94adc3a..842dce9 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -1,3 +1,4 @@ org.gradle.jvmargs=-Xmx1536M android.useAndroidX=true android.enableJetifier=true +kotlin.jvm.target.validation.mode = IGNORE \ No newline at end of file diff --git a/android/src/main/kotlin/io/alexrintt/sharedstorage/deprecated/DocumentFileApi.kt b/android/src/main/kotlin/io/alexrintt/sharedstorage/deprecated/DocumentFileApi.kt index fd17f6f..e29cd11 100644 --- a/android/src/main/kotlin/io/alexrintt/sharedstorage/deprecated/DocumentFileApi.kt +++ b/android/src/main/kotlin/io/alexrintt/sharedstorage/deprecated/DocumentFileApi.kt @@ -289,10 +289,23 @@ internal class DocumentFileApi(private val plugin: SharedStoragePlugin) : result.notSupported(CHILD, API_21, mapOf("uri" to uri)) } } + CAN_OPEN_DOCUMENT_TREE -> { + result.success(canOpenDocumentTree()) + } else -> result.notImplemented() } } + private fun canOpenDocumentTree(): Boolean { + return try { + val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE) + val activities = plugin.context.packageManager.queryIntentActivities(intent, 0) + activities.isNotEmpty() + } catch (e: Exception) { + false + } + } + @RequiresApi(API_21) private fun openDocument(call: MethodCall, result: MethodChannel.Result) { val initialUri = call.argument("initialUri") diff --git a/android/src/main/kotlin/io/alexrintt/sharedstorage/deprecated/DocumentsContractApi.kt b/android/src/main/kotlin/io/alexrintt/sharedstorage/deprecated/DocumentsContractApi.kt index c0b0428..1dd76d9 100644 --- a/android/src/main/kotlin/io/alexrintt/sharedstorage/deprecated/DocumentsContractApi.kt +++ b/android/src/main/kotlin/io/alexrintt/sharedstorage/deprecated/DocumentsContractApi.kt @@ -95,11 +95,12 @@ internal class DocumentsContractApi(private val plugin: SharedStoragePlugin) : } // the secret are these two lines.... - packageInfo.applicationInfo.sourceDir = it.path - packageInfo.applicationInfo.publicSourceDir = it.path + packageInfo.applicationInfo?.sourceDir = it.path + packageInfo.applicationInfo?.publicSourceDir = it.path val apkIcon: Drawable = - packageInfo.applicationInfo.loadIcon(packageManager) + packageInfo.applicationInfo?.loadIcon(packageManager) + ?: return@createTempUriFile result.success(null) val bitmap: Bitmap = drawableToBitmap(apkIcon) diff --git a/android/src/main/kotlin/io/alexrintt/sharedstorage/deprecated/lib/StorageAccessFrameworkConstant.kt b/android/src/main/kotlin/io/alexrintt/sharedstorage/deprecated/lib/StorageAccessFrameworkConstant.kt index 62af0c2..0fa9b62 100644 --- a/android/src/main/kotlin/io/alexrintt/sharedstorage/deprecated/lib/StorageAccessFrameworkConstant.kt +++ b/android/src/main/kotlin/io/alexrintt/sharedstorage/deprecated/lib/StorageAccessFrameworkConstant.kt @@ -39,6 +39,7 @@ const val COPY = "copy" const val LAST_MODIFIED = "lastModified" const val GET_DOCUMENT_THUMBNAIL = "getDocumentThumbnail" const val CHILD = "child" +const val CAN_OPEN_DOCUMENT_TREE = "canOpenDocumentTree" /** * Available DocumentFileHelper Method Channel APIs diff --git a/lib/src/common/functional_extender.dart b/lib/src/common/functional_extender.dart index 7e0bd65..c9abffc 100644 --- a/lib/src/common/functional_extender.dart +++ b/lib/src/common/functional_extender.dart @@ -25,7 +25,13 @@ extension FunctionalExtender on T? { T? takeIf(bool Function(T) f) { final T? self = this; - return self != null && f(self) ? self : null; + if (self == null) return null; + + if (f(self)) { + return self; + } else { + return null; + } } } diff --git a/lib/src/saf/saf.dart b/lib/src/saf/saf.dart index a0dd059..b3c45d3 100644 --- a/lib/src/saf/saf.dart +++ b/lib/src/saf/saf.dart @@ -134,6 +134,18 @@ Future canRead(Uri uri) async => kDocumentFileChannel Future canWrite(Uri uri) async => kDocumentFileChannel .invokeMethod('canWrite', {'uri': '$uri'}); +/// {@template sharedstorage.saf.canOpenDocumentTree} +/// Check if the device supports Storage Access Framework (SAF) and can open document trees. +/// +/// Returns `true` if the device has apps that can handle ACTION_OPEN_DOCUMENT_TREE intents, +/// `false` otherwise. This is useful to determine SAF support before attempting to use +/// document tree operations. +/// +/// [Refer to details](https://developer.android.com/reference/android/content/Intent#ACTION_OPEN_DOCUMENT_TREE). +/// {@endtemplate} +Future canOpenDocumentTree() async => kDocumentFileChannel + .invokeMethod('canOpenDocumentTree'); + /// {@template sharedstorage.saf.getDocumentThumbnail} /// Equivalent to `DocumentsContract.getDocumentThumbnail`. /// diff --git a/pubspec.yaml b/pubspec.yaml index 4d30b40..4115556 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -7,8 +7,8 @@ issue_tracker: https://github.com/alexrintt/shared-storage/issues documentation: https://github.com/alexrintt/shared-storage environment: - sdk: ">=2.16.0 <3.0.0" - flutter: ">=2.5.0" + sdk: ^3.12.0 + flutter: ">=3.44.0" dependencies: flutter: @@ -26,3 +26,5 @@ flutter: android: package: io.alexrintt.sharedstorage pluginClass: SharedStoragePlugin + supportedBuildSystems: + - gradle