Android DocumentFile invalid URI
Asked Answered
L

2

7

i am trying to list files in external storage devices on my android 5.1 phone using DocumentFile

String rootPathURI = "file:/media/storage/sdcard1/data/example.externalstorage/files/";


File f = new File(URI(rootPathURI));
DocumentFile documentFile = DocumentFile.fromFile(f);

This code works fine but i want to do it like this;

String rootPathURI = "file:/media/storage/sdcard1/data/example.externalstorage/files/";

DocumentFile documentFile = DocumentFile.fromTreeUri(getApplicationContext(), Uri.parse(rootPathURI));

but i get an exception like this:

W/System.err( 5157): java.lang.IllegalArgumentException: Invalid     URI:"file:/media/storage/sdcard1/data/example.externalstorage/files/"
Lamere answered 26/7, 2016 at 13:14 Comment(0)
M
3

fromTreeUri() is for use with a Uri returned from an ACTION_OPEN_DOCUMENT_TREE request, as is noted in the documentation. It might work for a StorageVolumeUri`.

Matrilocal answered 26/7, 2016 at 13:28 Comment(1)
Can you give me an example of StoreVolume Uri ?Lamere
S
2

If you dont want to use ACTION_OPEN_DOCUMENT_TREE or ACTION_OPEN_DOCUMENT to get an Uri, you can convert FILE to Uri (SAF) using the following method valid from API19(Android4.4-Kitkat) to API28(Android8-Oreo). The returned Uri's are the same that return the dialog and its valid for API 28 security restrictions (SAF permissions), if you want to access external removable storage outside your application...

 /**
 * Ing.N.Nyerges 2019 V2.0
 *
 * Storage Access Framework(SAF) Uri's creator from File (java.IO),
 * for removable external storages
 *
 * @param context Application Context
 * @param file File path + file name
 * @return Uri[]:
 *   uri[0] = SAF TREE Uri
 *   uri[1] = SAF DOCUMENT Uri
 */
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
public static Uri[] getSafUris (Context context, File file) {

    Uri[] uri = new Uri[2];
    String scheme = "content";
    String authority = "com.android.externalstorage.documents";

    // Separate each element of the File path
    // File format: "/storage/XXXX-XXXX/sub-folder1/sub-folder2..../filename"
    // (XXXX-XXXX is external removable number
    String[] ele = file.getPath().split(File.separator);
    //  ele[0] = not used (empty)
    //  ele[1] = not used (storage name)
    //  ele[2] = storage number
    //  ele[3 to (n-1)] = folders
    //  ele[n] = file name

    // Construct folders strings using SAF format
    StringBuilder folders = new StringBuilder();
    if (ele.length > 4) {
        folders.append(ele[3]);
        for (int i = 4; i < ele.length - 1; ++i) folders.append("%2F").append(ele[i]);
    }

    String common = ele[2] + "%3A" + folders.toString();

    // Construct TREE Uri
    Uri.Builder builder = new Uri.Builder();
    builder.scheme(scheme);
    builder.authority(authority);
    builder.encodedPath("/tree/" + common);
    uri[0] = builder.build();

    // Construct DOCUMENT Uri
    builder = new Uri.Builder();
    builder.scheme(scheme);
    builder.authority(authority);
    if (ele.length > 4) common = common + "%2F";
    builder.encodedPath("/document/" + common + file.getName());
    uri[1] = builder.build();

    return uri;
}

You must use SAF permission to grant access to external removable storage usin something like this:

    context.grantUriPermission(context.getPackageName(), uri, Intent
            .FLAG_GRANT_READ_URI_PERMISSION | Intent
            .FLAG_GRANT_WRITE_URI_PERMISSION);
    context.getContentResolver().takePersistableUriPermission(uri, Intent
            .FLAG_GRANT_READ_URI_PERMISSION | Intent
            .FLAG_GRANT_WRITE_URI_PERMISSION);
Spirometer answered 15/7, 2019 at 22:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.