frankelot
frankelot

Reputation: 14419

Load file from external storage using chooser

So, I'm trying to load a simple .txt file like this:

    private void showFileChooser() {
    Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
    intent.setType("text/plain");
    intent.addCategory(Intent.CATEGORY_OPENABLE);

    try {
        startActivityForResult(
                Intent.createChooser(intent, "Select a File to Upload"),
                FILE_SELECT_CODE);
    } catch (android.content.ActivityNotFoundException ex) {
        Toast.makeText(this, "Please install a File Manager.",
                Toast.LENGTH_SHORT).show();
    }
}

And of course, catching the result like this:

 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    switch (requestCode) {
        case FILE_SELECT_CODE:
            if (resultCode == RESULT_OK) {

                // Get the Uri of the selected file
                Uri uri = data.getData();

It works great on genymotion and on my device if I use a file explorer that I have installed (File explorer, see image abovew), now, If use the chooser directly like this:

enter image description here

It says it cannot find the specified file. (FileNotFoundException)

Now, I've realized that the URIs I get from these two file choosers are different

content://com.android.externalstorage.documents/document/primary%3ADownload%2Ffile.txt <- THIS DOESNT WORK (android built in explorer)

content://media/external/file/44751 <- THIS WORKS (custom explorer)

Does anyone have any idea why I'm getting different URIs for the SAME file.

EDIT: I tried to use a content resolver to get the file path from the URI like this:

public class Utils {

public static String getRealPathFromURI(Context context, Uri contentUri) {
    Cursor cursor = null;
    try {
        String[] proj = {MediaStore.Files.FileColumns.DATA};
        cursor = context.getContentResolver().query(contentUri, proj, null, null, null);
        int column_index = cursor.getColumnIndexOrThrow(proj[0]);
        cursor.moveToFirst();
        return cursor.getString(column_index);
    } finally {
        if (cursor != null) {
            cursor.close();
        }
    }
}

}

Still no luck :(

Upvotes: 4

Views: 17880

Answers (2)

frankelot
frankelot

Reputation: 14419

@CommonsWare's asnwer must be the right way of solving this, but I'm not sure how to implement his solution. I've ended up doing what @Paul Burke recomends on this link:

Android Gallery on KitKat returns different Uri for Intent.ACTION_GET_CONTENT

EDIT

For my particular case, this is how my code ended up. I leave this here for future reference. (I'm using @CommonsWare's explanation) see his answer above.

               try {
                    InputStream inputStream = getContentResolver().openInputStream(uri);
                    BufferedReader br = null;
                    if (inputStream != null) {
                        br = new BufferedReader(new InputStreamReader(inputStream));

                        String line;
                        while ((line = br.readLine()) != null) {
                            text.append(line);
                            text.append("\n");
                        }
                    } else {
                        subscriber.onError(new InputException("There's something seriously wrong with this file"));
                    }

                } catch (IOException e) {
                    e.printStackTrace();
                    subscriber.onError(e);
                }

Upvotes: 2

CommonsWare
CommonsWare

Reputation: 1006944

I tried to use a content resolver to get the file path from the URI like this

There is no file path. A Uri does not necessarily point to a file that you can access on your local filesystem, just as the URL to this Web page does not necessarily point to a file that you can access on your local filesystem. The Uri might:

  • represent a file held in internal storage of the other app
  • represent a BLOB column value in a database
  • represent a file held in "the cloud", to be downloaded when requested
  • etc.

Use a ContentResolver and methods like openInputStream() to read in the content represented by the Uri, just like you would use HttpUrlConnection to read in the content represented by the URL for this Web page. openInputStream() takes the Uri as a parameter and returns an InputStream. You would use that InputStream the same way you would any other InputStream (e.g., FileInputStream, InputStream from HttpUrlConnection). The exact mechanics of that will depend a lot on the underlying data (e.g., read in a string, pass to BitmapFactory to decode a Bitmap).

Upvotes: 1

Related Questions