saf 2.0.1 copy "saf: ^2.0.1" to clipboard
saf: ^2.0.1 copied to clipboard

PlatformAndroid

Flutter plugin that leverages Storage Access Framework (SAF) API to get access and perform the operations on files and folders.

saf — one class for the Android Storage Access Framework

Saf CI pipeline status

Saf #

One package for the Android Storage Access Framework: pickers, persisted permissions, file management with recursive walk, streamed read/write with progress, and local-file bridging — all in a single Saf class.

Highlights #

  • One class, no ceremony — pickers, permissions, file management, and I/O all on Saf; no isDir parameters anywhere.
  • Typed errorsSafPermissionException, SafNotFoundException, SafAlreadyExistsException, SafIoException.
  • Recursive walk() plus recursive copyTo / moveTo with progress callbacks.
  • Streaming I/O — backpressured readFileStream and one-call writeFileStream for large files.
  • Persisted permissions — grant once, reuse across restarts; list them with persistedPermissions().
  • Hidden folders — read dotfile folders (e.g. WhatsApp .Statuses) and pull them into your app dir with copyDirToLocal.
  • Broad support — Dart ≥ 3.0, Flutter ≥ 3.10, Android minSdk 21.

Quick start #

import 'package:saf/saf.dart';

final saf = Saf();

// 1. Ask once — the grant persists across restarts.
final dir = await saf.pickDirectory();
if (dir == null) return; // user cancelled

// Later launches: reuse the grant instead of prompting again.
final grants = await saf.persistedPermissions();

// 2. Manage files.
final files = await saf.list(dir.uri);
final report = await saf.mkdirp(dir.uri, ['reports', '2026']);
await for (final entry in saf.walk(dir.uri)) {
  print(entry.relativePath);
}

// 3. Read and write.
final doc = await saf.writeFileBytes(
    report.uri, 'summary.txt', 'text/plain', utf8.encode('hi') as Uint8List);
final bytes = await saf.readFileBytes(doc.uri);
final stream = await saf.readFileStream(doc.uri); // large files

// 4. Bridge to real file paths when another API needs one.
await saf.copyToLocalFile(doc.uri, '${cacheDir.path}/summary.txt',
    onProgress: (p) => print('${p.bytesDone}/${p.totalBytes}'));

Errors are typed — catch what you care about:

try {
  await saf.delete(uri);
} on SafPermissionException {
  // re-pick the directory
} on SafNotFoundException {
  // already gone
}

Migrating #

From saf 1.x #

The old path-based class still works as LegacySaf (deprecated, removed in 3.0.0): rename Saf(LegacySaf( and migrate at your own pace. The new API is URI-based — start from pickDirectory() and store URIs, not paths.

Scope #

saf keeps a focused, purposeful API. Intentionally out of scope for now:

  • Media picking — use image_picker / photo_manager, which specialize in it.
  • Raw file descriptors and thumbnails — niche; open an issue if you need them and they can land in a 2.1+.

Architecture #

saf is a single package with a mockable platform-interface layer, a thin Dart facade, and one coroutine-based Kotlin handler on a dedicated channel — the legacy 1.x channels are left untouched.

Flow: your app → Saf (facade) → SafPlatform → method channel → SafV2Api (Kotlin, coroutines) → DocumentsContract → Android SAF. All I/O runs off the main thread; the legacy 1.x channels are untouched.

See the architecture page for layer diagrams and a grant-then-read sequence.

Documentation #

Getting Started with Flutter #

For help getting started with Flutter, view the online documentation.


Built & maintained by jvoltci  ·  Docs  ·  Issues  ·  pub.dev  ·  MIT License

⭐ If saf saves you time, star the repo — it helps other Flutter devs find it.

70
likes
160
points
1.21k
downloads

Documentation

Documentation
API reference

Publisher

verified publisherivehement.com

Weekly Downloads

Flutter plugin that leverages Storage Access Framework (SAF) API to get access and perform the operations on files and folders.

Homepage
Repository (GitHub)
View/report issues
Contributing

License

MIT (license)

Dependencies

flutter, plugin_platform_interface

More

Packages that depend on saf

Packages that implement saf