EXTRA_INITIAL_URI isn't working

from the CommonsWare Community archives

At May 5, 2020, 4:46pm, Shahood asked:

Hi,
I’ve two fragments where user is provided the option to pick a storage location and in both fragments, I use the following method for this purpose:

private void launchFilePicker(boolean shouldDownload) {
    Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
    // Try to open the default/last location
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        // Get the persisted uri
        Uri uri = mListener.getDownloadDirUri();
        if (uri != null) {
            DocumentFile location = DocumentFile.fromTreeUri(mActivity, uri);
            if (location != null) {
                intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, location.getUri());
            }
        }
    }
    intent.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
 Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
    startActivityForResult(intent, Constants.REQ_DOWNLOAD_LOC);
}

The methods to persist Uri and request code are obviously different in both fragments.

Here is the code when user selects a Uri:

@Override
public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == Constants.REQ_DOWNLOAD_LOC) {
        if (resultCode == RESULT_OK && data != null && data.getData() != null) {
            Uri uri = data.getData();
                mListener.setDownloadDirUri(uri);
        }
    }
}

Here is when Uri is persisted:

@Override
public void setDownloadDirUri(Uri uri) {
    Uri oldUri = getDownloadDirUri();
    if (oldUri != null && uri.compareTo(oldUri) != 0) {
        getContentResolver().releasePersistableUriPermission(oldUri,
            Intent.FLAG_GRANT_READ_URI_PERMISSION |
                        Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
    }
    getContentResolver().takePersistableUriPermission(uri,
            Intent.FLAG_GRANT_READ_URI_PERMISSION |
                    Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
    getSharedPreferences(PreferenceKey.PREFS_FILES, MODE_PRIVATE).edit()
            .putString(PreferenceKey.KEY_DOWNLOAD_LOCATION, uri.toString()).apply();
}

What happens is that the file picker doesn’t show the respective persisted location as the initial location; it rather shows the location last selected in any of the two fragments. So, if I select a location in Fragment A and persist it in its distinct Key-Value pair, this same location will be opened as initial location in Fragment B without regard to which location was persisted for Fragment B earlier.
I’m testing it on a physical device with Android P.

Would really appreciate if you could suggest a solution for that.

Thanks!


At May 5, 2020, 5:55pm, mmurphy replied:

I do not believe that any of those flags are useful in this scenario.

I don’t know what the implementation of getDownloadDirUri() is, but if I understand your situation correctly, you have a bug there. Your EXTRA_INITIAL_URI value is derived from this, and by your description it appears to be returning the previous value (caching?).

BTW, rather than taking persistable permission for the individual documents, have you tried doing it just for the whole tree? I think you get access to the contents of that tree, without needing to persist the permissions for the individual documents.


At May 5, 2020, 7:01pm, Shahood replied:

That’s exactly what I’m doing: persisting the Uri of the whole tree.


At May 5, 2020, 7:15pm, mmurphy replied:

:man_facepalming:

Sorry, I wasn’t paying close attention there!


At May 6, 2020, 12:37am, Shahood replied:

Here it is:

public Uri getDownloadDirUri() {
    String uriString = getSharedPreferences(PreferenceKey.PREFS_FILES, Context.MODE_PRIVATE)
            .getString(PreferenceKey.KEY_DOWNLOAD_LOCATION, "");
    return Uri.parse(uriString);
}

At May 6, 2020, 12:08pm, mmurphy replied:

I misunderstood this earlier as well. SharedPreferences are per-app, not per-fragment. So, both fragments are sharing the SharedPreferences, and they both appear to use the same key, so they will share a common value. If you want each fragment to have its own value, each fragment needs its own key.


At May 6, 2020, 12:36pm, Shahood replied:

As per the documentation:

Location should specify a document URI or a tree URI with document ID.

Any idea about what document ID means in above statement?


At May 6, 2020, 12:54pm, mmurphy replied:

No, sorry. I do not know what it would mean for a tree Uri to have a document ID.


At May 6, 2020, 1:08pm, Shahood replied:

OK, thanks anyway. Oh and I’m using separate SharedPreferences keys for each fragment. Problem is somewhere else.


At May 7, 2020, 2:51pm, Jan replied:

Where are you doing the apply or commit after your edit on SharedPref?


At May 10, 2020, 8:27am, Shahood replied:

Please have a look at the code pasted in my question. It is already mentioned in there.


At May 10, 2020, 9:05pm, Jan replied:

Okay. I see it now. Maybe I didn’t scroll far enough to the right the first time. Hope you got your problem solved.