【问题标题】:Android - ask write to SD card permission dialogAndroid - 询问写入 SD 卡权限对话框
【发布时间】:2019-03-01 13:11:39
【问题描述】:

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

由于找不到任何示例,如何显示这样的对话框?我的目标是将卸载应用程序后保留的大文件存储在 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)

【问题讨论】:

标签: android android-permissions android-sdcard


【解决方案1】:

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

仅适用于 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 并将其与存储访问框架一起使用

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

【讨论】:

  • @a-urbanavičius 你能分享开源文件管理器应用程序的链接吗?它会帮助我。
  • 以及在哪里调用 getUri ??
  • @Nils github.com/1hakr/AnExplorer 是我发现的具有此对话框和源代码的应用程序。但请记住,如上述答案所述,android Q 中已弃用此对话框。同样对于uri,观看Android Storage Access Framework的教程,并不复杂。祝你好运。
  • @a-urbanavičius 感谢您的更新。真的对我有帮助。在 Android Q 中,这个对话框会消失还是不起作用??
  • @Nils 这不起作用,因为它不会显示对话框,而是返回 RESULT_CANCELED。
【解决方案2】:

不幸的是,现在 Android Q 已弃用 createAccessIntent,documentation 声明如果您在 Android Q 中使用它,它将立即返回 RESULT_CANCELED。

他们建议您使用带有ACTION_OPEN_DOCUMENT_TREE 的意图。您可以指定它最初打开的目录(仅在 Android O 及更高版本上支持),使用户更容易,但这仍然不是非常用户友好方法。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-01-08
    • 2016-08-20
    • 2017-12-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-27
    • 2012-01-20
    相关资源
    最近更新 更多