I want to let the user of my app choose a file, then the app open this file. For opening the file, I need its uri. In the official documentation https://developer.android.com/training/basics/intents/result#launch I see this simple example :
ActivityResultLauncher<String> mGetContent = registerForActivityResult(new GetContent(),
new ActivityResultCallback<Uri>() {
@Override
public void onActivityResult(Uri uri) {
// Handle the returned Uri
}
});
Called with :
mGetContent.launch("image/*");
That allows to open the selected file. Exactly what I need.
But I'd like to define an initial directory, called EXTRA_INITIAL_URI, but this can be set with a putExtra like this :
intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI,uri);
The problem is that there is no intent in this kind of implementation. So my question is : is it possible to define a EXTRA_INITIAL_URI , if yes how ?
Thanks a lot.
GetContent
, and the ACTION_GET_CONTENT
that it is named after doesn't support EXTRA_INITIAL_URI
at all: the list of intents it does support include:
ACTION_OPEN_DOCUMENT
ACTION_CREATE_DOCUMENT
ACTION_OPEN_DOCUMENT_TREE
which is why it isn't a parameter on that particular Activity Result Contract.
You'll note that OpenDocumentTree
specifically states:
The input is an optional Uri of the initial starting location.
Which maps to setting the EXTRA_INITIAL_URI
for that Activity Result contract, so you can use that contract directly if you are trying to select a folder.
For the other two, CreateDocument
and OpenDocument
, both specifically state:
This can be extended to override
createIntent
if you wish to pass additional extras to the Intent created bysuper.createIntent()
.
Which means you'd extend that contract to set the initial Uri.
For example, if you wanted to pass in the initial Uri as a constructor parameter to the contract, you'd write the class as
public class OpenDocumentAtFolder extends ActivityResultContracts.OpenDocument {
private final Uri initialUri;
public CustomContract(@NonNull Uri initialUri) {
this.initialUri = initialUri;
}
@NonNull
@Override
public Intent createIntent(@NonNull Context context, @NonNull String[] input) {
return super.createIntent(context, input)
.putExtra(DocumentsContract.EXTRA_INITIAL_URI, initialUri);
}
}
Which you'd then use in place of GetContent
:
ActivityResultLauncher<String> mOpenDocumentAtFolder = registerForActivityResult(
new OpenDocumentAtFolder(yourDefaultUriHere),
new ActivityResultCallback<Uri>() {
@Override
public void onActivityResult(Uri uri) {
// Handle the returned Uri
}
});
The guide to creating custom contracts talks more about writing type safe contracts if, for example, you wanted to instead have to pass the Uri and a mime type to launch
, you could write your own custom contract that doesn't extend OpenDocument
at all, but instead just uses the same underlying Intent extras that you want.