READ_EXTERNAL_STORAGE permission for Android

166,165

Solution 1

You have two solutions for your problem. The quick one is to lower targetApi to 22 (build.gradle file). Second is to use new and wonderful ask-for-permission model:

if (checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE)
        != PackageManager.PERMISSION_GRANTED) {

    // Should we show an explanation?
    if (shouldShowRequestPermissionRationale(
            Manifest.permission.READ_EXTERNAL_STORAGE)) {
        // Explain to the user why we need to read the contacts
    }

    requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
            MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE);

    // MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE is an
    // app-defined int constant that should be quite unique

    return;
}

Sniplet found here: https://developer.android.com/training/permissions/requesting.html

Solutions 2: If it does not work try this:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
    && ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
        REQUEST_PERMISSION);

return;

}

and then in callback

@Override
public void onRequestPermissionsResult(final int requestCode, @NonNull final String[] permissions, @NonNull final int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == REQUEST_PERMISSION) {
    if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
        // Permission granted.
    } else {
        // User refused to grant permission.
    }
}
}

that is from comments. thanks

Solution 2

You have to ask for the permission at run time:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
        && ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
    ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
            REQUEST_PERMISSION);
    dialog.dismiss();
    return;
}

And in the callback below you can access the storage without a problem.

@Override
public void onRequestPermissionsResult(final int requestCode, @NonNull final String[] permissions, @NonNull final int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == REQUEST_PERMISSION) {
        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            // Permission granted.
        } else {
            // User refused to grant permission.
        }
    }
}

Solution 3

Step1: add permission on android manifest.xml

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

Step2: onCreate() method

int permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);

    if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, MY_PERMISSIONS_REQUEST_READ_MEDIA);
    } else {
        readDataExternal();
    }

Step3: override onRequestPermissionsResult method to get callback

 @Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
    switch (requestCode) {
        case MY_PERMISSIONS_REQUEST_READ_MEDIA:
            if ((grantResults.length > 0) && (grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
                readDataExternal();
            }
            break;

        default:
            break;
    }
}

Note: readDataExternal() is method to get data from external storage.

Thanks.

Solution 4

I also had a similar error log and here's what I did-

  1. In onCreate method we request a Dialog Box for checking permissions

    ActivityCompat.requestPermissions(MainActivity.this,
    new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},1);
    
  2. Method to check for the result

    @Override
    public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
    switch (requestCode) {
        case 1: {
            // If request is cancelled, the result arrays are empty.
            if (grantResults.length > 0
                    && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // permission granted and now can proceed
             mymethod(); //a sample method called
    
            } else {
    
                // permission denied, boo! Disable the
                // functionality that depends on this permission.
                Toast.makeText(MainActivity.this, "Permission denied to read your External storage", Toast.LENGTH_SHORT).show();
            }
            return;
        }
        // add other cases for more permissions
        }
    }
    

The official documentation to Requesting Runtime Permissions

Solution 5

In 2021 I am facing this issue So I will solve this problem using the manifest file I add one tag inside application:

<application 
android:requestLegacyExternalStorage="true"
/>

NOTE: This only work until Android 10, see more information here

Share:
166,165

Related videos on Youtube

Slim Sim
Author by

Slim Sim

Updated on May 05, 2022

