Skip to content

Install & first run

1. Add the dependency

dependencies:
  saf: ^2.0.0
flutter pub get

saf is Android-only and needs no runtime permissions — SAF grants are handled through the system picker.

Minimum versions

Dart ≥ 3.0, Flutter ≥ 3.10, Android minSdk 21.

2. Grant a directory

import 'package:saf/saf.dart';

final saf = Saf();

Future<void> pick() async {
  final dir = await saf.pickDirectory();   // opens the system folder picker
  if (dir == null) {
    // user cancelled
    return;
  }
  print('granted: ${dir.uri}');
}

The grant is persisted by default. On later launches, reuse it instead of prompting again:

final grants = await saf.persistedPermissions();
if (grants.isNotEmpty) {
  final dir = await saf.stat(grants.first.uri);
  // use dir without showing the picker
}

3. Read and write

// write
final doc = await saf.writeFileBytes(
  dir.uri, 'notes.txt', 'text/plain',
  utf8.encode('Hello from saf 2.0!') as Uint8List,
);

// read
final bytes = await saf.readFileBytes(doc.uri);
print(utf8.decode(bytes)); // Hello from saf 2.0!

4. Handle errors

Every operation throws a typed SafException:

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

Next: Recipes for every operation, or the full API reference.