READ_EXTERNAL_STORAGE 权限在清单中,但仍然无效

READ_EXTERNAL_STORAGE permission is in manifest but still doesn't work

在 androidmanifest.xml 我有:

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

在 build.gradle 我有:

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.1"

    defaultConfig {
        multiDexEnabled true
        applicationId "test"
        minSdkVersion 16
        targetSdkVersion 23

如果我尝试调用 CameraRoll.getPhotos() 获取图书馆照片,我会收到错误消息:

Could not get photos: need READ_EXTERNAL_STORAGE permission
    at createErrorFromErrorData

我正在尝试在带有 android 6 和 7 的真实设备上运行 运行 应用程序,并且我正在尝试使其像 IOS 中那样工作 - 当调用 getPhotos( ) 查看权限请求对话框。
这里有什么问题?

要请求任何权限,您可以使用以下代码并添加您需要的权限。这就是您在访问与权限相关的任何数据之前请求它们来处理运行时权限的方式

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

一旦你这样做,对于 API >=23 的设备,你将在运行时弹出窗口,然后一旦用户接受或拒绝许可,你的 onRequestPermissionsResult 方法就会被调用。所以在这里你必须检查用户是否授予了应用程序权限。如果是,你可以继续你的逻辑

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

更新 1 对于 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;

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

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

}