Path Manager
A plugin providing unified access to commonly used host filesystem directories on Android, iOS, and macOS.
This plugin leverages direct native interop using Java Native Interface (JNI) on Android, and Objective-C FFI on iOS and macOS.
Platform & Method Support
| Method | Android | iOS | macOS | Description |
|---|---|---|---|---|
getTemporaryDirectory() |
✅ | ✅ | ✅ | Temporary directory for cache files (subject to OS cleanup). |
getApplicationSupportDirectory() |
✅ | ✅ | ✅ | Application-created directory for app state, databases, etc. |
getApplicationDocumentsDirectory() |
✅ | ✅ | ✅ | User-accessible directory for persistent documents/profiles. |
getCachesDirectory() |
✅ | ✅ | ✅ | Cache directory (persists longer than temporary files). |
getApplicationNoBackupPath() |
✅ | ✅ | ✅ | Resolves a default directory that is excluded from backups. |
setApplicationPathIsExcludedFromBackup(...) |
❌ Throws | ✅ | ✅ | Programmatically toggles the backup exclusion flag. |
Features
- Direct interop: Built completely with JNI and FFI interop—no MethodChannels.
- Tree shakeable: Platform-specific code and dependencies are only compiled and included for their target platform.
- Dedicated No-Backup Directories: Provides a default folder named
__no_backup__that is automatically marked for exclusion from platform backup systems. - Custom exclusions: Mark any arbitrary file or folder on iOS/macOS to be skipped during iCloud/iTunes backups.
Installation
Add path_manager to your pubspec.yaml dependencies:
dependencies:
path_manager:
path: ^0.5.0
Then run:
flutter pub get
Configuration
iOS & macOS
No additional setup is required. The plugin programmatically sets the NSURLIsExcludedFromBackupKey resource key using iOS/macOS Foundation APIs when managing exclusions.
Android
On Android, programmatic runtime backup exclusion on arbitrary filesystem entities is not supported by the OS. Instead, Android backup exclusions are configured statically via resource XML files.
To exclude the default __no_backup__ directory (which resolves to app_support_path/__no_backup__) from Android Auto Backup and Device-to-Device transfer, follow these setup steps:
1. Define Backup Rules (Android 11 and lower)
Create a file named backup_rules.xml in your Android project's resource directory (android/app/src/main/res/xml/backup_rules.xml):
<?xml version="1.0" encoding="utf-8"?>
<full-backup-content>
<!-- Exclude the __no_backup__ subdirectory inside the application files directory -->
<exclude domain="file" path="__no_backup__" />
</full-backup-content>
2. Define Data Extraction Rules (Android 12 / API 31 and above)
Create a file named data_extraction_rules.xml in your Android project's resource directory (android/app/src/main/res/xml/data_extraction_rules.xml):
<?xml version="1.0" encoding="utf-8"?>
<data-extraction-rules>
<cloud-backup>
<!-- Exclude from Cloud Backups -->
<exclude domain="file" path="__no_backup__" />
</cloud-backup>
<device-transfer>
<!-- Exclude from Device-to-Device Transfer -->
<exclude domain="file" path="__no_backup__" />
</device-transfer>
</data-extraction-rules>
3. Register XML Rules in AndroidManifest.xml
In your android/app/src/main/AndroidManifest.xml file, link the rules inside the <application> element:
<application
android:allowBackup="true"
android:fullBackupContent="@xml/backup_rules"
android:dataExtractionRules="@xml/data_extraction_rules"
... >
Usage
1. Retrieving Standard Directories
import 'package:path_manager/path_manager.dart';
// Retrieve paths as standard dart:io Directory instances
final Directory temp = await PathManager.getTemporaryDirectory();
final Directory support = await PathManager.getApplicationSupportDirectory();
final Directory docs = await PathManager.getApplicationDocumentsDirectory();
final Directory caches = await PathManager.getCachesDirectory();
print('Support Dir: ${support.path}');
2. Getting the Dedicated No-Backup Path
The getApplicationNoBackupPath() method provides a default directory path. If the directory does not exist, it is automatically created and (on Apple platforms) marked as excluded from backups.
import 'dart:io';
import 'package:path_manager/path_manager.dart';
try {
final String noBackupPath = await PathManager.getApplicationNoBackupPath();
final File localConfig = File('$noBackupPath/settings.json');
await localConfig.writeAsString('{"offline_mode": true}');
print('Saved sensitive offline settings to: $noBackupPath');
} on BackupExclusionConflictException catch (e) {
// Occurs if the __no_backup__ folder exists but was manually un-excluded
print('Conflict detected: ${e.message}');
} on MissingPlatformDirectoryException catch (e) {
print('Failed to resolve path: ${e.message}');
}
3. Programmatic Backup Exclusion (iOS & macOS Only)
You can programmatically exclude individual files or directories on iOS and macOS.
import 'dart:io';
import 'package:path_manager/path_manager.dart';
final Directory docsDir = await PathManager.getApplicationDocumentsDirectory();
final File localDatabase = File('${docsDir.path}/app_db.sqlite');
try {
// Exclude the SQLite file from iCloud/iTunes backups
await PathManager.setApplicationPathIsExcludedFromBackup(localDatabase.path, true);
print('Successfully excluded local database from backups.');
} on UnsupportedError catch (e) {
// Thrown on Android
print('Programmatic exclusions are not supported on this platform: ${e.message}');
} on FileSystemException catch (e) {
// Thrown if the target file/directory does not exist
print('Filesystem error: ${e.message}');
}
Contributing
We welcome contributions to this project!
Setting Up For Local Development
- Clone the repository and run dependencies setup:
flutter pub get - Generate FFI/JNI bindings:
- For Android (requires
JAVA_HOMEpointing to a JDK):dart run tools/jnigen.dart - For iOS/macOS:
dart run tools/ffigen.dart
- For Android (requires
- Format all files before pushing:
dart format .
Running Tests
Run the test suite on your development machine (macOS/Linux/Windows):
dart test
License
This package is licensed under the MIT License. See LICENSE for more details.