android ActivityResultContracts.OpenDocumentTree() Intent always opens the previous use last folder

244 Views Asked by At

I am working on a android app which I want the user to be able to export the user entered data without the need for third party apps or cloud storage. I think that the user should be able to export the data to a folder on the device that can later be used to import into the application or whatever else the user wants to do with it without having to dig into the app specific location. To do this I thought that the OpenDocumentTree would be the best way to do it. And other than the issue (below) it works just fine (using DocumentFile to create folders and files). I searched for a solution but could not find anything so...

in module gradle android { compileSdkVersion 33

defaultConfig {
    applicationId "com.inventory"
    minSdkVersion 24
    targetSdkVersion 33
    versionCode 1
    versionName "1.0"

    testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}

The issue:

When launching ActivityResultContracts.OpenDocumentTree(), the file picker never uses the "start at" Uri. It always opens the file picker starting in the folder of the last used launch. And the "Use This Folder" Button is not displayed and because the app creates a folder to use for app data export, the user has to navigate up before the "Use This Folder" Button is displayed. I think this might be confusing for some users. I have tried Uri.fromFile(requireContext().getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS)); and Uri.parse("content://com.android.providers.media.documents"); but these are either invalid or just ignored. I don't care if it starts in the Documents folder or some other folder as long the file picker starts at the requested Uri every time and displays the Use this Folder Button or informs the user that the folder is not usable and prompts to create a folder. I'm hoping that I am overlooking something simple as I am still learning my way around the android operating system.

I tried on a virtual device api 30 and samsung galaxy note 8 api 27 tried using Uri.fromFile(requireContext().getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS)); and Uri.parse("content://com.android.providers.media.documents");

Expecting the file picker to start in the DOCUMENTS folder (or some other folder) consistently.

Code snippet:

public class ExportInventoryFragment extends Fragment
{
    ContentResolver resolver;

    FragmentExportInventoryBinding binding;
    Uri exportFileUri;

    private DocumentFile selectedExportFolder;

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState)
    {
        super.onViewCreated(view, savedInstanceState);
        binding.exportInventoryStartButton.setEnabled(false);

        binding.exportInventorySearchButton.setOnClickListener(view1 -> {
            binding.exportInventorySelectedFolderText.setText("");
            binding.exportInventoryStartButton.setEnabled(false);
           selectInventoryExportFolder.launch(Uri.fromFile(requireContext().getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS)));
        });

        binding.exportInventoryStartButton.setOnClickListener(view1 -> {
            if (selectedExportFolder != null) {
                binding.exportInventoryStartButton.setEnabled(false);
                exportInventory();
            }
        });
    }


    private final ActivityResultLauncher<Uri> selectInventoryExportFolder = this.registerForActivityResult(
            new ActivityResultContracts.OpenDocumentTree(), result -> {
                try {
                    if (result != null) {
                        DocumentFile docFolder = DocumentFile.fromTreeUri(requireContext(), result);
                        if (docFolder == null) {
                            Snackbar.make(requireView(), "Nothing selected...", Snackbar.LENGTH_LONG).show();
                            return;
                        }
                        if (!docFolder.isDirectory()) {
                            Snackbar.make(requireView(), "Selected is Not a Folder", Snackbar.LENGTH_LONG).show();
                            return;
                        }
                        if (!docFolder.canWrite()) {
                            Snackbar.make(requireView(), "Unable to Write Selected Folder Files", Snackbar.LENGTH_LONG).show();
                            return;
                        }


                        binding.exportInventorySelectedFolderText.setText(
                                String.format("%s %s",
                                        getString(R.string.text_selected_folder),
                                        selectedExportFolder.getName()));

                        selectedExportFolder = docFolder;

                        // This button allows the user to continue
                        binding.exportInventoryStartButton.setEnabled(true);
                    } else {
                        Snackbar.make(requireView(), "Nothing selected...", Snackbar.LENGTH_LONG).show();
                    }
                } catch (Exception x) {
                    Log.e("SelectImageFolder Launcher", x.getMessage(), x);
                    Snackbar.make(requireView(), Objects.requireNonNull(x.getMessage()), Snackbar.LENGTH_LONG).show();
                }
            });
}
0

There are 0 best solutions below