Android get Gallery image Uri path
Asked Answered
L

4

43

In an Activity, I can choose an image from the Gallery, and I need its Uri path (in the log, the Uri path for my test image is /content:/media/external/images/media/1).

I'm getting this error though:

08-04 02:14:21.912: DEBUG/PHOTOUPLOADER(576): java.io.FileNotFoundException: /content:/media/external/images/media/1 (No such file or directory)
08-04 02:14:32.124: WARN/System.err(576): java.io.FileNotFoundException: /content:/media/external/images/media/1 (No such file or directory)

Is this the correct format of a file path? Or should I make it to be something like sdcard\...\image.png?

Leathern answered 4/8, 2011 at 2:22 Comment(3)
to anyone who may also have this problem: you do need a absolute path of your file. I'll post the method above you can use to convert this uri to pathLeathern
Post it as an answer if you have a solution.Susurrate
I meant, post it as an answer. Since it answers the question so other people see it as answered.Susurrate
L
45
public String getPath(Uri uri) {
    String[] projection = { MediaStore.Images.Media.DATA };
    Cursor cursor = managedQuery(uri, projection, null, null, null);
    startManagingCursor(cursor);
    int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
    cursor.moveToFirst();
    return cursor.getString(column_index);
}
Leathern answered 11/10, 2011 at 13:14 Comment(9)
For anyone else who gets here, note that managedQuery is a method of an activity, so you may need to provide an activity.Interpreter
A second note is that the cursor should be closed cursor.close()Interpreter
from the docs: Warning: Do not call Cursor.close() on a cursor obtained using this method, because the activity will do that for you at the appropriate time.Meteoroid
I would like to mention that managedQuery is now deprecated. If somebody developes the app for Android API 4 and higher, add support library v4 and use this code: CursorLoader loader = new CursorLoader(context, uri, projection, null, null, null); Cursor cursor = loader.loadInBackground(); instead of Cursor cursor = managedQuery(uri, projection, null, null, null);Clos
cursorloader target api 11 (at least for me)Polycotyledon
crash when you pick an old picture from "Photos"Zillion
I get the absolute uri but when I check the file.length() it's 0. Someone has one idea why?Saint
not compatible with all sdks , try my answer ... its full .Lexicostatistics
MediaStore.Images.Media.DATA is also deprecated, this method will no longer workConchitaconchobar
C
47
val inputStream = context.contentResolver.openInputStream(uri)

is all you need.

Crust answered 22/8, 2017 at 3:51 Comment(9)
How on earth this answer hasn't got any up votes yet? This is EXACTLY ALL WHAT WE NEED. Thank you Sir!Gravelly
This is too easy. Does it only work for certain SDK versions or something?Honeybunch
@DavidKennedy ContentResolver#openInputStream() was added in API level 1 so don't think soCrust
great, but how do i get path from this InputStream?Lobation
@Lobation you don't, the idea is to abstract away file pathsCrust
Now I just need to get a file path from this. Might be able to convert InputStream to OutputStream and save the file to a different location (I need to copy it anyway). IMO this whole Uri business is ridiculous. Why return this useless abstract Uri thing from an Image Gallery Picker, rather than an actual path to the actual file, on the actual device? LIke real world stuff. Crazy I knowWeinberger
@Weinberger Android uses Uri instead of raw file paths because images picked from Android's media picker may not actually be stored on user's storage (think Dropbox or Google Photos for example). Just because you don't understand something fully doesn't make it ridiculous.Crust
@Crust Yeah that's a good point, but the hoops you have to jump through for this are pretty funny. So it's impossible for a Uri to provide an absolute path if it's not a remote file? I just wish it wasn't so unwieldy to deal with.Weinberger
I don't think it is. You get a URI whose content can be read using a couple lines of code, especially with Okio. Accessing raw paths was always dangerous because they can be cached longer than their files' lifetime. What happens if a file is deleted? If you really want file paths, copying them to your app storage is a safe solution.Crust
L
45
public String getPath(Uri uri) {
    String[] projection = { MediaStore.Images.Media.DATA };
    Cursor cursor = managedQuery(uri, projection, null, null, null);
    startManagingCursor(cursor);
    int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
    cursor.moveToFirst();
    return cursor.getString(column_index);
}
Leathern answered 11/10, 2011 at 13:14 Comment(9)
For anyone else who gets here, note that managedQuery is a method of an activity, so you may need to provide an activity.Interpreter
A second note is that the cursor should be closed cursor.close()Interpreter
from the docs: Warning: Do not call Cursor.close() on a cursor obtained using this method, because the activity will do that for you at the appropriate time.Meteoroid
I would like to mention that managedQuery is now deprecated. If somebody developes the app for Android API 4 and higher, add support library v4 and use this code: CursorLoader loader = new CursorLoader(context, uri, projection, null, null, null); Cursor cursor = loader.loadInBackground(); instead of Cursor cursor = managedQuery(uri, projection, null, null, null);Clos
cursorloader target api 11 (at least for me)Polycotyledon
crash when you pick an old picture from "Photos"Zillion
I get the absolute uri but when I check the file.length() it's 0. Someone has one idea why?Saint
not compatible with all sdks , try my answer ... its full .Lexicostatistics
MediaStore.Images.Media.DATA is also deprecated, this method will no longer workConchitaconchobar
L
8

