Android-要求写入SD卡权限对话框

时间:2019-03-01 13:11:40

标签: android android-permissions android-sdcard

我无法获得对设备SD卡根目录的写访问权。我可以毫无问题地写入SD卡中的设备内部存储和应用包文件夹。我发现可以使用Storage Access Framework获得对SD卡的访问权限,因此我查看了其他应用程序以了解它们如何获得对SD卡的访问权限,并找到了Total Commander及其简洁的权限对话框。

write to SD card permission dialog

由于找不到任何示例,如何显示此类对话框?我的目标是将大型文件存储在SD卡上,并在卸载该应用程序后保留。

类似的问题:

Android (Write on external SD-Card): java.io.IOException: Permission denied

Android M write to SD Card - Permission Denied

Android SD Card Write Permission using SAF (Storage Access Framework)

2 个答案:

答案 0 :(得分:0)

我找到了开源文件管理器。查看代码,终于找到了解决方案。

仅适用于Android N(7.0.0)(api 24)及更高版本。

首先获取SD卡的根路径并显示用户权限对话框。

public void takeCardUriPermission(String sdCardRootPath) {
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
            File sdCard = new File(sdCardRootPath);
            StorageManager storageManager = (StorageManager) getSystemService(Context.STORAGE_SERVICE);
            StorageVolume storageVolume = storageManager.getStorageVolume(sdCard);
            Intent intent = storageVolume.createAccessIntent(null);
            try {
                startActivityForResult(intent, 4010);
            } catch (ActivityNotFoundException e) {
            }
        }
    }

当用户接受请求时,onActivityResult()被触发,我们可以从意图数据中保存uri

protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if (requestCode == 4010) {

            Uri uri = data.getData();

            grantUriPermission(getPackageName(), uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION |
                    Intent.FLAG_GRANT_READ_URI_PERMISSION);

            final int takeFlags = data.getFlags() & (Intent.FLAG_GRANT_WRITE_URI_PERMISSION |
                    Intent.FLAG_GRANT_READ_URI_PERMISSION);

            getContentResolver().takePersistableUriPermission(uri, takeFlags);
        }
    }

现在我们可以检索SD卡根目录的uri并将其与Storage Access Framework一起使用

public Uri getUri() {
        List<UriPermission> persistedUriPermissions = getContentResolver().getPersistedUriPermissions();
        if (persistedUriPermissions.size() > 0) {
            UriPermission uriPermission = persistedUriPermissions.get(0);
            return uriPermission.getUri();
        }
        return null;
    }

答案 1 :(得分:0)

不幸的是,现在在Android Q中不建议使用createAccessIntent,documentation指出,如果在Android Q中使用它,它将立即返回RESULT_CANCELED。

他们建议您将意图与ACTION_OPEN_DOCUMENT_TREE一起使用。您可以指定最初打开的目录(仅在Android O及更高版本上受支持),从而使用户更容易使用,但这仍然不是一个好主意。用户友好的方法。

我想知道是否有人知道其他任何用户友好的解决方案?我不明白为什么Android删除了createAccessIntent,因为这似乎是最用户友好的方式。