3

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?

Anil
  • 1,087
  • 1
  • 11
  • 24
1110
  • 7,829
  • 55
  • 176
  • 334
  • add runtime permission Beginning in Android 6.0 (API level 23), users grant permissions to apps while the app is running, not when they install the app. [read from docs](https://developer.android.com/training/permissions/requesting.html) – AskNilesh Jul 31 '17 at 11:52
  • Possible duplicate of [Android marshmallow request permission?](https://stackoverflow.com/questions/33666071/android-marshmallow-request-permission) – rohitanand Jul 31 '17 at 11:54
  • Hi you found solution here for this question please follow this link https://stackoverflow.com/questions/39866869/how-to-ask-permission-to-access-gallery-on-android-m/39866945#39866945 – Dileep Patel Jul 31 '17 at 12:00
  • Did I understand correctly. From API 23 I must write code that check if permission is allowed and ask user to allow it manually? Please note that I am using react native to build android project. – 1110 Jul 31 '17 at 12:03
  • Yes you need to do that even in react Native – Kapil G Jul 31 '17 at 12:11
  • add runtime permission for android 6 and above – Yogesh Mane Jul 31 '17 at 12:20
  • I am confused now :-/ is that some option in config or manually implement check? @YogeshMane – 1110 Jul 31 '17 at 12:22
  • @1110 I have added the react native code as well in my answer on how you can do that. Please check – Kapil G Jul 31 '17 at 12:24
  • @1110 you have to check permission in java code at run time check following ans for runtime permission – Yogesh Mane Jul 31 '17 at 12:24

3 Answers3

6

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});
    })
  }

}

Mike R Emo
  • 121
  • 3
  • 2
5

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;

    }
}
Kapil G
  • 4,081
  • 2
  • 20
  • 32
  • 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. – Davide Visentin Apr 09 '19 at 11:52
1
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);
                    }
                }
jojo
  • 463
  • 2
  • 5
  • 17