How to Add a File Picker Flutter Plugin to Your Cross-Platform App
To add a file picker flutter plugin, run flutter pub add file_picker, declare native permissions in AndroidManifest.xml and Info.plist, then invoke await FilePicker.platform.pickFiles() to open the native file picker UI and receive selected files as PlatformFile objects.
Adding a file picker flutter plugin enables your Flutter application to access native file selection dialogs across Android, iOS, macOS, and web platforms. The file_picker package implements a federated plugin architecture that delegates platform-specific logic to separate implementations while exposing a unified Dart API. This guide walks through the complete integration process using the dependency management and registration mechanisms found in the flutter/flutter repository.
Installing the File Picker Dependency
The first step to add a file picker flutter plugin is declaring the dependency in your project configuration and resolving the federated platform implementations.
Using the Flutter CLI
Execute the following command in your project root:
flutter pub add file_picker
This command updates your pubspec.yaml and runs flutter pub get automatically. According to the Flutter tool's command handling in packages/flutter_tools/lib/src/commands/pub.dart, this workflow ensures the package and its transitive dependencies—including the federated implementations file_picker_android, file_picker_ios, file_picker_macos, and file_picker_web—are resolved and locked in pubspec.lock.
Configuring Native Platform Permissions
Because the file picker interacts with device storage and media libraries, you must declare permissions in native configuration files. The plugin leverages Flutter's generated plugin registrant system to handle native registration automatically without manual boilerplate.
Android Manifest Setup
Add the following permissions to android/app/src/main/AndroidManifest.xml:
<manifest ...>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<!-- Optional: write permission if you plan to create files -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<application ...>
</application>
</manifest>
The Android embedding automatically registers the plugin via GeneratedPluginRegistrant.java, located at engine/src/flutter/shell/platform/android/test/io/flutter/plugins/GeneratedPluginRegistrant.java in the Flutter repository. This generated class registers the plugin with the FlutterEngine at startup, eliminating the need for manual registration code in your MainActivity.
iOS Info.plist Setup
For iOS, add usage descriptions to ios/Runner/Info.plist:
<dict>
<key>NSPhotoLibraryUsageDescription</key>
<string>We need access to your photo library to let you pick files.</string>
<key>NSCameraUsageDescription</key>
<string>Camera access is required to pick photos directly.</string>
</dict>
Similar to Android, iOS uses GeneratedPluginRegistrant.swift (found at engine/src/flutter/shell/platform/ios/GeneratedPluginRegistrant.swift) to automatically register the plugin with the engine during app launch.
Web Configuration
No additional configuration is required for web platforms. The plugin automatically falls back to the HTML <input type="file"> element when running in a browser, handled by the file_picker_web implementation.
Implementing the File Picker API
Once dependencies and permissions are configured, you can invoke the file picker from your Dart code using the platform interface.
Basic File Selection
Import the package and call pickFiles():
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
Future<void> selectFiles() async {
final result = await FilePicker.platform.pickFiles(
allowMultiple: true,
type: FileType.any,
);
if (result == null) {
// User cancelled the picker
return;
}
// Process selected files
for (final file in result.files) {
print('Selected: ${file.name} (${file.size} bytes)');
}
}
The core API resides in packages/file_picker/file_picker/lib/file_picker.dart, where FilePicker.platform acts as the platform interface delegate that routes calls to the appropriate native implementation.
Handling FilePickerResult and PlatformFile
The pickFiles() method returns a FilePickerResult object containing a list of PlatformFile instances. Each PlatformFile provides:
name: The file name with extensionpath: The absolute file path (null on web)size: File size in bytesbytes: Uint8List containing the file data (available on all platforms, essential for web)
if (result != null) {
final PlatformFile file = result.files.first;
if (file.bytes != null) {
// Use file.bytes for upload or processing
await uploadFileData(file.bytes!, file.name);
}
if (file.path != null) {
// Use file.path for local file operations (mobile/desktop only)
final localFile = File(file.path!);
final contents = await localFile.readAsString();
}
}
Understanding the Federated Plugin Architecture
The file_picker plugin uses Flutter's federated plugin architecture. Rather than containing all platform logic in a single package, the implementation is split across platform-specific packages:
file_picker_androidfile_picker_iosfile_picker_macosfile_picker_web
When you add the top-level file_picker dependency, Flutter's tooling automatically resolves and includes the correct platform implementations based on your build target. This architecture is managed by the plugin handler logic in packages/flutter_tools/gradle/src/main/kotlin/plugins/PluginHandler.kt for Android builds, which copies the plugin's native AARs into the final application package.
Summary
- Install the plugin using
flutter pub add file_picker, which updatespubspec.yamland resolves federated platform dependencies via the Flutter tool's pub command handler inpackages/flutter_tools/lib/src/commands/pub.dart. - Configure permissions by adding
READ_EXTERNAL_STORAGEtoAndroidManifest.xmlandNSPhotoLibraryUsageDescriptiontoInfo.plist, allowing the plugin to access native file systems through the automatically generated registrants (GeneratedPluginRegistrant.javaandGeneratedPluginRegistrant.swift). - Implement the API by calling
FilePicker.platform.pickFiles(), which returns aFilePickerResultcontainingPlatformFileobjects withname,path,size, andbytesproperties. - Handle platform differences by checking for
path(null on web) and usingbytesfor universal file access, leveraging the federated plugin architecture that separates implementations intofile_picker_android,file_picker_ios, andfile_picker_web.
Frequently Asked Questions
How do I add a file picker flutter plugin without using the command line?
You can manually edit the pubspec.yaml file in your project root. Under the dependencies section, add file_picker: ^5.5.0 (or the latest version), then run flutter pub get to download the package. This achieves the same result as flutter pub add file_picker by invoking the pub logic defined in packages/flutter_tools/lib/src/commands/pub.dart.
Why does my app crash when opening the file picker on Android?
Crashes typically occur when the READ_EXTERNAL_STORAGE permission is missing from android/app/src/main/AndroidManifest.xml. The plugin requires this permission to access the device's file system through the native Android embedding. Additionally, on Android 10+ (API 29+), ensure you handle scoped storage properly or request the appropriate permissions, as the GeneratedPluginRegistrant.java (located at engine/src/flutter/shell/platform/android/test/io/flutter/plugins/GeneratedPluginRegistrant.java) registers the plugin but does not grant runtime permissions.
Can I use the file picker on web platforms, and what are the limitations?
Yes, the file_picker plugin supports web through the file_picker_web federated implementation. However, on web platforms, the path property of PlatformFile is always null because browsers cannot provide local file system paths for security reasons. You must use the bytes property to access file content, which loads the entire file into memory. This behavior is handled automatically by the plugin's web implementation without requiring additional configuration in index.html.
What is the difference between FileType.any and specific file types when picking files?
FileType.any allows the user to select any file type from the device's storage, mapping to generic MIME type filters on Android and uniform type identifiers on iOS. Specifying FileType.image, FileType.video, FileType.media, or FileType.custom restricts the picker to specific MIME types or file extensions, improving user experience by filtering the native file browser. These type constraints are passed through the method channel to the native implementations (file_picker_android and file_picker_ios) which apply the appropriate platform-specific filters before displaying the picker UI.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →