image gallery - android get real path by Uri.getPath()


Translate

I'm trying to get image from gallery.

Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, "Select picture"), resultCode );

After I returned from this activity I have a data, which contains Uri. It looks like:

content://media/external/images/1

How can I convert this path to real one (just like '/sdcard/image.png') ?

Thanks


All Answers
  • Translate

    Is it really necessary for you to get a physical path?
    For example, ImageView.setImageURI() and ContentResolver.openInputStream() allow you to access the contents of a file without knowing its real path.


  • Translate

    This is what I do:

    Uri selectedImageURI = data.getData();
    imageFile = new File(getRealPathFromURI(selectedImageURI));
    

    and:

    private String getRealPathFromURI(Uri contentURI) {
        String result;
        Cursor cursor = getContentResolver().query(contentURI, null, null, null, null);
        if (cursor == null) { // Source is Dropbox or other similar local file path
            result = contentURI.getPath();
        } else { 
            cursor.moveToFirst(); 
            int idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA); 
            result = cursor.getString(idx);
            cursor.close();
        }
        return result;
    }
    

    NOTE: managedQuery() method is deprecated, so I am not using it.

    Last edit: Improvement. We should close cursor!!


  • Translate

    @Rene Juuse - above in comments... Thanks for this link !

    . the code to get the real path is a bit different from one SDK to another so below we have three methods that deals with different SDKs.

    getRealPathFromURI_API19(): returns real path for API 19 (or above but not tested) getRealPathFromURI_API11to18(): returns real path for API 11 to API 18 getRealPathFromURI_below11(): returns real path for API below 11

    public class RealPathUtil {
    
    @SuppressLint("NewApi")
    public static String getRealPathFromURI_API19(Context context, Uri uri){
        String filePath = "";
        String wholeID = DocumentsContract.getDocumentId(uri);
    
         // Split at colon, use second item in the array
         String id = wholeID.split(":")[1];
    
         String[] column = { MediaStore.Images.Media.DATA };     
    
         // where id is equal to             
         String sel = MediaStore.Images.Media._ID + "=?";
    
         Cursor cursor = context.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 
                                   column, sel, new String[]{ id }, null);
    
         int columnIndex = cursor.getColumnIndex(column[0]);
    
         if (cursor.moveToFirst()) {
             filePath = cursor.getString(columnIndex);
         }   
         cursor.close();
         return filePath;
    }
    
    
    @SuppressLint("NewApi")
    public static String getRealPathFromURI_API11to18(Context context, Uri contentUri) {
          String[] proj = { MediaStore.Images.Media.DATA };
          String result = null;
    
          CursorLoader cursorLoader = new CursorLoader(
                  context, 
            contentUri, proj, null, null, null);        
          Cursor cursor = cursorLoader.loadInBackground();
    
          if(cursor != null){
           int column_index = 
             cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
           cursor.moveToFirst();
           result = cursor.getString(column_index);
          }
          return result;  
    }
    
    public static String getRealPathFromURI_BelowAPI11(Context context, Uri contentUri){
               String[] proj = { MediaStore.Images.Media.DATA };
               Cursor cursor = context.getContentResolver().query(contentUri, proj, null, null, null);
               int column_index
          = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
               cursor.moveToFirst();
               return cursor.getString(column_index);
    }
    

    font: http://hmkcode.com/android-display-selected-image-and-its-real-path/


    UPDATE 2016 March

    To fix all problems with path of images i try create a custom gallery as facebook and other apps. This is because you can use just local files ( real files, not virtual or temporary) , i solve all problems with this library.

    https://github.com/nohana/Laevatein (this library is to take photo from camera or choose from galery , if you choose from gallery he have a drawer with albums and just show local files)


  • Translate

    Note This is an improvement in @user3516549 answer and I have check it on Moto G3 with Android 6.0.1
    I have this issue so I have tried answer of @user3516549 but in some cases it was not working properly. I have found that in Android 6.0(or above) when we start gallery image pick intent then a screen will open that shows recent images when user select image from this list we will get uri as

    content://com.android.providers.media.documents/document/image%3A52530
    

    while if user select gallery from sliding drawer instead of recent then we will get uri as

    content://media/external/images/media/52530
    

    So I have handle it in getRealPathFromURI_API19()

    public static String getRealPathFromURI_API19(Context context, Uri uri) {
            String filePath = "";
            if (uri.getHost().contains("com.android.providers.media")) {
                // Image pick from recent 
                String wholeID = DocumentsContract.getDocumentId(uri);
    
                // Split at colon, use second item in the array
                String id = wholeID.split(":")[1];
    
                String[] column = {MediaStore.Images.Media.DATA};
    
                // where id is equal to
                String sel = MediaStore.Images.Media._ID + "=?";
    
                Cursor cursor = context.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                        column, sel, new String[]{id}, null);
    
                int columnIndex = cursor.getColumnIndex(column[0]);
    
                if (cursor.moveToFirst()) {
                    filePath = cursor.getString(columnIndex);
                }
                cursor.close();
                return filePath;
            } else {
                // image pick from gallery 
               return  getRealPathFromURI_BelowAPI11(context,uri)
            }
    
        }
    

    EDIT : if you are trying to get image path of file in external sdcard in higher version then check my question


  • Translate

    There is no real path.

    A Uri with a content scheme is an opaque handle to some content. If that Uri represents openable content, you can use ContentResolver and openInputStream() to get an InputStream on that content. Similarly, a Uri with an http or https scheme does not represent a local file, and you would need to use an HTTP client API to access it.

    Only a Uri with a file scheme identifies a file (barring cases where the file was moved or deleted after the Uri was created).

    What stupid people do is try to derive a filesystem path by attempting to decode the contents of the Uri, possibly coupled with casting spells to invoke $EVIL_DEITY. At best, this will be unreliable, for three reasons:

    1. The rules for decoding the Uri values can change over time, such as with Android version releases, as the structure of the Uri represents an implementation detail, not an interface

    2. Even if you get a filesystem path, you may not have rights to access the file

    3. Not all Uri values can be decoded via fixed algorithms, as many apps have their own providers, and those can point to everything from assets to BLOB columns to data that needs to be streamed from the Internet

    If you have some limited API that requires a file, use the InputStream from openInputStream() to make a copy of that content. Whether that is a transient copy (e.g., used for a file upload operation, then deleted) or a durable copy (e.g., for an "import" feature of your app) is up to you.


  • Translate

    EDIT: Use this Solution here: https://stackoverflow.com/a/20559175/2033223 Works perfect!

    First of, thank for your solution @luizfelipetx

    I changed your solution a little bit. This works for me:

    public static String getRealPathFromDocumentUri(Context context, Uri uri){
        String filePath = "";
    
        Pattern p = Pattern.compile("(\\d+)$");
        Matcher m = p.matcher(uri.toString());
        if (!m.find()) {
            Log.e(ImageConverter.class.getSimpleName(), "ID for requested image not found: " + uri.toString());
            return filePath;
        }
        String imgId = m.group();
    
        String[] column = { MediaStore.Images.Media.DATA };
        String sel = MediaStore.Images.Media._ID + "=?";
    
        Cursor cursor = context.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                column, sel, new String[]{ imgId }, null);
    
        int columnIndex = cursor.getColumnIndex(column[0]);
    
        if (cursor.moveToFirst()) {
            filePath = cursor.getString(columnIndex);
        }
        cursor.close();
    
        return filePath;
    }
    

    Note: So we got documents and image, depending, if the image comes from 'recents', 'gallery' or what ever. So I extract the image ID first before looking it up.


  • Translate

    Hii here is my complete code for taking image from camera or galeery

    //My variable declaration

    protected static final int CAMERA_REQUEST = 0;
        protected static final int GALLERY_REQUEST = 1;
        Bitmap bitmap;
        Uri uri;
        Intent picIntent = null;
    

    //Onclick

    if (v.getId()==R.id.image_id){
                startDilog();
            }
    

    //method body

    private void startDilog() {
        AlertDialog.Builder myAlertDilog = new AlertDialog.Builder(yourActivity.this);
        myAlertDilog.setTitle("Upload picture option..");
        myAlertDilog.setMessage("Where to upload picture????");
        myAlertDilog.setPositiveButton("Gallery", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                picIntent = new Intent(Intent.ACTION_GET_CONTENT,null);
                picIntent.setType("image/*");
                picIntent.putExtra("return_data",true);
                startActivityForResult(picIntent,GALLERY_REQUEST);
            }
        });
        myAlertDilog.setNegativeButton("Camera", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                picIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                startActivityForResult(picIntent,CAMERA_REQUEST);
            }
        });
        myAlertDilog.show();
    }
    

    //And rest of things

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode==GALLERY_REQUEST){
            if (resultCode==RESULT_OK){
                if (data!=null) {
                    uri = data.getData();
                    BitmapFactory.Options options = new BitmapFactory.Options();
                    options.inJustDecodeBounds = true;
                    try {
                        BitmapFactory.decodeStream(getContentResolver().openInputStream(uri), null, options);
                        options.inSampleSize = calculateInSampleSize(options, 100, 100);
                        options.inJustDecodeBounds = false;
                        Bitmap image = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri), null, options);
                        imageofpic.setImageBitmap(image);
                    } catch (FileNotFoundException e) {
                        e.printStackTrace();
                    }
                }else {
                    Toast.makeText(getApplicationContext(), "Cancelled",
                            Toast.LENGTH_SHORT).show();
                }
            }else if (resultCode == RESULT_CANCELED) {
                Toast.makeText(getApplicationContext(), "Cancelled",
                        Toast.LENGTH_SHORT).show();
            }
        }else if (requestCode == CAMERA_REQUEST) {
            if (resultCode == RESULT_OK) {
                if (data.hasExtra("data")) {
                    bitmap = (Bitmap) data.getExtras().get("data");
                    uri = getImageUri(YourActivity.this,bitmap);
                    File finalFile = new File(getRealPathFromUri(uri));
                    imageofpic.setImageBitmap(bitmap);
                } else if (data.getExtras() == null) {
    
                    Toast.makeText(getApplicationContext(),
                            "No extras to retrieve!", Toast.LENGTH_SHORT)
                            .show();
    
                    BitmapDrawable thumbnail = new BitmapDrawable(
                            getResources(), data.getData().getPath());
                    pet_pic.setImageDrawable(thumbnail);
    
                }
    
            } else if (resultCode == RESULT_CANCELED) {
                Toast.makeText(getApplicationContext(), "Cancelled",
                        Toast.LENGTH_SHORT).show();
            }
        }
    }
    
    private String getRealPathFromUri(Uri tempUri) {
        Cursor cursor = null;
        try {
            String[] proj = { MediaStore.Images.Media.DATA };
            cursor = this.getContentResolver().query(tempUri,  proj, null, null, null);
            int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
            cursor.moveToFirst();
            return cursor.getString(column_index);
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }
    }
    public static int calculateInSampleSize(
            BitmapFactory.Options options, int reqWidth, int reqHeight) {
        // Raw height and width of image
        final int height = options.outHeight;
        final int width = options.outWidth;
        int inSampleSize = 1;
    
        if (height > reqHeight || width > reqWidth) {
    
            final int halfHeight = height / 2;
            final int halfWidth = width / 2;
    
            // Calculate the largest inSampleSize value that is a power of 2 and keeps both
            // height and width larger than the requested height and width.
            while ((halfHeight / inSampleSize) > reqHeight
                    && (halfWidth / inSampleSize) > reqWidth) {
                inSampleSize *= 2;
            }
        }
        return inSampleSize;
    }
    
    private Uri getImageUri(YourActivity youractivity, Bitmap bitmap) {
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, byteArrayOutputStream);
        String path = MediaStore.Images.Media.insertImage(youractivity.getContentResolver(), bitmap, "Title", null);
        return Uri.parse(path);
    }
    

  • Translate

    This helped me to get uri from Gallery and convert to a file for Multipart upload

    File file = FileUtils.getFile(this, fileUri);
    

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