0

I can successfully obtain a basepath Uri from OPEN_DOCUMENT_TREE from the Storage Access Framework.

How to use the new SD card access API presented for Android 5.0 (Lollipop)?

private static final int READ_REQUEST_CODE = 42;

public void performFileSearch() {

    Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);

    startActivityForResult(intent, READ_REQUEST_CODE);
}


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

    // The ACTION_OPEN_DOCUMENT intent was sent with the request code
    // READ_REQUEST_CODE. If the request code seen here doesn't match, it's the
    // response to some other intent, and the code below shouldn't run at all.

    if (requestCode == READ_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
        // The document selected by the user won't be returned in the intent.
        // Instead, a URI to that document will be contained in the return intent
        // provided to this method as a parameter.
        // Pull that URI using resultData.getData().
        Uri uri = null;
        if (resultData != null) {
            uri = resultData.getData();

        }
    }
}

But there is a bug/feature in android 5.0 that breaks recursion as referenced in this post:

Bug when listing files with Android Storage Access framework on Lollipop

Uri treeUri = resultData.getData();
DocumentFile pickedDir = DocumentFile.fromTreeUri(this, treeUri);
Uri f1 = pickedDir.findFile("MyFolder").getUri();
Log.d(TAG, "f1 = " + f1.toString());

Using File.listFiles() returns a Null array.

I already know the full path to the target folders/files. I would like to construct a valid DocumentFile Uri which has the authority of the root Uri returned in onActivityResult.

I would like to append to the root Uri path or build a new Uri which has the same permissions as the root Uri to access the target folders/files.

Community
  • 1
  • 1
boosth
  • 1
  • 3

1 Answers1

0

You basically want to slice and dice the path segments of the uri. You also want to avoid ever calling findFile. It's performance negatively scales with folder size. Hundreds of files can mean multiple seconds and it keeps going up.

My solution was to wrap DocumentFile with a properly functioning getParent. I'm not quite done yet (ie: this code is not fully functional), but it may point you to how to manipulate the uris to your goals.

/**
 *  Uri-based DocumentFile do not support parent at all
 *  Try to garner the logical parent through the uri itself
 * @return
 */
protected UsefulDocumentFile getParentDocument()
{
    Uri uri = mDocument.getUri();
    String documentId = DocumentsContract.getDocumentId(uri);

    String[] parts = getPathSegments(documentId);

    if (parts == null)
        return null;

    Uri parentUri;
    if (parts.length == 1)
    {
        String parentId = DocumentsContract.getTreeDocumentId(uri);
        parentUri = DocumentsContract.buildTreeDocumentUri(uri.getAuthority(), parentId);
    }
    else
    {
        String[] parentParts = Arrays.copyOfRange(parts, 0, parts.length - 2);
        String parentId = TextUtils.join(URL_SLASH, parentParts);
        parentUri = DocumentsContract.buildTreeDocumentUri(uri.getAuthority(), parentId);
    }

    return UsefulDocumentFile.fromUri(mContext, parentUri);
}

Once again this isn't fully functional yet but it may point you in the right direction. I'll update when I've worked out all the kinks.

Anthony
  • 7,638
  • 3
  • 38
  • 71