File and Folder Permissions in Flutter for Android
Many Flutter apps need access to device storage. Maybe you want to upload PDFs, pick images, download files, or save generated documents. That sounds straightforward until Android permissions enter the picture.
Modern Android versions heavily restrict storage access for privacy reasons. So if you skip proper permission handling, your app may work on one phone and completely fail on another.
This guide focuses only on the essential setup:
Adding Android storage permissions
Understanding Android version differences
Requesting runtime permissions from users
Preparing your Flutter app for file access
No deep file operations yet. Just the foundation you actually need first.
Why Android Storage Permissions Matter
Android does not automatically allow apps to access device files.
Even if your app wants to simply:
Pick a PDF
Upload an image
Download a document
Save a file
Android still requires explicit permission.
Think of it like entering a locked room. Declaring permissions in your app is like owning the keycard, but the user still has to unlock the door.
Android Storage Changed After Android 10
Older Android versions allowed broad storage access.
Modern Android introduced Scoped Storage, which restricts apps from freely accessing all folders.
Here’s the important timeline:
| Android Version | Storage Behavior |
|---|---|
| Android 9 and below | Easier full storage access |
| Android 10 | Scoped Storage introduced |
| Android 11+ | Stronger restrictions |
| Android 13+ | Media-specific permissions |
Because of this, many old Flutter tutorials are outdated.
Packages You Need
For permissions, most Flutter apps use:
| Package | Purpose |
|---|---|
permission_handler |
Request permissions |
file_picker |
Pick files later |
path_provider |
Safe app storage |
Useful package links:
Step 1: Add Dependencies
Open your pubspec.yaml.
dependencies:
flutter:
sdk: flutter
permission_handler: ^11.3.0
file_picker: ^8.0.0
Then run:
flutter pub get
Now your project is ready for permission handling.
Step 2: Add Android Permissions
Open:
android/app/src/main/AndroidManifest.xml
Permissions must be added above the <application> tag.
Add Internet Permission
If your app downloads or uploads files, add internet permission.
<uses-permission android:name="android.permission.INTERNET"/>
Storage Permissions for Android 12 and Below
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
These mainly support older Android versions.
Android 13+ Permissions
Android 13 introduced separate permissions for media.
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES"/>
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO"/>
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO"/>
Instead of asking for “entire storage,” Android now asks permission by media type.
That improves user privacy.
Full AndroidManifest Example
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Internet -->
<uses-permission android:name="android.permission.INTERNET"/>
<!-- Android 12 and below -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<!-- Android 13+ -->
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES"/>
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO"/>
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO"/>
<application
android:label="your_app_name"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher">
</application>
</manifest>
At this stage, your app declares what permissions it may request.
But Android still has one more step.
Step 3: Request Runtime Permission
Modern Android requires runtime permission requests.
Manifest permissions alone are not enough.
You must ask the user while the app is running.
Request Storage Permission in Flutter
import 'package:permission_handler/permission_handler.dart';
Future<void> requestPermission() async {
final status = await Permission.storage.request();
if (status.isGranted) {
print("Permission Granted");
} else {
print("Permission Denied");
}
}
This triggers the Android permission popup.
Without this step, storage-related features may silently fail.
Android 13 Permission Requests
For Android 13+, request media permissions instead.
await Permission.photos.request();
await Permission.videos.request();
await Permission.audio.request();
Only request the permissions your app actually needs.
If your app only handles images, don’t request audio access unnecessarily.
Common Beginner Mistakes
Forgetting Runtime Permission
Adding permissions in AndroidManifest.xml alone does not grant access.
You still need runtime requests.
Following Old Tutorials
Many tutorials written before Android 10 no longer work correctly.
Modern Android uses Scoped Storage restrictions.
Requesting Too Many Permissions
Only request what your app genuinely needs.
Users are more likely to trust apps with minimal permission requests.
Recommended Modern Approach
For most Flutter apps:
Use app-specific storage whenever possible
Request permissions only when needed
Prefer user-selected files over unrestricted storage access
Handle Android 13 permissions separately
That approach works reliably across modern Android versions.
Final Thoughts
Before reading or writing files in Flutter, permission handling must be configured properly. That setup forms the foundation for everything else like file pickers, downloads, uploads, and media access.
Once this permission layer is working correctly, adding actual file operations becomes much easier and far less frustrating.

