Skip to content

Commit 3ad5b54

Browse files
committed
(#110) Add persistablePermission and grantWritePermission to openDocumentTree and openDocument
1 parent 00be067 commit 3ad5b54

File tree

3 files changed

+54
-10
lines changed

3 files changed

+54
-10
lines changed

android/src/main/kotlin/io/alexrintt/sharedstorage/storageaccessframework/DocumentFileApi.kt

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import android.provider.DocumentsContract
77
import android.util.Log
88
import androidx.annotation.RequiresApi
99
import androidx.documentfile.provider.DocumentFile
10+
import com.anggrayudi.storage.extension.isTreeDocumentFile
1011
import com.anggrayudi.storage.file.child
1112
import io.flutter.plugin.common.*
1213
import io.flutter.plugin.common.EventChannel.StreamHandler
@@ -256,7 +257,6 @@ internal class DocumentFileApi(private val plugin: SharedStoragePlugin) :
256257

257258
@RequiresApi(API_21)
258259
private fun openDocument(call: MethodCall, result: MethodChannel.Result) {
259-
260260
val initialUri = call.argument<String>("initialUri")
261261

262262
val intent =
@@ -380,7 +380,8 @@ internal class DocumentFileApi(private val plugin: SharedStoragePlugin) :
380380
"isReadPermission" to it.isReadPermission,
381381
"isWritePermission" to it.isWritePermission,
382382
"persistedTime" to it.persistedTime,
383-
"uri" to "${it.uri}"
383+
"uri" to "${it.uri}",
384+
"isTreeDocumentFile" to it.uri.isTreeDocumentFile
384385
)
385386
}
386387
.toList()
@@ -404,16 +405,19 @@ internal class DocumentFileApi(private val plugin: SharedStoragePlugin) :
404405
val pendingResult = pendingResults[OPEN_DOCUMENT_TREE_CODE] ?: return false
405406

406407
val grantWritePermission = pendingResult.first.argument<Boolean>("grantWritePermission")!!
408+
val persistablePermission = pendingResult.first.argument<Boolean>("persistablePermission")!!
407409

