存储访问框架 - 对用户选择的文件夹授予永久权限失败

Storage Access Framework - Permanent permission grant fails on user-selected folder

我正在尝试在样本 Activity 中测试存储访问框架。 目标是获得对用户选择的文件夹 Uri 的永久 read/write 权限。

应用启动 SAF 文件选择器的方式如下:

Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
intent.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
startActivityForResult(intent, OPEN_DIRECTORY_REQUEST_CODE);

onActivityResult方法被调用:

@Override
protected void onActivityResult(int requestCode,int resultCode, Intent data) 
{
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == OPEN_DIRECTORY_REQUEST_CODE) 
    {
        if (resultCode == Activity.RESULT_OK) 
        {
            int takeFlags = data.getFlags()& (Intent.FLAG_GRANT_READ_URI_PERMISSION
                    | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
            ContentResolver resolver = this.getContentResolver();
            resolver.takePersistableUriPermission(data.getData(),takeFlags);
            updateDirectoryEntries(data.getData());


        } else 
          {
            // The user cancelled the request.
          }
    }
}

我得到这个 uri

"/tree/raw:/storage/emulated/0/Download/prova1"

并将其作为字符串。

下次应用程序运行时调用以下方法:

public void consumeUri(String uriPath)
{
    ContentResolver contentResolver;
    contentResolver = this.getContentResolver();
    Uri uri;
    Uri docUri;
    uri=Uri.parse(uriPath);
    docUri= DocumentsContract.buildDocumentUriUsingTree(uri,
            DocumentsContract.getTreeDocumentId(uri)); //error here
}

我得到这个堆栈跟踪:

java.lang.IllegalArgumentException: Invalid URI: /tree/raw:/storage/emulated/0/Download/prova1
    at android.provider.DocumentsContract.getTreeDocumentId(DocumentsContract.java:1023)
    at com.example.myapplication.MainActivity.consumeUri(MainActivity.java:123)
    at com.example.myapplication.MainActivity.onClick(MainActivity.java:54)
    at android.view.View.performClick(View.java:6330)
    at android.view.View$PerformClick.run(View.java:24967)
    at android.os.Handler.handleCallback(Handler.java:790)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:164)
    at android.app.ActivityThread.main(ActivityThread.java:6687)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:810)

我的代码有什么问题?

看来保存Uri路径的正确方法是

uri.toString();

Uri 路径将采用这种形式:

content://com.android.providers.downloads.documents/tree/raw%3A%2Fstorage%2Femulated%2F0%2FDownload%2Ftest_folder