dir_picker 0.2.1
dir_picker: ^0.2.1 copied to clipboard
A Flutter plugin for picking directories, supporting Android, iOS, macOS, Windows, Linux and Web via FFI and JNI.
dir_picker #
A Flutter plugin for picking a directory across all platforms using native system dialogs. Returns a Uri? — null if the user cancelled.
Features #
- 📁 All Platforms – Android, iOS, macOS, Windows, Linux, and Web
- ⚡ Native Performance – Powered by FFI (iOS/macOS/Windows) and JNI (Android) for near-zero overhead
- 🎨 Customizable Dialogs – Platform-specific options for title, button labels, and more
- 🔗 Persistent Permissions – Android SAF persistent URI access across reboots
- 🐧 Linux Portals – XDG Desktop Portal with zenity/kdialog fallback
If you want to say thank you, star us on GitHub or like us on pub.dev.
Installation #
First, follow the package installation instructions and add
dir_picker to your app.
Quick Start #
Platform Setup #
Android Configuration
Supported: API 21+ (Android 5.0+)
No configuration needed. The plugin uses the Storage Access Framework (Intent.ACTION_OPEN_DOCUMENT_TREE), which grants URI access through the system picker UI — no manifest permissions required.
iOS Configuration
Supported: iOS 13.0+
No configuration needed. The plugin uses UIDocumentPickerViewController, which is available without extra entitlements.
macOS Configuration
Supported: macOS 10.15+
Add the following entitlement to macos/Runner/Release.entitlements and macos/Runner/DebugProfile.entitlements:
<key>com.apple.security.files.user-selected.read-write</key>
<true/>
Windows Configuration
Supported: Windows 10+
No configuration needed. The plugin uses the native IFileOpenDialog COM API.
Linux Configuration
The plugin tries the following dialog backends in order:
- XDG Desktop Portal – Works on all modern desktop environments via D-Bus (
org.freedesktop.portal.FileChooser) - zenity – GNOME fallback
- kdialog – KDE fallback
If none are available, the pick call throws. To install a fallback manually:
# GNOME
sudo apt install zenity
# KDE
sudo apt install kdialog
Web Configuration
No configuration needed. The plugin uses the File System Access API.
Browser support: Chrome 86+ and Edge 86+. Not supported in Firefox or Safari.
Note: On web, the returned
Uripath contains only the directory name — browsers do not expose full filesystem paths for security reasons.
Basic Usage #
import 'package:dir_picker/dir_picker.dart';
final Uri? uri = await DirPicker.pick();
if (uri != null) {
print('Selected: $uri');
} else {
print('Cancelled');
}
Platform Options #
Each platform exposes its own options class for customizing the dialog. Pass them to DirPicker.pick():
final uri = await DirPicker.pick(
androidOptions: const AndroidOptions(shouldPersist: true),
macosOptions: const MacosOptions(acceptLabel: 'Choose', message: 'Select a project folder'),
linuxOptions: const LinuxOptions(title: 'Select Folder', acceptLabel: 'Choose'),
windowsOptions: const WindowsOptions(title: 'Select Folder', acceptLabel: 'Choose'),
);
AndroidOptions #
| Parameter | Type | Default | Description |
|---|---|---|---|
shouldPersist |
bool |
true |
Take persistable URI permission so the app retains access across reboots (SAF takePersistableUriPermission). |
MacosOptions #
| Parameter | Type | Default | Description |
|---|---|---|---|
acceptLabel |
String |
'Select' |
Label for the confirmation button (NSOpenPanel.prompt). |
message |
String |
'Choose a directory' |
Descriptive text shown inside the panel (NSOpenPanel.message). |
LinuxOptions #
| Parameter | Type | Default | Description |
|---|---|---|---|
title |
String |
'Select Directory' |
Window title of the dialog. |
acceptLabel |
String |
'Select' |
Label for the confirmation button (XDG Portal and zenity only). |
WindowsOptions #
| Parameter | Type | Default | Description |
|---|---|---|---|
title |
String |
'Select Directory' |
Window title of the dialog (IFileDialog::SetTitle). |
acceptLabel |
String |
'Select' |
Label for the confirmation button (IFileDialog::SetOkButtonLabel). |
Core Concepts #
Return value #
| Result | Meaning |
|---|---|
Uri |
The selected directory URI. |
null |
The user cancelled. |
Native Mechanisms #
| Platform | Mechanism |
|---|---|
| Android | SAF (Intent.ACTION_OPEN_DOCUMENT_TREE) via JNI |
| iOS | UIDocumentPickerViewController via FFI |
| macOS | NSOpenPanel via FFI |
| Windows | IFileOpenDialog (COM) via pure Dart FFI |
| Linux | XDG Desktop Portal → zenity → kdialog |
| Web | window.showDirectoryPicker() (JS interop) |
Common Use Cases #
Simple directory pick #
final uri = await DirPicker.pick();
if (uri != null) {
print('Selected: $uri');
}
Custom dialog labels #
final uri = await DirPicker.pick(
macosOptions: const MacosOptions(
acceptLabel: 'Use This Folder',
message: 'Select the folder to import from',
),
linuxOptions: const LinuxOptions(
title: 'Import Folder',
acceptLabel: 'Use This Folder',
),
windowsOptions: const WindowsOptions(
title: 'Import Folder',
acceptLabel: 'Use This Folder',
),
);
Android — enable persistent permission #
final uri = await DirPicker.pick(
androidOptions: const AndroidOptions(shouldPersist: true),
);
API Reference #
DirPicker.pick #
static Future<Uri?> pick({
AndroidOptions? androidOptions,
LinuxOptions? linuxOptions,
MacosOptions? macosOptions,
WindowsOptions? windowsOptions,
})
Returns the selected directory as a Uri, or null if the user cancelled.
Platform Support #
| Android | iOS | macOS | Windows | Linux | Web |
|---|---|---|---|---|---|
| ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
Minimum versions:
- Flutter ≥ 3.3.0
- Dart SDK ≥ 3.6.0
- Kotlin 2.1.0
- Swift 5.9
- Android API 21+
- iOS 13.0+
- macOS 10.15+
- Windows 10+
- Web: Chrome/Edge 86+
Contributing #
Contributions are welcome! Please feel free to submit a Pull Request.
License #
MIT License — see LICENSE file for details.