Skip to content

Releases: jvoltci/saf

saf 2.1.0 — file descriptors, thumbnails, hardened file layer

Choose a tag to compare

@jvoltci jvoltci released this 18 Jul 14:20

What's new

Raw file descriptors

Hand a SAF file to anything that wants a real path or fd — video players, PDF renderers, sqlite — no copy:

final title = await saf.withFileDescriptor(doc.uri, 'r', (fd) async {
  return someNativeLib.readMetadata(fd.path); // /proc/self/fd/<fd>
});

openFileDescriptor / closeFileDescriptor are also available for manual control. The descriptor is always closed for you with withFileDescriptor — even when your action throws.

Provider thumbnails

thumbnail(uri, width, height, quality) returns provider-generated JPEG bytes (Uint8List?) — perfect for gallery grids with Image.memory, no full-image decode.

Mini file-manager example

cd example && flutter run: pick a folder, browse it with live image thumbnails, tap a file for its details and fd path, write a file back. Verified on physical hardware against a 5,613-file camera roll.

Hardened file layer

  • An aborted writeFileStream no longer deletes a pre-existing target (overwrite/append) — only documents created by that write are cleaned up.
  • copyTo/moveTo now reject copying a directory into itself or its own subtree.
  • releasePersistedPermission now actually releases directory grants taken by pickDirectory.
  • Picker failures (e.g. no SAF handler on some Android TV/Go builds) no longer wedge all future picks.
  • openReadSession no longer leaks the stream when the initial seek fails.
  • Deprecated legacy FileTypes; internal mapPlatformException removed from the public API.

Full changelog: https://github.com/jvoltci/saf/blob/master/CHANGELOG.md
Docs: https://jvoltci.github.io/saf/

saf 2.0.0 — one class for the Storage Access Framework

Choose a tag to compare

@jvoltci jvoltci released this 18 Jul 12:12

One Saf class covers everything SAF — full native create/read/write/update/delete (no dart:io on granted folders), typed errors, streaming with backpressure, recursive walk, progress, and hidden-folder support.

Highlights

  • Pickers + persisted permissions — grant once, reuse across restarts; persistedPermissions() lists grants.
  • File managementlist (fast single-cursor), stat, exists, child, mkdirp, delete, rename, recursive copyTo/moveTo with progress, recursive walk().
  • Read/writereadFileBytes, readFileStream (pull-based, no OOM on huge files), writeFileBytes, one-call writeFileStream.
  • Bridge to local filescopyToLocalFile, pasteLocalFile, and copyDirToLocal (pull a whole granted folder — e.g. WhatsApp .Statuses — into your app dir).
  • Typed errorsSafPermissionException, SafNotFoundException, SafAlreadyExistsException, SafIoException.
  • No isDir params anywhere. Broad support: Dart >=3.0, Flutter >=3.10, minSdk 21.

Breaking

The legacy path-based class is now LegacySaf (deprecated, removed in 3.0.0). Migrate with Saf( -> LegacySaf(. See the README.

Docs & quality

Docs: https://jvoltci.github.io/saf/ · pana 150/150 · verified end-to-end on a physical Android 15 device.

Fixes: #8 #24 #27 #34 #36 #37 #39 #41 (and #31 — docs are back).

1.0.3+3

Choose a tag to compare

@jvoltci jvoltci released this 15 Mar 09:10
30cf9f5
Merge pull request #7 from jvoltci/sync-bug

Fixed: Sync Thread  bug