How To Get Real File Path From Android Uri

The previous article Android Pick Multiple Image From Gallery Example has told us how to browse an image gallery to select and show images use Intent.ACTION_GET_CONTENT intent. In that example, we save all user-selected images android file path URI in a list. Then we display those images one by one.

Besides image type files, the Intent.ACTION_GET_CONTENT intent can be used to pick up any android documents with any file type extension. What you need to do is just invoke the Intent.ACTION_GET_CONTENT object’s setType method and pass the file type extension string to it. For example, to select an android file of any document type, just pass “*/*” to the intent object’s setType method like below.

openAlbumIntent.setType("*/*");

or

openAlbumIntent.setType("image/*");

or 

openAlbumIntent.setType("video/*");

Please note, you must use the above setType method to set at least one file type extension, otherwise, it will throw below exception.

android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.GET_CONTENT } 

At some time, only save the image URI in the android app is not enough, because the image URI may be changed, or the image URI is not changed but its related image may be removed. In this case, we need to save the URI related images in the android app folder. Then we can use it later such as display it or upload it to a web server, this can improve the Android app performance.

To achieve the above goal, we need to get the image URI related file’s real android file path, then we can use this local android file path to read the image and save a copy of the image to our app folder.

Because from android SDK version 19, to make Android apps secure, android does not allow one Android app to access another app created files from the android storage system directly.
If your Android app wants to access other app created files, you should get the file from its ContentProvider with a content URI.

