Skip to content

Commit

Permalink
Merge pull request #111 from alexrintt/master
Browse files Browse the repository at this point in the history
`v0.7.0`
  • Loading branch information
Alex Rintt authored Nov 16, 2022
2 parents 25f58f9 + b806fbd commit 310bf9d
Show file tree
Hide file tree
Showing 20 changed files with 517 additions and 118 deletions.
1 change: 1 addition & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
github: [alexrintt]
22 changes: 20 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,28 @@
## 0.7.0

- New APIs and options.
- There's no major breaking changes when updating to `v0.7.0` but there are deprecation notices over Media Store and Environment API.

### New

- `openDocument` API with single and multiple files support @honjow.
- `openDocumentTree` it now also supports `persistablePermission` option which flags an one-time operation to avoid unused permission issues.

### Deprecation notices

- All non SAF APIs are deprecated (Media Store and Environment APIs), if you are using them, let us know by [opening an issue](https://github.com/alexrintt/shared-storage/issues/new) with your use-case so we can implement a new compatible API using a cross-platform approach.

### Example project

- Added a new button that implements `openDocument` API.

## 0.6.0

This release contains a severe API fixes and some minor doc changes:

### Breaking changes

- Unused arguments in `DocumentFile.getContent` and `DocumentFile.getContentAsString`. [#107](https://github.com/alexrintt/shared-storage/issues/107).
- Unused arguments in `DocumentFile.getContent` and `DocumentFile.getContentAsString`. [#107](https://github.com/alexrintt/shared-storage/issues/107) @clragon.
- Package import it's now done through a single import.

## 0.5.0
Expand Down Expand Up @@ -170,7 +188,7 @@ See the label [reference here](/docs/Usage/API%20Labeling.md).

- <samp>Mirror</samp> `getStorageDirectory` from [`Environment.getStorageDirectory`](https://developer.android.com/reference/android/os/Environment#getStorageDirectory%28%29).

### Deprecation Notices
### Deprecation notices

- `getExternalStoragePublicDirectory` was marked as deprecated and should be replaced with an equivalent API depending on your use-case, see [how to migrate `getExternalStoragePublicDirectory`](https://stackoverflow.com/questions/56468539/getexternalstoragepublicdirectory-deprecated-in-android-q). This deprecation is originated from official Android documentation and not by the plugin itself.

Expand Down
21 changes: 13 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
<img src="https://img.shields.io/badge/Flutter-22272E?style=for-the-badge&logo=flutter&logoColor=66B1F1">
</p>

<a href="https://pub.dev/packages/shared_storage"><h4 align="center"><samp>Install It</samp></h4></a>
<h4 align="center"><samp><a href="https://pub.dev/packages/shared_storage">Install It</a></samp></h4>

## Documentation

Expand All @@ -34,15 +34,20 @@ Latest changes are available on `master` branch and the actual latest published

All other branches are derivated from issues, new features or bug fixes.

## Supporters

- [aplicatii-romanesti](https://www.bibliotecaortodoxa.ro/) who bought me a whole month of caffeine!

## Contributors

- [clragon](https://github.com/clragon) submitted a severe bug report and opened discussions around package architecture, thanks!
- [jfaltis](https://github.com/jfaltis) fixed a memory leak and implemented an API to override existing files, thanks for you contribution!
- [EternityForest](https://github.com/EternityForest) did fix a severe crash when the ID column was not provided and implemented a new feature to list all subfolders, thanks man!
- Thanks [dhaval-k-simformsolutions](https://github.com/dhaval-k-simformsolutions) for taking time to submit bug reports related to duplicated file entries!
- [dangilbert](https://github.com/dangilbert) pointed and fixed bug when the user doesn't select a folder, thanks man!
- A huge thanks to [aplicatii-romanesti](https://www.bibliotecaortodoxa.ro/) for taking time to submit device specific issues and for supporting the project!
- I would thanks [ankitparmar007](https://github.com/ankitparmar007) for discussing and requesting create file related APIs!
- [honjow](https://github.com/honjow) contributed by [implementing `openDocument` Android API #110](https://github.com/alexrintt/shared-storage/pull/110) to pick single or multiple file URIs. Really helpful, thanks!
- [clragon](https://github.com/clragon) submitted a severe [bug report #107](https://github.com/alexrintt/shared-storage/issues/107) and opened [discussions around package architecture #108](https://github.com/alexrintt/shared-storage/discussions/108), thanks!
- [jfaltis](https://github.com/jfaltis) fixed [a memory leak #86](https://github.com/alexrintt/shared-storage/pull/86) and implemented an API to [override existing files #85](https://github.com/alexrintt/shared-storage/pull/85), thanks for your contribution!
- [EternityForest](https://github.com/EternityForest) did [report a severe crash #50](https://github.com/alexrintt/shared-storage/issues/50) when the column ID was not provided and [implemented a new feature to list all subfolders #59](https://github.com/alexrintt/shared-storage/pull/59), thanks man!
- Thanks [dhaval-k-simformsolutions](https://github.com/dhaval-k-simformsolutions) for taking time to submit [bug reports](https://github.com/alexrintt/shared-storage/issues?q=is%3Aissue+author%3Adhaval-k-simformsolutions) related to duplicated file entries!
- [dangilbert](https://github.com/dangilbert) pointed and [fixed a bug #14](https://github.com/alexrintt/shared-storage/pull/14) when the user doesn't select a folder, thanks man!
- A huge thanks to [aplicatii-romanesti](https://www.bibliotecaortodoxa.ro/) for taking time to submit [device specific issues](https://github.com/alexrintt/shared-storage/issues?q=author%3Aaplicatii-romanesti)!
- I would thanks [ankitparmar007](https://github.com/ankitparmar007) for [discussing and requesting create file related APIs #20](https://github.com/alexrintt/shared-storage/issues/10)!

<br>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import android.provider.DocumentsContract
import android.util.Log
import androidx.annotation.RequiresApi
import androidx.documentfile.provider.DocumentFile
import com.anggrayudi.storage.extension.isTreeDocumentFile
import com.anggrayudi.storage.file.child
import io.flutter.plugin.common.*
import io.flutter.plugin.common.EventChannel.StreamHandler
Expand Down Expand Up @@ -60,6 +61,10 @@ internal class DocumentFileApi(private val plugin: SharedStoragePlugin) :
result.notSupported(call.method, API_21)
}
}
OPEN_DOCUMENT ->
if (Build.VERSION.SDK_INT >= API_21) {
openDocument(call, result)
}
OPEN_DOCUMENT_TREE ->
if (Build.VERSION.SDK_INT >= API_21) {
openDocumentTree(call, result)
Expand Down Expand Up @@ -250,6 +255,32 @@ internal class DocumentFileApi(private val plugin: SharedStoragePlugin) :
}
}

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

val intent =
Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)

if (initialUri != null) {
val tree = DocumentFile.fromTreeUri(plugin.context, Uri.parse(initialUri))
if (Build.VERSION.SDK_INT >= API_26) {
putExtra(DocumentsContract.EXTRA_INITIAL_URI, tree?.uri)
}
}

type = call.argument<String>("mimeType") ?: "*/*"
putExtra(Intent.EXTRA_ALLOW_MULTIPLE, call.argument<Boolean>("multiple") ?: false)
}

if (pendingResults[OPEN_DOCUMENT_CODE] != null) return

pendingResults[OPEN_DOCUMENT_CODE] = Pair(call, result)

plugin.binding?.activity?.startActivityForResult(intent, OPEN_DOCUMENT_CODE)
}

@RequiresApi(API_21)
private fun openDocumentTree(call: MethodCall, result: MethodChannel.Result) {
val grantWritePermission = call.argument<Boolean>("grantWritePermission")!!
Expand Down Expand Up @@ -349,7 +380,8 @@ internal class DocumentFileApi(private val plugin: SharedStoragePlugin) :
"isReadPermission" to it.isReadPermission,
"isWritePermission" to it.isWritePermission,
"persistedTime" to it.persistedTime,
"uri" to "${it.uri}"
"uri" to "${it.uri}",
"isTreeDocumentFile" to it.uri.isTreeDocumentFile
)
}
.toList()
Expand All @@ -373,16 +405,19 @@ internal class DocumentFileApi(private val plugin: SharedStoragePlugin) :
val pendingResult = pendingResults[OPEN_DOCUMENT_TREE_CODE] ?: return false

val grantWritePermission = pendingResult.first.argument<Boolean>("grantWritePermission")!!
val persistablePermission = pendingResult.first.argument<Boolean>("persistablePermission")!!

try {
val uri = data?.data

if (uri != null) {
plugin.context.contentResolver.takePersistableUriPermission(
if (persistablePermission) {
plugin.context.contentResolver.takePersistableUriPermission(
uri,
if (grantWritePermission) Intent.FLAG_GRANT_WRITE_URI_PERMISSION
else Intent.FLAG_GRANT_READ_URI_PERMISSION
)
)
}

pendingResult.second.success("$uri")

Expand All @@ -394,6 +429,39 @@ internal class DocumentFileApi(private val plugin: SharedStoragePlugin) :
pendingResults.remove(OPEN_DOCUMENT_TREE_CODE)
}
}
OPEN_DOCUMENT_CODE -> {
val pendingResult = pendingResults[OPEN_DOCUMENT_CODE] ?: return false

val grantWritePermission = pendingResult.first.argument<Boolean>("grantWritePermission")!!
val persistablePermission = pendingResult.first.argument<Boolean>("persistablePermission")!!

try {
// if data.clipData not null, uriList from data.clipData, else uriList is data.data
val uriList = data?.clipData?.let {
(0 until it.itemCount).map { i -> it.getItemAt(i).uri }
} ?: data?.data?.let { listOf(it) }

if (uriList != null) {
if (persistablePermission) {
for (uri in uriList) {
plugin.context.contentResolver.takePersistableUriPermission(
uri,
if (grantWritePermission) Intent.FLAG_GRANT_WRITE_URI_PERMISSION
else Intent.FLAG_GRANT_READ_URI_PERMISSION
)
}
}

pendingResult.second.success(uriList.map { "$it" })

return true
}

pendingResult.second.success(null)
} finally {
pendingResults.remove(OPEN_DOCUMENT_CODE)
}
}
}

return false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const val DOCUMENTS_CONTRACT_EXTRA_INITIAL_URI =
/**
* Available DocumentFile Method Channel APIs
*/
const val OPEN_DOCUMENT = "openDocument"
const val OPEN_DOCUMENT_TREE = "openDocumentTree"
const val PERSISTED_URI_PERMISSIONS = "persistedUriPermissions"
const val RELEASE_PERSISTABLE_URI_PERMISSION = "releasePersistableUriPermission"
Expand Down Expand Up @@ -54,3 +55,4 @@ const val GET_DOCUMENT_CONTENT = "getDocumentContent"
* Intent Request Codes
*/
const val OPEN_DOCUMENT_TREE_CODE = 10
const val OPEN_DOCUMENT_CODE = 11
12 changes: 12 additions & 0 deletions docs/Migrate notes/Migrate to v0.7.0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
There's no major breaking changes when updating to `v0.7.0` but there are deprecation notices if you are using Media Store and Environment API.

Update your `pubspec.yaml`:

```yaml
dependencies:
shared_storage: ^0.7.0
```
## Deprecation notices
All non SAF APIs are deprecated, if you are using them, let us know by [opening an issue](https://github.com/alexrintt/shared-storage/issues/new) with your use-case so we can implement a new compatible API using a cross-platform approach.
2 changes: 2 additions & 0 deletions docs/Usage/Environment.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
> **WARNING** This API is deprecated and will be removed soon. If you need it, please open an issue with your use-case to include in the next release as part of the new original cross-platform API.
## Import package

```dart
Expand Down
2 changes: 2 additions & 0 deletions docs/Usage/Media Store.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
> **WARNING** This API is deprecated and will be removed soon. If you need it, please open an issue with your use-case to include in the next release as part of the new original cross-platform API.
## Import package

```dart
Expand Down
40 changes: 40 additions & 0 deletions docs/Usage/Storage Access Framework.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,46 @@ if (grantedUri != null) {
}
```

### <samp>openDocument</samp>

Same as `openDocumentTree` but for file URIs, you can request user to select a file and filter by:

- Single or multiple files.
- Mime type.

You can also specify if you want a one-time operation (`persistablePermission` = false) and if you don't need write access (`grantWritePermission` = false).

```dart
const kDownloadsFolder =
'content://com.android.externalstorage.documents/tree/primary%3ADownloads/document/primary%3ADownloads';
final List<Uri>? selectedDocumentUris = await openDocument(
// if you have a previously saved URI,
// you can use the specify the tree you user will see at startup of the file picker.
initialUri: Uri.parse(kDownloadsFolder),
// whether or not allow the user select multiple files.
multiple: true,
// whether or not the selected URIs should be persisted across app and device reboots.
persistablePermission: true,
// whether or not grant write permission required to edit file metadata (name) and it's contents.
grantWritePermission: true,
// whether or not filter by mime type.
mimeType: 'image/*' // default '*/*'
);
if (selectedDocumentUris == null) {
return print('User cancelled the operation.');
}
// If [selectedDocumentUris] are [persistablePermission]s then it will be returned by this function
// along with any another URIs you've got permission over.
final List<UriPermission> persistedUris = await persistedUriPermissions();
```

### <samp>listFiles</samp>

This method list files lazily **over a granted uri:**
Expand Down
Loading

0 comments on commit 310bf9d

Please sign in to comment.