如何打开 SAF(存储访问框架)到 select 存储?

How to open SAF (Storage Access Framework) to select storage?

如何打开 SAF(存储访问框架)到 select 存储,如图所示?

我试过了:

Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
intent.putExtra(DocumentsContract.EXTRA_PROMPT, "Select path to save");
startActivityForResult(intent, PICK_FOLDER);

但这只会打开 Recent,用户必须单击 ...Show Internal Storage,然后单击 select,例如 SDCardInternal Storage.那不是用户友好的。

有没有办法像图片那样打开视图? Intent DocumentsContract.EXTRA_INITIAL_URI 有额外的数据,但我可以添加什么值来显示如图所示的打开视图?

我可以通过以下方式直接打开primary storage

StorageManager sm = (StorageManager) getSystemService(Context.STORAGE_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { //From Android 10+
    startActivityForResult(sm.getPrimaryStorageVolume().createOpenDocumentTreeIntent(), PICK_FOLDER);
}

但我想打开如图所示的视图。

How to open SAF (Storage Access Framework) to select storage as in the picture?

我的猜测是 "Select path to save" 意味着 UI 来自 ACTION_CREATE_DOCUMENT。但是,如果您希望抽屉自动打开,则没有 Intent 操作可以做到这一点。

but this opens only Recent and user have to click to ... and Show Internal Storage and after that select for example SDCard or Internal Storage. That's not user friendly.

没有记录和支持的自动提供 "internal storage" 作为选项的方法。话虽这么说,there are hacks that you can try,请记住,不能保证它们可以跨设备、OS 版本等工作。并且 none 必须打开那个抽屉。

There is extra data to Intent DocumentsContract.EXTRA_INITIAL_URI, but what value can I add it to show open view as in the picture?

嗯,none? EXTRA_INITIAL_URI 会预先 select 某些文件(其中 Uri 是您之前通过 SAF 获得的文件),但它不一定会更改存储选项,也不一定会预先打开那个抽屉。

仅适用于 Android 问

你可以使用createOpenDocumentTreeIntent() //添加在API level 29

        String choice = "We choose (sdcard)";

        StorageManager sm = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);

            List<StorageVolume> volumes = sm.getStorageVolumes();

            if (  volumes.size() < 0 ) {
                Toast.makeText(context, "no volumes found", Toast.LENGTH_LONG).show();

                return;
            }

            int nr = -1;

            if (  volumes.size() > 0 && choice.contains("(primary)"))
                nr = 0;
            if (  volumes.size() > 1 && choice.contains("(sdcard)"))
                nr = 1;
            if (  volumes.size() > 2 && choice.contains("(usbdisk"))
                nr = 2;

            if (  nr < 0 ) {
                Toast.makeText(context, "sorry we can not help you", Toast.LENGTH_LONG).show();

                return;
            }

            Intent intent = volumes.get(nr).createOpenDocumentTreeIntent(); //Added in API level 29


            ((Activity) context).startActivityForResult(intent, SELECT_DIRECTORY_CODE);