Using Storage Permission in Flutter

Mar 21, 2021 . 3 min Muhammed Mukhthar CM Cover Image

Flutter is an awesome toolkit. It allows us for fast UI iteration. But what if we are not able to access the storage of the device we’re running on? In this guide, we’ll go through how we can get the storage permission in a Flutter Application.

Prerequisites

Platform setup

For this guide, I assume you’re using an Android Device. Normally, In Android, we have to add these lines to our AndroidManifest.xml file.

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

For those who don’t know, this file is located in 3 locations.

I’ll be sufficient to make the changes inside the one inside main folder.

And one thing to take note is that, if your App is Targeting Android Q or above, you’ll have to make the below change also.

<application
        android:requestLegacyExternalStorage="true"

Don’t worry! Example file in Embedded below 😊. You can Clear all your doubts by comparing it with yours.

Packages

for this guide, we need a package called permission_handler in our pubspec.yaml

dependencies:
  flutter:
    sdk: flutter
  cupertino_icons: ^1.0.2
  permission_handler: ^6.1.1

Dart Code!

The first thing we wanna do is to ask the user permission for accesing the storage. Let’s create a function for this.

  Future _getStoragePermission() async {
    if (await Permission.storage.request().isGranted) {
      setState(() {
        permissionGranted = true;
      });
    }
  }

The above code checks if the app have permission to access storage. And if permission is not granted yet, it’ll request the permission. And sets the value of the boolean permissionGranted to true.

But there may be cases when user have already chose, Deny And Don't Ask Again option android presents. In that case, the only option we have is to let the user grant the permission manually. But it is a bad Experience if the user have to go all the way into settings and find your app.

For this purpose, the permission_handler library provides a handy shortcut.

Future _getStoragePermission() async {
  if (await Permission.storage.request().isGranted) {
    setState(() {
      permissionGranted = true;
    });
  } else if (await Permission.storage.request().isPermanentlyDenied) {
    await openAppSettings();
  } else if (await Permission.storage.request().isDenied) {
    setState(() {
      permissionGranted = false;
    });
  }
}

The above code checks if the Permission is permanentlyDenied. If it is , it’ll open the settings page of the App for user by using openAppSettings() provided by permission_handler package.

You can Alter the above code according to your requirements.

I think this post was useful to you. If it is, please do share this in your circle, so that more people can make use of this 😊. And Follow me on Twitter for getting more posts like these 😉.

Also if you found any mistakes or have any suggestions, don’t hesitate to ping me on my Twitter or to drop a mail at mukhtharcm@gmail.com.

Sample AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.status_downloader">
  <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
   <application
        android:requestLegacyExternalStorage="true"
        android:label="storage_demo"
        android:icon="@mipmap/ic_launcher">
        <activity
            android:name=".MainActivity"
            android:launchMode="singleTop"
            android:theme="@style/LaunchTheme"
            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
            android:hardwareAccelerated="true"
            android:windowSoftInputMode="adjustResize">
            <!-- Specifies an Android theme to apply to this Activity as soon as
                 the Android process has started. This theme is visible to the user
                 while the Flutter UI initializes. After that, this theme continues
                 to determine the Window background behind the Flutter UI. -->
            <meta-data
              android:name="io.flutter.embedding.android.NormalTheme"
              android:resource="@style/NormalTheme"
              />
            <!-- Displays an Android View that continues showing the launch screen
                 Drawable until Flutter paints its first frame, then this splash
                 screen fades out. A splash screen is useful to avoid any visual
                 gap between the end of Android's launch screen and the painting of
                 Flutter's first frame. -->
            <meta-data
              android:name="io.flutter.embedding.android.SplashScreenDrawable"
              android:resource="@drawable/launch_background"
              />
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <!-- Don't delete the meta-data below.
             This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
        <meta-data
            android:name="flutterEmbedding"
            android:value="2" />
    </application>
</manifest>