saf 2.1.2
saf: ^2.1.2 copied to clipboard
Flutter plugin that leverages Storage Access Framework (SAF) API to get access and perform the operations on files and folders.
2.1.2 #
- Fix: build failure on AGP 9 with
android.builtInKotlin=false(#45). 2.1.1 inferred built-in Kotlin from the AGP major version alone, so projects using Flutter's documented opt-out got neither built-in Kotlin nor KGP and failed withCould not find method kotlin(). The guard now mirrors Flutter's ownisBuiltInKotlinEnabledrule and reads the property. - Fix: no more spurious "plugins that apply Kotlin Gradle Plugin (KGP): saf"
warning on AGP 9. Flutter's check regex-scans the build script and cannot see
the conditional, so KGP is now applied via
pluginManager.applyinstead.
2.1.1 #
- Android: compatible with AGP 9's built-in Kotlin (#45). The Kotlin Gradle Plugin is now applied only when building with AGP < 9, so the plugin builds on both current Flutter versions and the upcoming built-in-Kotlin default. No Dart API changes.
- Fix:
renameno longer reports success when the provider rejected the rename (a nullrenameDocumentresult means failure, not "unchanged"). - Fix:
releasePersistedPermissionis idempotent again — releasing an already released or never-persisted URI no longer throws (regression in 2.1.0). - Fix:
thumbnailreturnsnullinstead of empty bytes when JPEG encoding fails, and rejects non-positive sizes or out-of-range quality. - Docs:
closeFileDescriptoris only safe for descriptors this plugin still owns (fd numbers are reused); an abortedoverwrite/appendwrite can leave the pre-existing document with partial content. - Legacy
LegacySaffixes:DocumentFile.canReadno longer returns write status;getFilesUrisent the wrong argument key and always returned null;createFileAsStringnow writes UTF-8 instead of truncated UTF-16;singleCachenever ran at all;copyandgetDocumentThumbnailnever completed their futures (thumbnail also crashed on an Int/double mismatch); cache/sync results are posted on the main thread as MethodChannel requires;listFilesno longer walks the whole subtree whenmimeTypeis requested and now closes its stream; the picker works again after a configuration change.
2.1.0 #
- New:
openFileDescriptor/closeFileDescriptoropen a live file descriptor for a SAF document and expose its/proc/self/fd/<fd>path for native or path-based APIs;withFileDescriptoropens, runs your action, and always closes in afinally. - New:
thumbnail(uri, width, height, quality)returns provider-generated JPEG bytes (Uint8List?), ornullwhen the provider has none. - New:
SafOpenFdmodel (fd,path). - Example: a mini file-manager showcasing the new descriptor and thumbnail APIs.
- Fix: an aborted
writeFileStreamno longer deletes a pre-existing target file (overwrite/append) — only documents created by that write are cleaned up. - Fix:
copyTo/moveTonow reject copying a directory into itself or its own subtree instead of recursing until storage fills. - Fix:
releasePersistedPermissionnow releases directory grants taken bypickDirectory(URI-form mismatch made it a silent no-op). - Fix: picker failures (e.g. no SAF handler on some Android TV/Go builds) no longer leave the plugin stuck rejecting all future picks.
- Fix:
openReadSessionno longer leaks the stream when seeking fails. - Deprecated
FileTypes(legacy 1.x, removed in 3.0.0); internalmapPlatformExceptionis no longer exported.
2.0.1 #
- Documentation and presentation polish. No API or behavior changes.
2.0.0 #
One class for everything SAF. The new Saf class covers pickers,
persisted permissions, file management, recursive walk(), byte/stream
read-write with progress callbacks, and local-file bridging — one focused
API, typed exceptions, no isDir parameters.
BREAKING: the legacy path-based class is renamed LegacySaf
(deprecated, removal in 3.0.0). Its behavior is unchanged — existing code
only needs Saf( → LegacySaf(.
- New:
pickDirectory/pickFile/pickFileswith initial URI and persistable permissions;persistedPermissions()listing. - New:
list(single-cursor, fast),stat,exists,child,mkdirp,delete,rename, recursivecopyTo/moveTowith progress,walk(). - New:
readFileBytes/readFileStream,writeFileBytes, one-callwriteFileStream,copyToLocalFile/pasteLocalFile, andcopyDirToLocal(bulk-copy a granted folder into your app dir — e.g. WhatsApp.Statuses). - New: sealed
SafExceptionhierarchy (permission/not_found/already_exists/io). - Broad support: Dart >=3.0, Flutter >=3.10, Android minSdk 21.