3

In my Android app, I launch a document chooser so the user can import some documents into my app:

this.intentlauncherchoosedoc = this.registerForActivityResult(
    new ActivityResultContracts.OpenMultipleDocuments(), 
    new ActivityResultCallback<List<Uri>>() {
        @Override
        public void onActivityResult(List<Uri> urilist) {
            for (Uri uri : urilist) {
                String filename = uri.getLastPathSegment();
                createdoc(uri, filename);
            }
        }
    }   
);

Unfortunately, when the user choose a document, the uri that comes back looks like this:

content://com.google.android.apps.docs.storage/document/acc=1;doc=encoded=mgMyynWh7Lrq1qW1dradGc60EJWehheCQiS5mYY7a8CF80Ouzro=

Is there any way to get the original filename of the document that was chosen, so that I can save that filename and list it to my user when they are reviewing their imported docs?

Kenny Wyland
  • 20,844
  • 26
  • 117
  • 229
  • 1
    You can try `DocumentFile.fromSingleUri().getName()` to attempt to get a "display name" for the document. This may or may not be a filename, as the content selected by the user may or may not be a file. – CommonsWare May 07 '20 at 19:55
  • @CommonsWare I read the linked answers you provided when closing this question, and while I understand that it doesn't guarantee a filename being there, there -is- an answer on how to get the filename and I figured it out. I wanted to post it as an answer to my own question, but this got closed too quickly. Querying the metadata via the Content Resolver let's me get access to a filename, if there is one, and that is a reasonable answer... but it's not contained in your linked answers. – Kenny Wyland May 07 '20 at 20:12
  • Reading through the docs, I figured out how to get access to the filename by querying for the metadata associated with the uri: `Cursor cursor = getContentResolver().query(incominguri, null, null, null, null); String filename = null; if (cursor != null) { int nameindex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME); cursor.moveToFirst(); filename = cursor.getString(nameindex); cursor.close(); }` – Kenny Wyland May 07 '20 at 20:12
  • Note that this is not necessarily a filename, and you will need to guard against data sources that fail to implement `OpenableColumns` support. – CommonsWare May 07 '20 at 20:32

1 Answers1

0

For the benefit of others searching for this, here is sample Kotlin code to open a single file and retrieve its name and content. The use of GetContent() guarantees that the column DISPLAY_NAME will be included in the returned metadata.

    private val getFile = registerForActivityResult(ActivityResultContracts.GetContent()) { uri ->
        requireActivity().contentResolver.apply { 
            query(uri, null, null, null, null)?.use { cursor ->
                val nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
                cursor.moveToFirst()
                cursor.getString(nameIndex)
            }?.let { fileName ->
                openInputStream(uri)?.use { stream ->
                    presenter.addFile(fileName, stream)
                }
            }
        }
    }

And to link it to a button:

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        view.findViewById<Button>(R.id.chooseFile).setOnClickListener {
            getFile.launch("*/*")
        }
    }
Clyde
  • 7,389
  • 5
  • 31
  • 57