408410
try {
409411
val uri = data?.data
410412

411413
if (uri != null) {
412-
plugin.context.contentResolver.takePersistableUriPermission(
414+
if (persistablePermission) {
415+
plugin.context.contentResolver.takePersistableUriPermission(
413416
uri,
414417
if (grantWritePermission) Intent.FLAG_GRANT_WRITE_URI_PERMISSION
415418
else Intent.FLAG_GRANT_READ_URI_PERMISSION
416-
)
419+
)
420+
}
417421

418422
pendingResult.second.success("$uri")
419423

@@ -428,13 +432,26 @@ internal class DocumentFileApi(private val plugin: SharedStoragePlugin) :
428432
OPEN_DOCUMENT_CODE -> {
429433
val pendingResult = pendingResults[OPEN_DOCUMENT_CODE] ?: return false
430434

435+
val grantWritePermission = pendingResult.first.argument<Boolean>("grantWritePermission")!!
436+
val persistablePermission = pendingResult.first.argument<Boolean>("persistablePermission")!!
437+
431438
try {
432439
// if data.clipData not null, uriList from data.clipData, else uriList is data.data
433440
val uriList = data?.clipData?.let {
434441
(0 until it.itemCount).map { i -> it.getItemAt(i).uri }
435442
} ?: data?.data?.let { listOf(it) }
436443

437444
if (uriList != null) {
445+
if (persistablePermission) {
446+
for (uri in uriList) {
447+
plugin.context.contentResolver.takePersistableUriPermission(
448+
uri,
449+
if (grantWritePermission) Intent.FLAG_GRANT_WRITE_URI_PERMISSION
450+
else Intent.FLAG_GRANT_READ_URI_PERMISSION
451+
)
452+
}
453+
}
454+
438455
pendingResult.second.success(uriList.map { "$it" })
439456

440457
return true

lib/src/saf/saf.dart

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,14 @@ import 'common.dart';
2020
/// {@endtemplate}
2121
Future<Uri?> openDocumentTree({
2222
bool grantWritePermission = true,
23+
bool persistablePermission = true,
2324
Uri? initialUri,
2425
}) async {
2526
const kOpenDocumentTree = 'openDocumentTree';
2627

2728
final args = <String, dynamic>{
2829
'grantWritePermission': grantWritePermission,
30+
'persistablePermission': persistablePermission,
2931
if (initialUri != null) 'initialUri': '$initialUri',
3032
};
3133

@@ -38,21 +40,26 @@ Future<Uri?> openDocumentTree({
3840
/// [Refer to details](https://developer.android.com/reference/android/content/Intent#ACTION_OPEN_DOCUMENT).
3941
Future<List<Uri>?> openDocument({
4042
Uri? initialUri,
43+
bool grantWritePermission = true,
44+
bool persistablePermission = true,
4145
String mimeType = '*/*',
4246
bool multiple = false,
4347
}) async {
4448
const kOpenDocument = 'openDocument';
4549

4650
final args = <String, dynamic>{
4751
if (initialUri != null) 'initialUri': '$initialUri',
52+
'grantWritePermission': grantWritePermission,
53+
'persistablePermission': persistablePermission,
4854
'mimeType': mimeType,
4955
'multiple': multiple,
5056
};
5157

5258
final selectedUriList =
5359
await kDocumentFileChannel.invokeListMethod(kOpenDocument, args);
5460

55-
return selectedUriList?.apply((e) => e.map((e) => Uri.parse(e as String)).toList());
61+
return selectedUriList
62+
?.apply((e) => e.map((e) => Uri.parse(e as String)).toList());
5663
}
5764

5865
/// {@template sharedstorage.saf.persistedUriPermissions}

lib/src/saf/uri_permission.dart

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
/// This grants may have been created via `Intent#FLAG_GRANT_READ_URI_PERMISSION`,
33
/// etc when sending an `Intent`, or explicitly through `Context#grantUriPermission(String, android.net.Uri, int)`.
44
///
5-
/// [Refer to details](https://developer.android.com/reference/android/content/UriPermission)
5+
/// [Refer to details](https://developer.android.com/reference/android/content/UriPermission).
66
class UriPermission {
77
/// Even we allow create instances of this class avoid it and use
88
/// `persistedUriPermissions` API instead
@@ -11,6 +11,7 @@ class UriPermission {
1111
required this.isWritePermission,
1212
required this.persistedTime,
1313
required this.uri,
14+
required this.isTreeDocumentFile,
1415
});
1516

1617
factory UriPermission.fromMap(Map<String, dynamic> map) {
@@ -19,6 +20,7 @@ class UriPermission {
1920
isWritePermission: map['isWritePermission'] as bool,
2021
persistedTime: map['persistedTime'] as int,
2122
uri: Uri.parse(map['uri'] as String),
23+
isTreeDocumentFile: map['isTreeDocumentFile'] as bool,
2224
);
2325
}
2426

@@ -40,24 +42,41 @@ class UriPermission {
4042
/// [Refer to details](https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/content/UriPermission.java#56)
4143
final Uri uri;
4244

45+
/// Whether or not a tree document file.
46+
///
47+
/// Tree document files are granted through [openDocumentTree] method, that is, when the user select a folder-like tree document file.
48+
/// Document files are granted through [openDocument] method, that is, when the user select (a) specific(s) document files.
49+
///
50+
/// Roughly you may consider it as a property to verify if [this] permission is over a folder or a single-file.
51+
final bool isTreeDocumentFile;
52+
4353
@override
4454
bool operator ==(Object other) =>
4555
other is UriPermission &&
4656
isReadPermission == other.isReadPermission &&
4757
isWritePermission == other.isWritePermission &&
4858
persistedTime == other.persistedTime &&
49-
uri == other.uri;
59+
uri == other.uri &&
60+
isTreeDocumentFile == other.isTreeDocumentFile;
5061

5162
@override
52-
int get hashCode =>
53-
Object.hash(isReadPermission, isWritePermission, persistedTime, uri);
63+
int get hashCode => Object.hashAll(
64+
[
65+
isReadPermission,
66+
isWritePermission,
67+
persistedTime,
68+
uri,
69+
isTreeDocumentFile,
70+
],
71+
);
5472

5573
Map<String, dynamic> toMap() {
5674
return <String, dynamic>{
5775
'isReadPermission': isReadPermission,
5876
'isWritePermission': isWritePermission,
5977
'persistedTime': persistedTime,
6078
'uri': '$uri',
79+
'isTreeDocumentFile': isTreeDocumentFile,
6180
};
6281
}
6382

@@ -66,5 +85,6 @@ class UriPermission {
6685
'isReadPermission: $isReadPermission, '
6786
'isWritePermission: $isWritePermission, '
6887
'persistedTime: $persistedTime, '
69-
'uri: $uri)';
88+
'uri: $uri, '
89+
'isTreeDocumentFile: $isTreeDocumentFile)';
7090
}

0 commit comments

Comments
 (0)