Skip to main content

Command Palette

Search for a command to run...

File and Folder Permissions in Flutter for Android

Updated
5 min read
F
Thinking...

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.