Android 6.0:尽管有权限,但 SD 卡目录创建失败

Android 6.0: SD Card Directory creation fails in spite of having permissions

我正在尝试创建外部目录结构以将一些文件从设备存储移动到 Android 手机中的 SD 卡。我已按照 https://developer.android.com/training/permissions/requesting.html 中给出的步骤和多个 Whosebug 答案进行操作。但是,当我尝试创建目录时,我的程序失败了。

我的 AndroidManifest.xml 文件包含以下行:

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

相关代码如下:

    public int mkFolder(String folderName){
        String state = Environment.getExternalStorageState();
        if (!Environment.MEDIA_MOUNTED.equals(state)){
            Log.d(TAG, "Error: external storage is unavailable");
            return 0;
        }
        if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
            Log.d(TAG, "Error: external storage is read only.");
            return 0;
        }
        Log.d(TAG, "External storage is not read only or unavailable");

        boolean writePermission = ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED;
        boolean readPermission = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED;
        final boolean permissionNotGranted = writePermission|| readPermission;
        if (permissionNotGranted) {
            Log.i(TAG, "STORAGE permissions NOT granted");
            // Should we show an explanation?
            boolean shouldShowRationaleForWritePermssion = ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
            boolean shouldShowRationaleForReadPermssion = ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.READ_EXTERNAL_STORAGE);
            if (shouldShowRationaleForWritePermssion || shouldShowRationaleForReadPermssion) {

                // Show an explanation to the user *asynchronously* -- don't block
                // this thread waiting for the user's response! After the user
                // sees the explanation, try again to request the permission.

            } else {
                ActivityCompat.requestPermissions(this, PERMISSIONS_STORAGE, REQUEST_EXTERNAL_STORAGE);
            }
        } else {
            Log.i(TAG, "STORAGE permissions granted");
        }

//        File folder = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM),folderName);
        File folder = new File(folderName);
        int result = 0;
        if (folder.exists()) {
            Log.d(TAG,"folder exist:"+folder.toString());
            result = 2; // folder exist
        }else{
            try {
                if (folder.mkdirs()) {
                    Log.d(TAG, "folder created:" + folder.toString());
                    result = 0; // folder created
                } else {
                    Log.d(TAG, "create folder fails:" + folder.toString());
                    result = 1; // create folder fails
                }
            }catch (Exception ecp){
                ecp.printStackTrace();
            }
        }
        return result;
    }

    public static final int REQUEST_EXTERNAL_STORAGE = 112;
    private static String[] PERMISSIONS_STORAGE = {
            Manifest.permission.READ_EXTERNAL_STORAGE,
            Manifest.permission.WRITE_EXTERNAL_STORAGE
    };

    @Override
    public void onRequestPermissionsResult(int requestCode,
                                           @NonNull String permissions[], @NonNull int[] grantResults) {
        Log.e(TAG, "onRequestPermissionsResult invoked");
        switch (requestCode) {
            case REQUEST_EXTERNAL_STORAGE: {
                // If request is cancelled, the result arrays are empty.
                if (grantResults.length > 0
                        && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

                    // permission was granted, yay! Do the
                    // contacts-related task you need to do.
                    Log.i(TAG, "Permission to write to external storage granted");
                    Toast.makeText(this, "Permission to write to external storage granted", Toast.LENGTH_LONG).show();
                } else {
                    // permission denied, boo! Disable the
                    // functionality that depends on this permission.
                    Log.e(TAG, "Permission to write to external storage NOT granted");
                    Toast.makeText(this, "Permission to write to external storage NOT granted", Toast.LENGTH_LONG).show();
                }
            }
            // other 'case' lines to check for other
            // permissions this app might request
        }
    }

这是日志的摘录:

MainActivity: /storage/0000-0000    false   true
MainActivity: /storage/0000-0000/MyDir does not exist. Creating target parent directory
MainActivity: STORAGE permissions granted
MainActivity: Creation of directory /storage/0000-0000/MyDir failed with return value 1. Aborting...

谁能帮我理解我的代码中的错误是什么?

您不能直接访问文件系统上的任意位置 removable storage, starting with Android 4.4. WRITE_EXTERNAL_STORAGE is meaningless here, as external storage 不是可移动存储。

改用存储访问框架(ACTION_OPEN_DOCUMENT_TREE 和 kin)。或者,将您的工作限制在作为 getExternalFilesDirs()getExternalCacheDirs()getExternalMediaDirs()Context 上的所有方法)的一部分返回的可移动存储位置。