πŸ“ Flutter SAF (Storage Access Framework) Helper

FlutterSaf is a helper class designed to simplify directory access and file operations using Android’s Storage Access Framework (SAF) in Flutter. It allows developers to easily request directory access, manage permissions, read file contents, and more β€” all through a unified API.


πŸš€ Features

  • βœ… Request directory access
  • βœ… Check and release persisted permissions
  • βœ… Read file contents as bytes
  • βœ… Fetch list of files in a directory
  • βœ… Generate thumbnails for media files

πŸ“¦ Installation

Add this package and its dependencies:

dependencies:
  flutter_saf: 

Then run:

flutter pub get

🧩 Usage

Step 1: Import the package

import 'package:flutter_saf/flutter_saf.dart';

Step 2: Initialize with a directory path

final flutterSaf = FlutterSaf(directory: '/storage/emulated/0/Download');

πŸ“š API Reference & Examples


πŸ“‚ getDirectory()

Returns the directory path provided during initialization.

print('Selected directory: ${flutterSaf.getDirectory()}');

🌐 getUriString() and getUri()

Returns the directory URI in string or Uri form.

print('Directory URI string: ${flutterSaf.getUriString()}');

final uri = flutterSaf.getUri();
print('Directory URI object: $uri');

πŸ” requestDirectoryAccess()

Requests access to the directory. If permission already exists, returns true; otherwise opens the picker.

final granted = await flutterSaf.requestDirectoryAccess(allowWriteAccess: true);
if (granted == true) {
  print('Directory access granted!');
} else {
  print('Access denied or cancelled.');
}

πŸ—οΈ getPersistedDirectoryPermissions()

Retrieves all persisted directory permissions as a list.

final permissions = await flutterSaf.getPersistedDirectoryPermissions();
permissions?.forEach((p) {
  print('Persisted URI: ${p.uri}');
  print('Read: ${p.isReadPermission}, Write: ${p.isWritePermission}');
});

πŸ”Ž hasPersistedDirectoryPermission()

Checks whether your app already has access to the initialized directory.

final hasPermission = await flutterSaf.hasPersistedDirectoryPermission();
print('Has permission: $hasPermission');

🚫 releasePersistedDirectoryPermission()

Releases the directory permission previously granted by the user.

await flutterSaf.releasePersistedDirectoryPermission();
print('Permission released successfully.');

πŸ“„ getContent()

Reads and returns file content from the current directory as bytes.

final bytes = await flutterSaf.getContent();
if (bytes != null) {
  print('File size: ${bytes.lengthInBytes} bytes');
}

πŸ’‘ Useful when reading files like PDFs, images, or documents.


🧾 getFilesUri()

Lists all files inside the selected directory.

final files = await flutterSaf.getFilesUri();
if (files != null && files.isNotEmpty) {
  for (final file in files) {
    print('File name: ${file.name}');
    print('URI: ${file.uri}');
  }
} else {
  print('No files found.');
}

πŸ–ΌοΈ getThumbnail(Uri fileUri, {int width, int height})

Generates a thumbnail for the specified file (commonly images or videos).

final uri = Uri.parse('content://com.android.providers.media.documents/document/image%3A12345');
final thumbnailBytes = await flutterSaf.getThumbnail(uri, width: 300, height: 300);

if (thumbnailBytes != null) {
  print('Thumbnail generated successfully (${thumbnailBytes.length} bytes)');
}

🧠 Example Use Case

void main() async {
  final saf = FlutterSaf(directory: '/storage/emulated/0/Documents');

  final accessGranted = await saf.requestDirectoryAccess();
  if (accessGranted == true) {
    final files = await saf.getFilesUri();
    print('Found ${files?.length ?? 0} files in directory.');
  }
}

🧩 Models

DirectoryPermission

Represents a persisted permission entry.

Property Type Description
uri String Directory URI
isReadPermission bool Whether read access is granted
isWritePermission bool Whether write access is granted
persistedTime int Time when the permission was granted

DocumentFileModel

Represents a document/file entry.

Property Type Description
name String File name
uri String File URI
type String MIME type
size int File size

🧾 Logging

You can easily print the class details:

print(flutterSaf.toString());
// Output: FlutterSaf(directory: /storage/emulated/0/Download, uri: content://...)

πŸ§‘β€πŸ’» Contributing

Pull requests and suggestions are welcome! If you encounter any issues, please open an issue on GitHub.

167d86b (chore: initial commit)

Libraries

flutter_saf