Comments

  • Slim Sim
    Slim Sim about 2 years

    I'm trying to access media files (music) on the users device to play them; an easy "hello world"-music player app.

    I've followed some tutorials and they basically give the same code. But it won't work; it keeps crashing and telling me:

    error.....
    Caused by: java.lang.SecurityException: Permission Denial: reading com.android.providers.media.MediaProvider uri content://media/external/audio/media from pid=27696, uid=10059 requires android.permission.READ_EXTERNAL_STORAGE, or grantUriPermission()
    ....
    

    Now, this is my manifest file:

    <?xml version="1.0" encoding="utf-8"?>
    <manifest
        xmlns:android="http://schemas.android.com/apk/res/android"
        package="slimsimapps.troff" >
    
        <uses-permission android:name="android.permission.MEDIA_CONTENT_CONTROL"/>
        <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    
    
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
    
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
    </manifest>
    

    This is my Java-method:

    public void initialize() {
        ContentResolver contentResolver = getContentResolver();
        Uri uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
        Cursor cursor = contentResolver.query(uri, null, null, null, null);
        if (cursor == null) {
            // query failed, handle error.
        } else if (!cursor.moveToFirst()) {
            // no media on the device
        } else {
            do {
                addSongToXML(cursor);
            } while (cursor.moveToNext());
        }
    }
    

    I have tried:

    To put this at different places in the manifest file:

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

    To add android:maxSdkVersion at Read external storage premission:

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

    To put this in the manifest / application / activity-tag:

    android:exported=“true”
    

    To put grantUriPremission between uri and cursro in the javamethod:

    grantUriPermission(null, uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
    

    To use this, it won't crash, but the cursor becomes null:

    uri = MediaStore.Audio.Media.getContentUri("EXTERNAL_CONTENT_URI”);
    

    To use INTERNAL content uri, this works as expected, but it only gives "OS-sounds" such as shutter-sound, low-battery-sound, button-click and such:

    uri = MediaStore.Audio.Media.INTERNAL_CONTENT_URI;
    

    Pleas help, this should not be a hard problem i know, but i feel like such a beginner!

    I have read and tried (or considered them to be not applicable for my problem):

    Stack trace:

    09-08 06:59:36.619    2009-2009/slimsimapps.troff D/AndroidRuntime﹕ Shutting down VM
        --------- beginning of crash
    09-08 06:59:36.619    2009-2009/slimsimapps.troff E/AndroidRuntime﹕ FATAL EXCEPTION: main
        Process: slimsimapps.troff, PID: 2009
        java.lang.IllegalStateException: Could not execute method for android:onClick
                at android.view.View$DeclaredOnClickListener.onClick(View.java:4452)
                at android.view.View.performClick(View.java:5198)
                at android.view.View$PerformClick.run(View.java:21147)
                at android.os.Handler.handleCallback(Handler.java:739)
                at android.os.Handler.dispatchMessage(Handler.java:95)
                at android.os.Looper.loop(Looper.java:148)
                at android.app.ActivityThread.main(ActivityThread.java:5417)
                at java.lang.reflect.Method.invoke(Native Method)
                at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
                at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
         Caused by: java.lang.reflect.InvocationTargetException
                at java.lang.reflect.Method.invoke(Native Method)
                at android.view.View$DeclaredOnClickListener.onClick(View.java:4447)
                at android.view.View.performClick(View.java:5198)
                at android.view.View$PerformClick.run(View.java:21147)
                at android.os.Handler.handleCallback(Handler.java:739)
                at android.os.Handler.dispatchMessage(Handler.java:95)
                at android.os.Looper.loop(Looper.java:148)
                at android.app.ActivityThread.main(ActivityThread.java:5417)
                at java.lang.reflect.Method.invoke(Native Method)
                at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
                at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
         Caused by: java.lang.SecurityException: Permission Denial: reading com.android.providers.media.MediaProvider uri content://media/external/audio/media from pid=2009, uid=10059 requires android.permission.READ_EXTERNAL_STORAGE, or grantUriPermission()
                at android.os.Parcel.readException(Parcel.java:1599)
                at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:183)
                at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:135)
                at android.content.ContentProviderProxy.query(ContentProviderNative.java:421)
                at android.content.ContentResolver.query(ContentResolver.java:491)
                at android.content.ContentResolver.query(ContentResolver.java:434)
                at slimsimapps.troff.MainActivity.initialize(MainActivity.java:106)
                at slimsimapps.troff.MainActivity.InitializeExternal(MainActivity.java:80)
                at java.lang.reflect.Method.invoke(Native Method)
                at android.view.View$DeclaredOnClickListener.onClick(View.java:4447)
                at android.view.View.performClick(View.java:5198)
                at android.view.View$PerformClick.run(View.java:21147)
                at android.os.Handler.handleCallback(Handler.java:739)
                at android.os.Handler.dispatchMessage(Handler.java:95)
                at android.os.Looper.loop(Looper.java:148)
                at android.app.ActivityThread.main(ActivityThread.java:5417)
                at java.lang.reflect.Method.invoke(Native Method)
                at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
                at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
        --------- beginning of system
    
    • Sunil Sunny
      Sunil Sunny over 8 years
      Strange that error is shown when you have not given this line in manifest <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> are you trying to read some files which is protected by some other apps?
    • Sharp Edge
      Sharp Edge over 8 years
      On which api level are you trying this ?
    • Sunil Sunny
      Sunil Sunny over 8 years
      Did you tried cleaning the project. ?
    • Slim Sim
      Slim Sim over 8 years
      @sunilsunny I'm not trying to read som files that are protected, not that I know of anyway, just a simple media player. Yes, I have tried to clean it, i have tried to restart computer, I have tried to generate a signed APK and publish it to google Play and access it as a tester, with no luck....
    • Slim Sim
      Slim Sim over 8 years
      @SharpEdge ; My AVD is the standard Nexus 5, api 23. My module gradle has: compileSdkVersion 23 buildToolsVersion "23.0.0" minSdkVersion 14 targetSdkVersion 23 So i would say 23.
    • k3b
      k3b over 8 years
      can you open your specific audio with any other media player? is the file drm protected? or is located in a protected directory where only super-user has access to?
    • Slim Sim
      Slim Sim over 8 years
      @k3b I don't have any other audio on my AVD, but I would like for my app to say, nrSongs=0, instead of crashing. On my mobile device i have songs, which I can open with both Google Play Music, and another music player I downloaded from the play store. so, Yes - I Can. "Is the file drm protected?" - I don't know, I just want to access all the music files that I'm allowed to access... like a music player... "Is it located in a protected directory..." same anser as before. Note; I'm not including the audio as part of the app, I want to play the audio from the users media library.
  • Slim Sim
    Slim Sim over 8 years
    Thanks, I have tried something similar before, but I tried your code and it crashes on "cursor = managedQuery(allsongsuri, STAR, selection, null, null);", same error as before. By the way; managedQuery is deprecated, but it still crashes if i change it to "contentResolver.query", which have the same input parameters...
  • Slim Sim
    Slim Sim over 8 years
    Thanks, I tried your suggestion but it crashed on the same spot... I'm using a Mac, can that be a problem?
  • Derek Fung
    Derek Fung over 8 years
    updated, try to remove <uses-permission android:name="android.permission.MEDIA_CONTENT_CONTROL"/> and try? It may create strange behaviour because your app request for an permission not allowed
  • Rajan Bhavsar
    Rajan Bhavsar over 8 years
    Hi I am able to get All sdcadr Songs using above code. with Android Version 4.2.2 Device and also able to with Version 5.0.2. In which You are trying. What Error you got please describe with Android Version
  • Slim Sim
    Slim Sim over 8 years
    thanks, i tried to remove that permission, but it crashes at the same spot with the same error...
  • Slim Sim
    Slim Sim over 8 years
    I have updated the question with the stack-trace, hope that helps. What do you mean with Android Version? (I'm using apk 23)
  • Rajan Bhavsar
    Rajan Bhavsar over 8 years
    Ok Let me Give Full Source code and Check Out that again.
  • Slim Sim
    Slim Sim over 8 years
    if you want to test for yourself, download the zip here: drive.google.com/open?id=0B2AV8VRk9HUeVzFXSWVRZU9TRUk when you run it, press the left initialize-button, to generate the crach.
  • Slim Sim
    Slim Sim over 8 years
    Yes, of course! The new permission model Google introduced with the latest Android! Thank you, I will test this as soon as possible and mark it correct if it works! (and i was beginning to think this was forgotten!)
  • maclir
    maclir about 8 years
    The permission that is being requested should be READ_EXTERNAL_STORAGE. Like in this answer.
  • George Kagan
    George Kagan almost 8 years
    Worked for me using Cordova, by setting only the max SDK version in AndroidManifest.xml to 22 (instead of 23)
  • Renascienza
    Renascienza over 7 years
    I think you misplaced the needed permission here: is READ_EXTERNAL_STORAGE.
  • Renascienza
    Renascienza over 7 years
    swap != PackageManager.READ_EXTERNAL_STORAGE for != PackageManager.PERMISSION_GRANTED
  • piotrpo
    piotrpo over 7 years
    @Renascienza, yes you're right. Someone edited this answer in wrong way.
  • TheQ
    TheQ about 7 years
    where does checkSelfPermissions() come from, im getting a red line error here?
  • Solo
    Solo almost 7 years
    What is MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE ?
  • piotrpo
    piotrpo almost 7 years
    @Solo Just an int constant used to identify permission granted event in the callback. This value is returned as a param to onRequestPermissionResult(...) method.
  • Mahdi H
    Mahdi H almost 7 years
    i used it and it worked perfectly does it work on all android devices ?
  • Ateş Danış
    Ateş Danış over 2 years
    requestLegacyExternalStorage *typo