Storage Access Framework - failing to obtain docum

2020-02-02 03:28发布

My Android app wants to create a folder in Google Drive and get the uri from the Drive app on the device.

It sends an intent, you can see the code below:

private void createFolder(String folderName) {
    Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
    intent.addCategory(Intent.CATEGORY_OPENABLE);
    // Create a file with the requested MIME type.
    intent.setType("vnd.android.document/directory");
    intent.putExtra(Intent.EXTRA_TITLE, folderName);
    startActivityForResult(intent, WRITE_REQUEST_CODE);
}

then it gets the returned data, you can see the code below:

@Override
protected void  onActivityResult(int requestCode, int resultCode, Intent resultData)
{

    if (requestCode == WRITE_REQUEST_CODE && resultCode == Activity.RESULT_OK) {

        Uri uri = null;
       if (resultData != null) {
            uri = resultData.getData();
            Log.i("result", "Uri: " + uri.toString());
            DocumentFile pickedDir = DocumentFile.fromTreeUri(this, uri); //this line gives the error
                       }
    }

}

I used a mimetype found on the internet that seems to be a standard type. The same error is issued when using "application/vnd.google-apps.folder". The goal is to have a document tree but in logcat I get the following error:

java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=43, result=-1, data=Intent { dat=content://com.google.android.apps.docs.storage/document/acc=1;doc=encoded=LongStringWithRandomCharactersHere/j flg=0x43 }} to activity {com.example.myapplication/com.example.myapplication.MainActivity}: java.lang.IllegalArgumentException: Invalid URI: content://com.google.android.apps.docs.storage/document/acc%3D1%3Bdoc%3Dencoded%3DSameLongStringWithRandomCharactersHere%2Fj

and below

Caused by: java.lang.IllegalArgumentException: Invalid URI: content://com.google.android.apps.docs.storage/document/acc%3D1%3Bdoc%3Dencoded%3DAnotherLongStringWithDifferentRandomDataHere

Here's the complete stack trace:

2019-05-31 15:06:50.167 31184-31184/com.example.myapplication E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.myapplication, PID: 31184
java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=43, result=-1, data=Intent { dat=content://com.google.android.apps.docs.storage/document/acc=1;doc=encoded=randomcharacters flg=0x43 }} to activity {com.example.myapplication/com.example.myapplication.MainActivity}: java.lang.IllegalArgumentException: Invalid URI: content://com.google.android.apps.docs.storage/document/acc%3D1%3Bdoc%3Dencoded%3Drandomcharacters
    at android.app.ActivityThread.deliverResults(ActivityThread.java:4365)
    at android.app.ActivityThread.handleSendResult(ActivityThread.java:4409)
    at android.app.ActivityThread.-wrap19(Unknown Source:0)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1670)
    at android.os.Handler.dispatchMessage(Handler.java:106)
    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)
 Caused by: java.lang.IllegalArgumentException: Invalid URI: content://com.google.android.apps.docs.storage/document/acc%3D1%3Bdoc%3Dencoded%3Drandomcharacters
    at android.provider.DocumentsContract.getTreeDocumentId(DocumentsContract.java:1023)
    at android.support.v4.provider.DocumentFile.fromTreeUri(DocumentFile.java:138)
    at com.example.myapplication.MainActivity.onActivityResult(MainActivity.java:254)
    at android.app.Activity.dispatchActivityResult(Activity.java:7295)
    at android.app.ActivityThread.deliverResults(ActivityThread.java:4361)
    at android.app.ActivityThread.handleSendResult(ActivityThread.java:4409) 
    at android.app.ActivityThread.-wrap19(Unknown Source:0) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1670) 
    at android.os.Handler.dispatchMessage(Handler.java:106) 
    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) 

The uri is not wrong because I can further extract the name of the folder (and the size=0), that is successfully created on the Drive cloud. What's wrong instead? It seems that my app cannot handle it as a document tree.

1条回答
beautiful°
2楼-- · 2020-02-02 04:29

This is working with Google Drive cloud space but maybe it's a hack. It is not guaranteed to always work.

This example creates a cloud file in a cloud folder that was created by the user (the SAF picker is opened by the app).

Creating the cloud folder (the user has to select the cloud root first from the picker UI)

 Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
 intent.setType("vnd.android.document/directory");
 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, CREATE_DIRECTORY_REQUEST_CODE);

onActivityResult

@Override
protected void onActivityResult(int requestCode,int resultCode, Intent data) 
{
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == CREATE_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);
      archiveUri(data.getData().toString()); //important to save the toString() result, not getPath()
      archiveAuthority(data.getData().getAuthority());
      } 
      else 
      {
            // The user cancelled the request.
      }
    }
}

using the Uri next time

ContentResolver contentResolver;
contentResolver = this.getContentResolver();
uriPath=retrieveArchivedUri();
Uri tempUri;
Uri uri; 
String authority;
tempUri=Uri.parse(uriPath);
authority=retrieveArchivedAuthority();
uri= DocumentsContract.buildDocumentUri(authority,
            DocumentsContract.getDocumentId(tempUri)); //folder Uri

try 
{
 DocumentsContract.createDocument(contentResolver,uri,"plain/text","fileName");
} 
catch (FileNotFoundException e) 
{
        e.printStackTrace();
}
查看更多
登录 后发表回答