this works for all SDK's Versions :

/**
 * Get a file path from a Uri. This will get the the path for Storage Access
 * Framework Documents, as well as the _data field for the MediaStore and
 * other file-based ContentProviders.
 *
 * @param context The context.
 * @param uri The Uri to query.
 * @author paulburke
 */
public static String getPath(final Context context, final Uri uri) {

    final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;

    // DocumentProvider
    if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
        // ExternalStorageProvider
        if (isExternalStorageDocument(uri)) {
            final String docId = DocumentsContract.getDocumentId(uri);
            final String[] split = docId.split(":");
            final String type = split[0];

            if ("primary".equalsIgnoreCase(type)) {
                return Environment.getExternalStorageDirectory() + "/" + split[1];
            }

            // TODO handle non-primary volumes
        }
        // DownloadsProvider
        else if (isDownloadsDocument(uri)) {

            final String id = DocumentsContract.getDocumentId(uri);
            final Uri contentUri = ContentUris.withAppendedId(
                    Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));

            return getDataColumn(context, contentUri, null, null);
        }
        // MediaProvider
        else if (isMediaDocument(uri)) {
            final String docId = DocumentsContract.getDocumentId(uri);
            final String[] split = docId.split(":");
            final String type = split[0];

            Uri contentUri = null;
            if ("image".equals(type)) {
                contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
            } else if ("video".equals(type)) {
                contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
            } else if ("audio".equals(type)) {
                contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
            }

            final String selection = "_id=?";
            final String[] selectionArgs = new String[] {
                    split[1]
            };

            return getDataColumn(context, contentUri, selection, selectionArgs);
        }
    }
    // MediaStore (and general)
    else if ("content".equalsIgnoreCase(uri.getScheme())) {

        // Return the remote address
        if (isGooglePhotosUri(uri))
            return uri.getLastPathSegment();

        return getDataColumn(context, uri, null, null);
    }
    // File
    else if ("file".equalsIgnoreCase(uri.getScheme())) {
        return uri.getPath();
    }

    return null;
}

/**
 * Get the value of the data column for this Uri. This is useful for
 * MediaStore Uris, and other file-based ContentProviders.
 *
 * @param context The context.
 * @param uri The Uri to query.
 * @param selection (Optional) Filter used in the query.
 * @param selectionArgs (Optional) Selection arguments used in the query.
 * @return The value of the _data column, which is typically a file path.
 */
public static String getDataColumn(Context context, Uri uri, String selection,
        String[] selectionArgs) {

    Cursor cursor = null;
    final String column = "_data";
    final String[] projection = {
            column
    };

    try {
        cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
                null);
        if (cursor != null && cursor.moveToFirst()) {
            final int index = cursor.getColumnIndexOrThrow(column);
            return cursor.getString(index);
        }
    } finally {
        if (cursor != null)
            cursor.close();
    }
    return null;
}


/**
 * @param uri The Uri to check.
 * @return Whether the Uri authority is ExternalStorageProvider.
 */
public static boolean isExternalStorageDocument(Uri uri) {
    return "com.android.externalstorage.documents".equals(uri.getAuthority());
}

/**
 * @param uri The Uri to check.
 * @return Whether the Uri authority is DownloadsProvider.
 */
