1

In one of my android projects I'm facing the following issue on a Samsung Tablet with Android 5.0.2: From a Fragment, the user can start to choose a file:

private static final int REQUEST_CHOOSE_FILE = 1;
...
private void chooseFile() {
    Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
    intent.addCategory(Intent.CATEGORY_OPENABLE);
    intent.setType("*/*");

    this.startActivityForResult(intent, REQUEST_CHOOSE_FILE);
}

The activity result is handled via

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    if (requestCode == REQUEST_CHOOSE_FILE && resultCode == Activity.RESULT_OK && data != null) {
        Uri uri = data.getData();

        String path = Util.getPath(this.getBaseActivity().getApplicationContext(), uri);
        ...
    }
}

with Util.getPath(...) taken from Get real path from URI, Android KitKat new storage access framework

This works fine for nearly everything - but not for files taken from the "Audio" link in the left part of the filechooser. In this case I'm not able to determine the file extension with my helper function. Everything I get is the name of the file...

I'm a bit stuck, especially because the filechooser isn't showing the extension, too.

Does anyone know this issue and could give me a hint to work around it?

Community
  • 1
  • 1
justus
  • 584
  • 1
  • 7
  • 19

1 Answers1

1

This works fine for nearly everything

No, it does not. It works for a small subset of providers, and fewer with each passing month.

Does anyone know this issue

The issue is that you are relying upon intrinsically unreliable code.

could give me a hint to work around it?

If you want to use the content associated with a Uri, use a ContentResolver. In particular, if you want to know the MIME type of the content, use getType() on ContentResolver. From there, you can attempt to come up with a relevant file extension, such as through MimeTypeMap.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • Ok, thanks for your fast answer. I think I'm lacking some basic android knowledge... Is there any way to get the full path (or a File instance) from any kind of Uri? As far as I know, there were some Uri changes with Android 5, but I have to support also versions 4.3+. Are there libraries to manage my issue for these versions? – justus Nov 25 '15 at 18:16
  • @Julius: "Is there any way to get the full path (or a File instance) from any kind of Uri?" -- no. There is no requirement that a `Uri` point to a file at all, let alone one you can access on the filesystem. This is no different than the Web, where a URL does not necessarily point to a file on a filesystem anywhere, let alone on the machine running the Web browser. "Are there libraries to manage my issue for these versions?" -- I do not know what you consider your issue to be. – CommonsWare Nov 25 '15 at 18:21
  • Hmm, in my app, the user selects files and I need to store them in a tmp directory to archive them later on. How would I do this correctly? Copying the Uris target to my tmp folder? How would that be done? – justus Nov 26 '15 at 08:28
  • @Julius: Copying the `Uri` values themselves will not be useful, as you may not have access to the data in the future. Think of them as akin to URLs to a Web site, for which you have temporary authorization. If you need to save the content, use `ContentResolver` to `openInputStream()`, then use Java I/O to copy the content from that stream to some `FileOutputStream` of yours, pointing to where you want to make a copy of the content. – CommonsWare Nov 26 '15 at 12:38
  • Thank you @CommonWare for the detailed explanation. A mosaic is getting put together in my head... I'll try to refactor my code and store the `Uri` content in a temp directory. But not before weekend :-) You'll get my feedback afterwards. – justus Nov 27 '15 at 15:51
  • @CommonWare: I've had the time now to refactor my app, everything's working fine now with `ContentResolver`s! Thanks for your explanation! – justus Dec 16 '15 at 08:03