The ContentProvider URI is not a real android file path URI (  file:///storage/41B7-12F1/DCIM/Camera/IMG_20180211_095139.jpg), it is a content provider style URI ( content://media/external/images/media/1302716 ). So we should parse the content provider style URI to the real android file local path by query related content provider ( image provider, audio provider, video provider, and document provider ).

The below source code will show you how to get an android file real local storage path from it’s content provider URI.

/* 
This method can parse out the real local file path from a file URI. 
*/
private String getUriRealPath(Context ctx, Uri uri)
{
    String ret = "";

    if( isAboveKitKat() )
    {
        // Android sdk version number bigger than 19.
        ret = getUriRealPathAboveKitkat(ctx, uri);
    }else
    {
        // Android sdk version number smaller than 19.
        ret = getImageRealPath(getContentResolver(), uri, null);
    }

    return ret;
}

/*
This method will parse out the real local file path from the file content URI. 
The method is only applied to android sdk version number that is bigger than 19.
*/
private String getUriRealPathAboveKitkat(Context ctx, Uri uri)
{
    String ret = "";

    if(ctx != null && uri != null) {

        if(isContentUri(uri))
        {
            if(isGooglePhotoDoc(uri.getAuthority()))
            {
                ret = uri.getLastPathSegment();
            }else {
                ret = getImageRealPath(getContentResolver(), uri, null);
            }
        }else if(isFileUri(uri)) {
            ret = uri.getPath();
        }else if(isDocumentUri(ctx, uri)){

            // Get uri related document id.
            String documentId = DocumentsContract.getDocumentId(uri);

            // Get uri authority.
            String uriAuthority = uri.getAuthority();

            if(isMediaDoc(uriAuthority))
            {
                String idArr[] = documentId.split(":");
                if(idArr.length == 2)
                {
                    // First item is document type.
                    String docType = idArr[0];

                    // Second item is document real id.
                    String realDocId = idArr[1];

                    // Get content uri by document type.
                    Uri mediaContentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
                    if("image".equals(docType))
                    {
                        mediaContentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
                    }else if("video".equals(docType))
                    {
                        mediaContentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
                    }else if("audio".equals(docType))
                    {
                        mediaContentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
                    }

                    // Get where clause with real document id.
                    String whereClause = MediaStore.Images.Media._ID + " = " + realDocId;

                    ret = getImageRealPath(getContentResolver(), mediaContentUri, whereClause);
                }

            }else if(isDownloadDoc(uriAuthority))
            {
                // Build download uri.
                Uri downloadUri = Uri.parse("content://downloads/public_downloads");

                // Append download document id at uri end.
                Uri downloadUriAppendId = ContentUris.withAppendedId(downloadUri, Long.valueOf(documentId));

                ret = getImageRealPath(getContentResolver(), downloadUriAppendId, null);

            }else if(isExternalStoreDoc(uriAuthority))
            {
                String idArr[] = documentId.split(":");
                if(idArr.length == 2)
                {
                    String type = idArr[0];
                    String realDocId = idArr[1];

                    if("primary".equalsIgnoreCase(type))
                    {
                        ret = Environment.getExternalStorageDirectory() + "/" + realDocId;
                    }
                }
            }
        }
    }

    return ret;
}

/* Check whether current android os version is bigger than kitkat or not. */
private boolean isAboveKitKat()
{
    boolean ret = false;
    ret = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
    return ret;
}

/* Check whether this uri represent a document or not. */
private boolean isDocumentUri(Context ctx, Uri uri)
{
    boolean ret = false;
    if(ctx != null && uri != null) {
        ret = DocumentsContract.isDocumentUri(ctx, uri);
    }
    return ret;
}

/* Check whether this uri is a content uri or not.
*  content uri like content://media/external/images/media/1302716
*  */
private boolean isContentUri(Uri uri)
{
    boolean ret = false;
    if(uri != null) {
        String uriSchema = uri.getScheme();
        if("content".equalsIgnoreCase(uriSchema))
        {
            ret = true;
        }
    }
    return ret;
}

/* Check whether this uri is a file uri or not.
*  file uri like file:///storage/41B7-12F1/DCIM/Camera/IMG_20180211_095139.jpg
* */
private boolean isFileUri(Uri uri)
{
    boolean ret = false;
    if(uri != null) {
        String uriSchema = uri.getScheme();
        if("file".equalsIgnoreCase(uriSchema))
        {
            ret = true;
        }
    }
    return ret;
}


/* Check whether this document is provided by ExternalStorageProvider. Return true means the file is saved in external storage. */
private boolean isExternalStoreDoc(String uriAuthority)
{
    boolean ret = false;

    if("com.android.externalstorage.documents".equals(uriAuthority))
    {
        ret = true;
    }

    return ret;
}

/* Check whether this document is provided by DownloadsProvider. return true means this file is a downloaed file. */
private boolean isDownloadDoc(String uriAuthority)
{
    boolean ret = false;

    if("com.android.providers.downloads.documents".equals(uriAuthority))
    {
        ret = true;
    }

    return ret;
}

/* 
Check if MediaProvider provide this document, if true means this image is created in android media app.
*/
private boolean isMediaDoc(String uriAuthority)
{
    boolean ret = false;

    if("com.android.providers.media.documents".equals(uriAuthority))
    {
        ret = true;
    }

    return ret;
}

/* 
Check whether google photos provide this document, if true means this image is created in google photos app.
*/
private boolean isGooglePhotoDoc(String uriAuthority)
{
    boolean ret = false;

    if("com.google.android.apps.photos.content".equals(uriAuthority))
    {
        ret = true;
    }

    return ret;
}

/* Return uri represented document file real local path.*/
private String getImageRealPath(ContentResolver contentResolver, Uri uri, String whereClause)
{
    String ret = "";

    // Query the uri with condition.
    Cursor cursor = contentResolver.query(uri, null, whereClause, null, null);

    if(cursor!=null)
    {
        boolean moveToFirst = cursor.moveToFirst();
        if(moveToFirst)
        {

            // Get columns name by uri type.
            String columnName = MediaStore.Images.Media.DATA;

            if( uri==MediaStore.Images.Media.EXTERNAL_CONTENT_URI )
            {
                columnName = MediaStore.Images.Media.DATA;
            }else if( uri==MediaStore.Audio.Media.EXTERNAL_CONTENT_URI )
            {
                columnName = MediaStore.Audio.Media.DATA;
            }else if( uri==MediaStore.Video.Media.EXTERNAL_CONTENT_URI )
            {
                columnName = MediaStore.Video.Media.DATA;
            }

            // Get column index.
            int imageColumnIndex = cursor.getColumnIndex(columnName);

            // Get column value which is the uri related file local path.
            ret = cursor.getString(imageColumnIndex);
        }
    }

    return ret;
}
0 0 vote
Article Rating
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

11 Comments
Newest
Oldest Most Voted
Inline Feedbacks
View all comments
Abhay
Abhay

I was searching for this stuffs since two-three days. Thanks a lot. I almost gave up. Thanks a lot.

ChanLung
ChanLung

Thank you.
But in android emulator (include Android 9.0) …..
Uri downloadUri = Uri.parse(“content://downloads/public_downloads”);
In this part, the issue was happened.
I hope you help me as soon as possible.
Best wishes

Kirill Karmazin
Kirill Karmazin

You shouldn’t try to get file path from Uri. Or at least you should understand that not all Uris can provide you with a file path!
read this: https://stackoverflow.com/a/49619018/5502121

The code above will crash if your Uri won’t have a ‘_data’ column in the cursor if it’s media.

For example, In my case user draws a picture, and it is saved as a Bitmap in .png file. I create a Uri using FileProvider and this Uri IS a MEDIA but DOESN”T HAVE the ‘_data’ column.

And the last thing: this code is very inefficient – you shouldn’t query with ‘null’ as a projection (the list of columns).

And there is a lot of such cases.

UchePhilz
UchePhilz

Why do I feel that there is a shorter way to get this done??

David Chen
David Chen

Jerry. Your code is wonderful. This helped me a lot with my school project. But how did you learn all this if the info is not in the Android documentation?

Arko Chatterjee
Arko Chatterjee

Hey, Thank you for the code. It works for most apps but does not work for images shared from WhatsApp. I am trying to catch the images shared from WhatsApp to my app but the uri of the images does not give the real path. When i’m using your code it gives the error:

java.lang.IllegalStateException: Couldn’t read row 0, col -1 from CursorWindow. Make sure the Cursor is initialized correctly

Can you please suggest something to fix it.
Thank you

happyzhaosong
happyzhaosong
Admin

From the error message, it said the col number is -1 which is not correct, because the minimum col value should be 0.

I think you should set a breakpoint at where the error occurred, and debug into it to fix this error.

Marium
Marium

Hey I am facing the same problem when trying to open the file shared on whatsapp. Have you found any solution?

Ricardo
Ricardo

Super nice……. 1000/1000

Alex Boutakidis
Alex Boutakidis

You are my hero, such a mess on documenting this on google’s part

Rob
Rob

Very helpful, thanks!!!

11
0
Would love your thoughts, please comment.x
()
x