READ_EXTERNAL_STORAGE permission is in manifest but still doesn't work

12,218

Solution 1

To request for any permission you can use the below code and add the permissions you need. This is how you handle runtime permissions by requesting them before accessing any data related to permission

public  boolean isStoragePermissionGranted() {
if (Build.VERSION.SDK_INT >= 23) {

    if (checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE)
            == PackageManager.PERMISSION_GRANTED) {
        Log.v(TAG,"Permission is granted");
        return true;
    } else {

        Log.v(TAG,"Permission is revoked");
        ActivityCompat.requestPermissions(this, new String[]{ Manifest.permission.READ_EXTERNAL_STORAGE}, 1);
        return false;
    }
}
else { //permission is automatically granted on sdk<23 upon installation
    Log.v(TAG,"Permission is granted");
    return true;
}
}

Once you do that, for devices with API >=23 You will get popup at runtime and then once the user accepts the permission or rejects it, your onRequestPermissionsResult method is called. so here you will have to handle your check whether user granted the app the permission. If yes you can continue with your logic

@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
    switch (requestCode) {
        case 0:
            boolean isPerpermissionForAllGranted = false;
            if (grantResults.length > 0 && permissions.length==grantResults.length) {
                for (int i = 0; i < permissions.length; i++){
                    if (grantResults[i] == PackageManager.PERMISSION_GRANTED){
                        isPerpermissionForAllGranted=true;
                    }else{
                        isPerpermissionForAllGranted=false;
                    }
                }

                Log.e("value", "Permission Granted");
            } else {
                isPerpermissionForAllGranted=true;
                Log.e("value", "Permission Denied");
            }
            if(isPerpermissionForAllGranted){
               // do your stuff here
            }
            break;
    }
}

UPDATE 1 For react Native

String[] perms = {
    "android.permission.READ_EXTERNAL_STORAGE", 
    "android.permission.WRITE_EXTERNAL_STORAGE"
};



@Override
public void onCreate (Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // Checking permissions on init
    checkPerms();
}


public void checkPerms() {
    // Checking if device version > 22 and we need to use new permission model 
    if(Build.VERSION.SDK_INT>Build.VERSION_CODES.LOLLIPOP_MR1) {
        // Checking if we can draw window overlay
        if (!Settings.canDrawOverlays(this)) {
            // Requesting permission for window overlay(needed for all react-native apps)
            Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
              Uri.parse("package:" + getPackageName()));
            startActivityForResult(intent, OVERLAY_PERMISSION_REQ_CODE);
        }
        for(String perm : perms){
            // Checking each persmission and if denied then requesting permissions
            if(checkSelfPermission(perm) == PackageManager.PERMISSION_DENIED){
                requestPermissions(perms, PERMISSION_REQ_CODE);
                break;
            }
        }
    }
}

// Window overlay permission intent result
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
  super.onActivityResult(requestCode, resultCode, data);
  if (requestCode == OVERLAY_PERMISSION_REQ_CODE) {
      checkPerms();
  }
}

// Permission results
@Override
public void onRequestPermissionsResult(int permsRequestCode, String[] permissions, int[] grantResults){
    switch(permsRequestCode){
        case PERMISSION_REQ_CODE:
            // example how to get result of permissions requests (there can be more then one permission dialog)
            // boolean readAccepted = grantResults[0]==PackageManager.PERMISSION_GRANTED;
            // boolean writeAccepted = grantResults[1]==PackageManager.PERMISSION_GRANTED;
            // checking permissions to prevent situation when user denied some permission
            checkPerms();
            break;

    }
}

Solution 2

Uses react-native PermissionAndroid class. https://facebook.github.io/react-native/docs/permissionsandroid

import { PermissionsAndroid } from 'react-native'

async requestExternalStoreageRead() {
    try {
        const granted = await PermissionsAndroid.request(
                  PermissionsAndroid.PERMISSIONS.READ_EXTERNAL_STORAGE,
                  {
                       'title': 'Cool App ...',
                       'message': 'App needs access to external storage'
                   }
        );

        return granted == PermissionsAndroid.RESULTS.GRANTED
} 
catch (err) {
  //Handle this error
  return false;
}

}

getPhotos = async () => {
    //Before calling getPhotos, request permission
    if (await this.requestExternalStoreageRead()){
        CameraRoll.getPhotos({
            first: 1000,
            assetType: 'All'
        })
        .then((r) => {
             this.setState({ photos: r.edges, summary: `Number of photos found ${r.edges.length}` })
    })
    .catch((error) => {
        this.setState({errorMsg: error.message});
    })
  }

}

Solution 3

Add This code to your Activity on create      

        if (ContextCompat.checkSelfPermission(UserActivity.this,
                        Manifest.permission.READ_EXTERNAL_STORAGE)
                        != PackageManager.PERMISSION_GRANTED) {
                    if (ActivityCompat.shouldShowRequestPermissionRationale(UserActivity.this,
                            Manifest.permission.READ_EXTERNAL_STORAGE)) {

                    } else {
                        ActivityCompat.requestPermissions(UserActivity.this,
                                new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
                                a);
                    }
                }
Share:
12,218
1110
Author by

1110

Updated on June 05, 2022

Comments

  • 1110
    1110 almost 2 years

    In androidmanifest.xml I have:

        <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> 
    <uses-sdk
            android:minSdkVersion="16"
            android:targetSdkVersion="23" />
    

    In build.gradle I have:

    android {
        compileSdkVersion 23
        buildToolsVersion "23.0.1"
    
        defaultConfig {
            multiDexEnabled true
            applicationId "test"
            minSdkVersion 16
            targetSdkVersion 23
    

    If i try to call CameraRoll.getPhotos() to get library photos I get error:

    Could not get photos: need READ_EXTERNAL_STORAGE permission
        at createErrorFromErrorData
    

    I am trying to run app on real device with android 6 and 7 on it, and I am trying to make it work like in IOS - when call getPhotos() to see permission request dialog.
    What is wrong here?

  • Davide Visentin
    Davide Visentin about 5 years
    In the second piece of code, it should be case 1 to match the request code passed in the first snippet. Better, you can use a constant.
  • Patrissol Kenfack
    Patrissol Kenfack almost 4 years
    This answer would be definitively the best one. It saved me a lot of time!!