public static boolean isDownloadsDocument(Uri uri) {
    return "com.android.providers.downloads.documents".equals(uri.getAuthority());
}

/**
 * @param uri The Uri to check.
 * @return Whether the Uri authority is MediaProvider.
 */
public static boolean isMediaDocument(Uri uri) {
    return "com.android.providers.media.documents".equals(uri.getAuthority());
}

/**
 * @param uri The Uri to check.
 * @return Whether the Uri authority is Google Photos.
 */
public static boolean isGooglePhotosUri(Uri uri) {
    return "com.google.android.apps.photos.content".equals(uri.getAuthority());
}

taken from here : https://github.com/iPaulPro/aFileChooser/blob/master/aFileChooser/src/com/ipaulpro/afilechooser/utils/FileUtils.java

Lexicostatistics answered 16/5, 2016 at 13:35 Comment(1)
This is failing on OreoImperfective
D
0

try {

                 // open a URL connection to the Servlet
               FileInputStream fileInputStream = new FileInputStream(sourceFile);
               URL url = new URL(upLoadServerUri);

               // Open a HTTP  connection to  the URL
               conn = (HttpURLConnection) url.openConnection();
               conn.setDoInput(true); // Allow Inputs
               conn.setDoOutput(true); // Allow Outputs
               conn.setUseCaches(false); // Don't use a Cached Copy
               conn.setRequestMethod("POST");
               conn.setRequestProperty("Connection", "Keep-Alive");
               conn.setRequestProperty("ENCTYPE", "multipart/form-data");
               conn.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
               conn.setRequestProperty("uploaded_file", fileName);

               dos = new DataOutputStream(conn.getOutputStream());

               dos.writeBytes(twoHyphens + boundary + lineEnd);
               dos.writeBytes("Content-Disposition: form-data; name=uploaded_file;filename="+ fileName + "" + lineEnd);

               dos.writeBytes(lineEnd);

               // create a buffer of  maximum size
               bytesAvailable = fileInputStream.available();

               bufferSize = Math.min(bytesAvailable, maxBufferSize);
               buffer = new byte[bufferSize];

               // read file and write it into form...
               bytesRead = fileInputStream.read(buffer, 0, bufferSize); 

               while (bytesRead > 0) {

                 dos.write(buffer, 0, bufferSize);
                 bytesAvailable = fileInputStream.available();
                 bufferSize = Math.min(bytesAvailable, maxBufferSize);
                 bytesRead = fileInputStream.read(buffer, 0, bufferSize); 

                }

               // send multipart form data necesssary after file data...
               dos.writeBytes(lineEnd);
               dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);

               // Responses from the server (code and message)
               serverResponseCode = conn.getResponseCode();
               String serverResponseMessage = conn.getResponseMessage();

               Log.i("uploadFile", "HTTP Response is : "
                       + serverResponseMessage + ": " + serverResponseCode);

               if(serverResponseCode == 200){

                   runOnUiThread(new Runnable() {
                        public void run() {

                            String msg = "File Upload Completed.\n\n See uploaded file here : \n\n"
                                          +" http://www.androidtrainer.netne.net.com/uploads/"
                                          +uploadFileName;

                            messageText.setText(msg);
                            Toast.makeText(UploadToServer.this, "File Upload Complete.",
                                         Toast.LENGTH_SHORT).show();
                        }
                    });               
               }   

               //close the streams //
               fileInputStream.close();
               dos.flush();
               dos.close();

          } catch (MalformedURLException ex) {

              dialog.dismiss(); 
              ex.printStackTrace();

              runOnUiThread(new Runnable() {
                  public void run() {
                      messageText.setText("MalformedURLException Exception : check script url.");
                      Toast.makeText(UploadToServer.this, "MalformedURLException",
                                                          Toast.LENGTH_SHORT).show();
                  }
              });

              Log.e("Upload file to server", "error: " + ex.getMessage(), ex); 
          } catch (Exception e) {

              dialog.dismiss(); 
              e.printStackTrace();

              runOnUiThread(new Runnable() {
                  public void run() {
                      messageText.setText("Got Exception : see logcat ");

if you have problem not solve till you can visit here for complete example

Deflect answered 21/2, 2014 at 12:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.