Get filename and path from URI from mediastore
Asked Answered
K

32

444

I have an onActivityResult returning from an mediastore image selection which I can get a URI for an image using the following:

Uri selectedImage = data.getData();

Converting this to a string gives this:

content://media/external/images/media/47

Or to a path gives:

/external/images/media/47

However I can't seem to find a way to convert this into an absolute path, as I want to load the image into a bitmap without having to copy it somewhere. I know this can be done using the URI and content resolver, but this seems to break on rebooting of the phone, I guess MediaStore doesn't keep its numbering the same between reboots.

Kaolinite answered 3/8, 2010 at 23:46 Comment(2)
gist.github.com/tatocaster/32aad15f6e0c50311626Circuit
API 19 and Above the solution is here, https://mcmap.net/q/18239/-get-filename-and-path-from-uri-from-mediastore . Hope guys this can help you.Genitive
R
643

Below API 19 use this code to get File Path from URI:

public String getRealPathFromURI(Context context, Uri contentUri) {
  Cursor cursor = null;
  try { 
    String[] proj = { MediaStore.Images.Media.DATA };
    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);
  } finally {
    if (cursor != null) {
      cursor.close();
    }
  }
}
Rochette answered 5/8, 2010 at 12:42 Comment(27)
Make sure to close the cursor before returning. :PSouffle
Just tried to use this and it works fine for items opened when downloaded from the browser, but when opening from an email attachment it returns null. How can I fix that?Ossified
it's not an universal solution, for example, it can not deal with URi format like: content://com.google.android.gallery3d.provider/picasa/item/5717464716603009922Littman
It's not working for me with Drive app. The URI: content://com.google.android.apps.docs.files/exposed_content/tHV4PoDlSl1OAu3qtER7rQ%3D%3D%0A%3BG1D2s6GYCEX7Niqtuj%2F7BWa71jRnlkCknibIU24b%2FO5BROqc0NMwnGsVaAIvxSTN%0AJohannisberger
as Christopher points out - this is not supported in 4.4+ See this question for more info: stackoverflow.com/questions/20067508/…Galton
How would I change the code to efficiently handle multiple uris instead of a single one? I know I could just call this function in a loop, but is there maybe a better way that will have a single query instead?Hurlow
Does not work. cursor is null. And I am not on Android 4.4+, I'm on 4.1.2.Cupreous
In this case, couldn't you just hardcode zero as your column index, since you're only returning one column in the result set?Predigestion
What must you pass through as the context?Striper
need to check if cursor != null before performing cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);, otherwise there is a possibility of a NullPointerExceptionGermanic
I'd recommend making this method static.Octan
Can anyone please tell me how I can use this method to get the path of a PDF file?Woodsia
I got always null value any help ? stackoverflow.com/questions/27103529/…Darfur
Tested on 5 devices. Gives null on all except for Android 4.1.2. On all newer Androids returns null.Quillan
See teepee solution below. It has a link to a much more complete solution that really saved me a ton of time.Prentiss
when I call this function what should I pass as context? @PercyPercyAretta
Sadly I'm realizing that there are so many glitches between android versions that in Google Head Quarter doesn't worry to repair. I said "Sadly" because this is a way to push developers to develop for newest android versions :/. Anyway, @PercyPercy your code works in Android 4.4.2, thanksTwila
What if we need audio path?Uncommonly
function above return null on Android Pixel emulator api 25, Galaxy j1 2016 (Android 5.1.1) . But it work on Google nexus S Android 4.1.2 (Jelly Bean) @@Thebaine
just tell me if uri is not for iimage let say its pdf uri that what ? everywhere same code only for imageHeaver
@Cupreous This is working for content scheme files only.Jamarjamb
@AshishSahu For other types of files Uri.getPath() should work.Jamarjamb
API 19 and above I solve this, Check the solution https://mcmap.net/q/18239/-get-filename-and-path-from-uri-from-mediastore.Genitive
Now that MediaStore.Images.Media.DATA is deprecated, how can we get the file path now?Tetanus
data constant is deprecated in Android Q(10)Innes
MediaStore.Images.Media.DATA is depricated now and MediaStore.Images.Media._ID with contentWrapperUri always return relative uri not absolute Uri. That is the main problem for getting valid Uri and this Uri not return a valid file path and occurred FileNotFoundExceptionJacquard
My Uri path returns: /document//storage/emulated/0/ in the starting of it. MediaStore cannot parse it.Adjourn
L
133

Just a simple update on the first answer: mActivity.managedQuery() is now deprecated. I've updated the code with the new method.

private String getRealPathFromURI(Uri contentUri) {
    String[] proj = { MediaStore.Images.Media.DATA };
    CursorLoader loader = new CursorLoader(mContext, contentUri, proj, null, null, null);
    Cursor cursor = loader.loadInBackground();
    int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
    cursor.moveToFirst();
    String result = cursor.getString(column_index);
    cursor.close();
    return result;
}

android dev source

Licentiate answered 12/5, 2012 at 14:47 Comment(12)
@dextor: This didn't work for me. It works when I click a file in a file browser, but when I click on an email attachment, I still get the content://... thing. I tried all the suggestions here without luck. Any idea why?Trophoblast
@Luis me too I get the same issueOssified
@dextor you need to close the cursor.Insurgency
Can you help in this : stackoverflow.com/questions/27103529/…Darfur
@dextor I tried this solution it did not work, probably something changed in the mean time. The solution of Paul Burke from this question stackoverflow.com/questions/20067508/… worked however.Ronna
This did not work for me, I got an exception saying that it was trying to access cursor after closed. Should the last two lines be flipped in order?Krug
Yes, it was flipped by some user. I fixed it.Licentiate
Is it works for other files rather images, like a text file, doc, pdf etc..?Salience
cursor is always null with this. API 19+Urga
It is insecure. Sometimes it return null and, if you are not careful, it can produce a NullPointerException.Blinders
Although your solution has worked in my physical device, it does not work in my emulator. Do you know why? My device has SDK 25 and my emulator has targetSdkVersion 28.Scientism
My Uri path returns: /document//storage/emulated/0/ in the starting of it. MediaStore cannot parse it.Adjourn
J
121

For Oreo

Uri uri = data.getData(); 
File file = new File(uri.getPath());//create path from uri
final String[] split = file.getPath().split(":");//split the path.
filePath = split[1];//assign it to a string(your choice).

For All version below Oreo I have made this method which get real path from uri

 @SuppressLint("NewApi")
    public static String getFilePath(Context context, Uri uri) throws URISyntaxException {
        String selection = null;
        String[] selectionArgs = null;
        // Uri is different in versions after KITKAT (Android 4.4), we need to
        if (Build.VERSION.SDK_INT >= 19 && DocumentsContract.isDocumentUri(context.getApplicationContext(), uri)) {
            if (isExternalStorageDocument(uri)) {
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                return Environment.getExternalStorageDirectory() + "/" + split[1];
            } else if (isDownloadsDocument(uri)) {
                final String id = DocumentsContract.getDocumentId(uri);
                uri = ContentUris.withAppendedId(
                        Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
            } else if (isMediaDocument(uri)) {
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                final String type = split[0];
                if ("image".equals(type)) {
                    uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
                } else if ("video".equals(type)) {
                    uri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
                } else if ("audio".equals(type)) {
                    uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
                }
                selection = "_id=?";
                selectionArgs = new String[]{
                        split[1]
                };
            }
        }
        if ("content".equalsIgnoreCase(uri.getScheme())) {


          if (isGooglePhotosUri(uri)) {
              return uri.getLastPathSegment();
           }

            String[] projection = {
                    MediaStore.Images.Media.DATA
            };
            Cursor cursor = null;
            try {
                cursor = context.getContentResolver()
                        .query(uri, projection, selection, selectionArgs, null);
                int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
                if (cursor.moveToFirst()) {
                    return cursor.getString(column_index);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else if ("file".equalsIgnoreCase(uri.getScheme())) {
            return uri.getPath();
        }
        return null;
    }

    public static boolean isExternalStorageDocument(Uri uri) {
        return "com.android.externalstorage.documents".equals(uri.getAuthority());
    }

    public static boolean isDownloadsDocument(Uri uri) {
        return "com.android.providers.downloads.documents".equals(uri.getAuthority());
    }

    public static boolean isMediaDocument(Uri uri) {
        return "com.android.providers.media.documents".equals(uri.getAuthority());
    }

  public static boolean isGooglePhotosUri(Uri uri) {
    return "com.google.android.apps.photos.content".equals(uri.getAuthority());
}
Jephthah answered 19/4, 2016 at 9:28 Comment(23)
thats the only version working seamlessly on every type of Uri - should be the top answer..Expound
This code is working if user has not selected file from SD card. If user has selected file from SD card than returned path is for example /storage/emulated/0/filePath even though file is located on /storage/sdCard/filePathDuffey
is there any solution for resolving this issue @ adi9090. i am stuck over this issue for nearly 2 days :(Boser
@Ali Nawaz Did u find any answer?Cosmotron
well you can try some library like material picker for android url: github.com/nbsp-team/MaterialFilePicker this can take u more closer to solution i am still on it if u get any solution kindly post it below..Boser
@AliNawaz I have referred svenoaks answer from the link: github.com/iPaulPro/aFileChooser/issues/58 When I use this code to select pdf file from sd card its not giving any error but the file is not uploading to server. My php code is correct because same code is working for internal storage.Cosmotron
Does not work either: java.lang.UnsupportedOperationException: Unsupported Uri content://com.android.externalstorage.documents/tree/primary%3ADCIM%2FCamera...why the android team made life so difficultEquestrienne
Works very well.. Though not on Samsung phones. Any idea why?Sylphid
This works very good but it doesn't work when you select file from SD Card. Is there any solutions for that?Phenformin
what does @SuppressLint("NewApi") mean? is it neccensary to add that?Phenformin
Yes. It's one kind of annotationJephthah
This doesn't work for downloaded pdf files in Android 9.0 (Pie).Starlet
This is not working in Android Oreo. Caused by: java.lang.IllegalArgumentException: Unknown URI: content://downloads/public_downloads/1658Mitochondrion
Now You can check for Oreo tooJephthah
does not wok for documentsFreesia
Worked in one app, returns null in another.Sybarite
@YadyneshDesai you need to check permissionJephthah
@Jitendraramoliya yes, figured that out later. Thanks anyway.Sybarite
@Jitendraramoliya I am recording a video and then trying to get the file path from the uri. I am able to play the video in Exoplayer but the above method returns null for this URI /storage/emulated/0/Android/data/com.example.playground.stage/files/1560516207297.mp4Sybarite
This answer is really incorrect. MediaStore returns me uri as follows: "/ external / images / media / 599" I don't think the above option could return the path to me.Diagraph
Cursor is returning nullSill
content://downloads/public_downloads/32 it throw java.lang.IllegalArgumentException: Unknown URI: content://downloads/public_downloads/32 for android 12Rowlandson
Works for me, tksDurno
G
112

Don't try to find a uri in the filesystem, that's slow to go look things up in the database.

You can get a bitmap from a uri by giving an input stream to the factory like you give a file to the factory:

InputStream is = getContentResolver().openInputStream(uri);
Bitmap bitmap = BitmapFactory.decodeStream(is);
is.close();
Gratuitous answered 1/9, 2011 at 1:20 Comment(10)
Actually this is the only correct response. Nobody really cares about the file name. What we need is the content. The actual file might be in the private folder of the app, in internet, sqlite or be purely virtual and generated on the fly.Cacuminal
The specific question asked is for the filename and path. Yes, the OP is looking to derive a bitmap from the file, but that isn't true of everyone looking for the path. Sometimes we need the actual file contents.Helminthic
getContentResolver() is a method of Context, per stackoverflow.com/questions/3750903/…, so use getActivity().getContentResolver() if you try to get the file content in a Fragment or nested Fragment.Bankston
@durilka, an example: if the file is a video and you want a thumbnail, the function "ThumbnailUtils.createVideoThumbnail" just can be called with a path of type String, does not accepts any tipe of inputStreams.Enter
I would first check if the content provider for videos provides thumbnails along with metadata. Android is all about "don't implement it yourself if somebody did this already". Really freaks me how every ambitious application tries to create own photo capturing.Cacuminal
@durilka, what if you want to use ExifInterface? It takes filename as parameter.Lecompte
@sver create a ticket asking google to start implementing their api consistently. every file can be a stream, not every stream is a file. even if they use filename to call some native library which takes the filename. in your case, i'd save the stream as a temp file, pass it to the Exif, remove (maybe) file. Extra hoop, but will definitely work in the future no matter if google will decide not to keep your pictures locally, but give you always urls instead.Cacuminal
You've just introduced a path which leads to OutOfMemory bugKannry
save my time and nervesPreglacial
I wonder why this is not the marked as the correct answer, since is more cleaner, simple and it actually solved the problem in question.Lydell
M
43

Here it is my example of getting file name, from URI like file://... and content://... . It's works for me not only with Android MediaStore but also with third part application like EzExplorer.

public static String getFileNameByUri(Context context, Uri uri)
{
    String fileName="unknown";//default fileName
    Uri filePathUri = uri;
    if (uri.getScheme().toString().compareTo("content")==0)
    {      
        Cursor cursor = context.getContentResolver().query(uri, null, null, null, null);
        if (cursor.moveToFirst())
        {
            int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);//Instead of "MediaStore.Images.Media.DATA" can be used "_data"
            filePathUri = Uri.parse(cursor.getString(column_index));
            fileName = filePathUri.getLastPathSegment().toString();
        }
    }
    else if (uri.getScheme().compareTo("file")==0)
    {
        fileName = filePathUri.getLastPathSegment().toString();
    }
    else
    {
        fileName = fileName+"_"+filePathUri.getLastPathSegment();
    }
    return fileName;
}
Mezzotint answered 21/3, 2012 at 0:58 Comment(10)
Can this convert between file:// and content:// URIs and vice versa? I tried including the code in my project, but it says ApplicationObject cannot be resolved.Roughen
It's problem with ApplicationObject, can you give me some code?Mezzotint
oh, its ok, dont worry, i found some other example code that worked, cheers.Roughen
This deserves to be the best answer, it is more comprehensive and solved a problem I had.Tattle
Why are you calling getLastPathSegment().toString() when getLastPathSegment() already returns a String?Stephine
What is ApplicationObject?Ossified
Class that extends developer.android.com/reference/android/app/Application.htmlMezzotint
best answer as it works on both stock gallery and external galleryCommorancy
I would just add one check for additional precaution in case an uri is content scheme but not coming from the Android gallery but from a app-defined content provider: if (MediaStore.AUTHORITY.equals(uri.getAuthority()))Lerma
column '_data' does not existSightless
C
18

Good existing answers, some of which I used to come up with my own:

I have to get the path from URIs and get the URI from paths, and Google has a hard time telling the difference so for anyone who has the same issue (e.g., to get the thumbnail from the MediaStore of a video whose physical location you already have). The former:

/**
 * Gets the corresponding path to a file from the given content:// URI
 * @param selectedVideoUri The content:// URI to find the file path from
 * @param contentResolver The content resolver to use to perform the query.
 * @return the file path as a string
 */
private String getFilePathFromContentUri(Uri selectedVideoUri,
        ContentResolver contentResolver) {
    String filePath;
    String[] filePathColumn = {MediaColumns.DATA};

    Cursor cursor = contentResolver.query(selectedVideoUri, filePathColumn, null, null, null);
    cursor.moveToFirst();

    int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
    filePath = cursor.getString(columnIndex);
    cursor.close();
    return filePath;
}

The latter (which I do for videos, but can also be used for Audio or Files or other types of stored content by substituting MediaStore.Audio (etc) for MediaStore.Video):

/**
 * Gets the MediaStore video ID of a given file on external storage
 * @param filePath The path (on external storage) of the file to resolve the ID of
 * @param contentResolver The content resolver to use to perform the query.
 * @return the video ID as a long
 */
private long getVideoIdFromFilePath(String filePath,
        ContentResolver contentResolver) {


    long videoId;
    Log.d(TAG,"Loading file " + filePath);

            // This returns us content://media/external/videos/media (or something like that)
            // I pass in "external" because that's the MediaStore's name for the external
            // storage on my device (the other possibility is "internal")
    Uri videosUri = MediaStore.Video.Media.getContentUri("external");

    Log.d(TAG,"videosUri = " + videosUri.toString());

    String[] projection = {MediaStore.Video.VideoColumns._ID};

    // TODO This will break if we have no matching item in the MediaStore.
    Cursor cursor = contentResolver.query(videosUri, projection, MediaStore.Video.VideoColumns.DATA + " LIKE ?", new String[] { filePath }, null);
    cursor.moveToFirst();

    int columnIndex = cursor.getColumnIndex(projection[0]);
    videoId = cursor.getLong(columnIndex);

    Log.d(TAG,"Video ID is " + videoId);
    cursor.close();
    return videoId;
}

Basically, the DATA column of MediaStore (or whichever sub-section of it you're querying) stores the file path, so you either use what you know to look up that DATA field, or use the field to look up whatever else you want.

I then further use the Scheme as above to figure out what to do with my data:

 private boolean  getSelectedVideo(Intent imageReturnedIntent, boolean fromData) {

    Uri selectedVideoUri;

    //Selected image returned from another activity
            // A parameter I pass myself to know whether or not I'm being "shared via" or
            // whether I'm working internally to my app (fromData = working internally)
    if(fromData){
        selectedVideoUri = imageReturnedIntent.getData();
    } else {
        //Selected image returned from SEND intent 
                    // which I register to receive in my manifest
                    // (so people can "share via" my app)
        selectedVideoUri = (Uri)getIntent().getExtras().get(Intent.EXTRA_STREAM);
    }

    Log.d(TAG,"SelectedVideoUri = " + selectedVideoUri);

    String filePath;

    String scheme = selectedVideoUri.getScheme(); 
    ContentResolver contentResolver = getContentResolver();
    long videoId;

    // If we are sent file://something or content://org.openintents.filemanager/mimetype/something...
    if(scheme.equals("file") || (scheme.equals("content") && selectedVideoUri.getEncodedAuthority().equals("org.openintents.filemanager"))){

        // Get the path
        filePath = selectedVideoUri.getPath();

        // Trim the path if necessary
        // openintents filemanager returns content://org.openintents.filemanager/mimetype//mnt/sdcard/xxxx.mp4
        if(filePath.startsWith("/mimetype/")){
            String trimmedFilePath = filePath.substring("/mimetype/".length());
            filePath = trimmedFilePath.substring(trimmedFilePath.indexOf("/"));
        }

        // Get the video ID from the path
        videoId = getVideoIdFromFilePath(filePath, contentResolver);

    } else if(scheme.equals("content")){

        // If we are given another content:// URI, look it up in the media provider
        videoId = Long.valueOf(selectedVideoUri.getLastPathSegment());
        filePath = getFilePathFromContentUri(selectedVideoUri, contentResolver);

    } else {
        Log.d(TAG,"Failed to load URI " + selectedVideoUri.toString());
        return false;
    }

     return true;
 }
Cambridgeshire answered 22/7, 2012 at 20:52 Comment(1)
By using your code of get the path from URIs, I can return the path to be used to save in CameraRoll later in React Native, thanksCastellatus
I
14

Things are complicated now especially after API level 29 Android Q.

  • You must requestLegacyStorage in the manifest.xml.

  • This is how you should get filename from the content Uri

          public static String getNameFromContentUri(Context context, Uri contentUri){  
                              Cursor returnCursor = context.getContentResolver().query(contentUri, null, null, null, null);
                              int nameColumnIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
                              returnCursor.moveToFirst();
                              String fileName = returnCursor.getString(nameColumnIndex);
                              return fileName;}
    
  • and this is how you get full path of the Content Uri for all android versions

JAVA

    public static String getFullPathFromContentUri(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 ("com.android.externalstorage.documents".equals(uri.getAuthority())) {
                    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];
                    }//non-primary e.g sd card
                     else {

                           if (Build.VERSION.SDK_INT > 20) {
                    //getExternalMediaDirs() added in API 21
                    File extenal[] = context.getExternalMediaDirs();
                   for (File f : extenal) {
                    filePath = f.getAbsolutePath();
                    if (filePath.contains(type)) {
                        int endIndex = filePath.indexOf("Android");
                        filePath = filePath.substring(0, endIndex) + split[1];
                    }
                }
             }else{
                    filePath = "/storage/" + type + "/" + split[1];
             }
            return filePath;
        }
                }
                // DownloadsProvider
                else if ("com.android.providers.downloads.documents".equals(uri.getAuthority())) {
    
                    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 ("com.android.providers.media.documents".equals(uri.getAuthority())) {
                    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]
                    };
    
                       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 column_index = cursor.getColumnIndexOrThrow(column);
                    return cursor.getString(column_index);
                }
            } finally {
                if (cursor != null)
                    cursor.close();
            }
            return null;
                }
            }
            // MediaStore (and general)
            else if ("content".equalsIgnoreCase(uri.getScheme())) {
                return getDataColumn(context, uri, null, null);
            }
            // File
            else if ("file".equalsIgnoreCase(uri.getScheme())) {
                return uri.getPath();
            }
    
            return null;
        }

    private 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 column_index = cursor.getColumnIndexOrThrow(column);
                    return cursor.getString(column_index);
                }
            } finally {
                if (cursor != null)
                    cursor.close();
            }
            return null;
        }

KOTLIN

companion object {
@JvmStatic
    @SuppressLint("NewApi")
    fun getPath(context: Context, uri: Uri): String? {
        val isKitKat: Boolean = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT

        // DocumentProvider
        if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
            // ExternalStorageProvider
            if (isExternalStorageDocument(uri)) {
                val docId = DocumentsContract.getDocumentId(uri)
                val split = docId.split(":").toTypedArray()
                val type = split[0]
                return if ("primary".equals(type, ignoreCase = true)) {
                    Environment.getExternalStorageDirectory().toString() + "/" + split[1]
                } else { // non-primary volumes e.g sd card
                    var filePath = "non"
                    //getExternalMediaDirs() added in API 21
                    val extenal = context.externalMediaDirs
                    for (f in extenal) {
                        filePath = f.absolutePath
                        if (filePath.contains(type)) {
                            val endIndex = filePath.indexOf("Android")
                            filePath = filePath.substring(0, endIndex) + split[1]
                        }
                    }
                    filePath
                }
            } else if (isDownloadsDocument(uri)) {
                val id = DocumentsContract.getDocumentId(uri)
                val contentUri = ContentUris.withAppendedId(
                        Uri.parse("content://downloads/public_downloads"), java.lang.Long.valueOf(id))
                return getDataColumn(context, contentUri, null, null)
            } else if (isMediaDocument(uri)) {
                val docId = DocumentsContract.getDocumentId(uri)
                val split = docId.split(":").toTypedArray()
                val type = split[0]
                var contentUri: Uri? = null
                if ("image" == type) {
                    contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
                } else if ("video" == type) {
                    contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI
                } else if ("audio" == type) {
                    contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
                }
                val selection = "_id=?"
                val selectionArgs = arrayOf(
                        split[1]
                )
                return getDataColumn(context, contentUri, selection, selectionArgs)
            }
        } else if ("content".equals(uri.scheme, ignoreCase = true)) {
            return getDataColumn(context, uri, null, null)
        } else if ("file".equals(uri.scheme, ignoreCase = true)) {
            return uri.path
        }
        return null
    }

    private fun getDataColumn(context: Context, uri: Uri?, selection: String?,
                              selectionArgs: Array<String>?): String? {
        var cursor: Cursor? = null
        val column = "_data"
        val projection = arrayOf(
                column
        )
        try {
            cursor = context.contentResolver.query(uri!!, projection, selection, selectionArgs,
                    null)
            if (cursor != null && cursor.moveToFirst()) {
                val column_index = cursor.getColumnIndexOrThrow(column)
                return cursor.getString(column_index)
            }
        } catch (e: java.lang.Exception) {
        } finally {
            cursor?.close()
        }
        return null
    }

    private fun isExternalStorageDocument(uri: Uri): Boolean {
        return "com.android.externalstorage.documents" == uri.authority
    }

    private fun isDownloadsDocument(uri: Uri): Boolean {
        return "com.android.providers.downloads.documents" == uri.authority
    }

    private fun isMediaDocument(uri: Uri): Boolean {
        return "com.android.providers.media.documents" == uri.authority
    }

}

}

Innes answered 3/6, 2020 at 18:39 Comment(3)
using "_data" is same as using "MediaStore.Images.Media.DATA", which is deprecated from api 29.Struble
That is deprecated because apps may not have permission to use it, for apps that have been granted the permissions can use it.Innes
I mean getDataColumn is using deprecated _data column, and you are calling getDataColumn for every api level.Struble
H
12

None of these answers worked for me in all cases. I had to go directly to Google's Documentation https://developer.android.com/guide/topics/providers/document-provider.html on this topic and found this useful method:

private Bitmap getBitmapFromUri(Uri uri) throws IOException {
    ParcelFileDescriptor parcelFileDescriptor =
    getContentResolver().openFileDescriptor(uri, "r");
    FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
    Bitmap image = BitmapFactory.decodeFileDescriptor(fileDescriptor);
    parcelFileDescriptor.close();
    return image;
}

You can use this bitmap to display it in an Image View.

Hauge answered 24/6, 2016 at 15:55 Comment(1)
But, if we want a path instead of a bitmap, then what?Cloven
G
10

API 19 and Above, Image File Path from Uri works perfectly. I also check this latest PIE API 28.

public String getImageFilePath(Uri uri) {
    String path = null, image_id = null;

    Cursor cursor = getContentResolver().query(uri, null, null, null, null);
    if (cursor != null) {
        cursor.moveToFirst();
        image_id = cursor.getString(0);
        image_id = image_id.substring(image_id.lastIndexOf(":") + 1);
        cursor.close();
    }

    cursor = getContentResolver().query(android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI, null, MediaStore.Images.Media._ID + " = ? ", new String[]{image_id}, null);
    if (cursor!=null) {
        cursor.moveToFirst();
        path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
        cursor.close();
    }
    return path;
}
Genitive answered 7/7, 2018 at 22:29 Comment(6)
Firstly, you have initialized cursor twice! Secondly, this code throws CursorIndexOutOfBoundsException: Index 0 requested, with a size of 0 at this line: path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));Torras
I am using Oreo stock android and it doesn't work on it for some reasonTorras
how to get pdf file File Path from URI can you help mePanoptic
@HarshilPansare, how did you get it working for Android Oreo? I am stuck at it for 2 days.Kashmir
This does not work if the selected item is not an imageAutochthonous
@Autochthonous : It doesn't work image either. The second query doesn't return anythingUnaccountedfor
L
9

Any way for past Android Q, when MediaStore.Images.Media.DATA won't be available anymore? This field is depreciated in Android Q:

This constant was deprecated in API level 29. Apps may not have filesystem permissions to directly access this path. Instead of trying to open this path directly, apps should use ContentResolver#openFileDescriptor(Uri, String) to gain access.

https://developer.android.com/reference/android/provider/MediaStore.MediaColumns.html#DATA

--- Edited

As far as I know for past Android Q the only way is to relay on RELATIVE_PATH

Relative path of this media item within the storage device where it is persisted. For example, an item stored at /storage/0000-0000/DCIM/Vacation/IMG1024.JPG would have a path of DCIM/Vacation/.

https://developer.android.com/reference/android/provider/MediaStore.MediaColumns.html#RELATIVE_PATH

Lowman answered 29/8, 2019 at 12:26 Comment(4)
do all files in android Q have relative path or do we need to add them , like if file is already present on device its relative path will be available?Gerdes
@Gerdes according to description in the link if you pass it as null, then system will set it up properly. If file is already present then Media scanner should add the field.Lowman
you need Android Q as target API and perhaps turn on Scoped storageLowman
Searching by relative path and display name: https://mcmap.net/q/18416/-android-studio-mediastore-audio-media-data-is-deprecated-any-alternativesBobbi
P
6

Try This

Still, if you are getting the problem to get the real path, you can try my answers. Above answers didn't help me.

Explanation:- This method gets the URI and then check the API level of your Android device after that according to API level it will generate the Real path. Code for generating real path method is different according to API levels.

  1. method to get the Real path from URI

    @SuppressLint("ObsoleteSdkInt")
    public String getPathFromURI(Uri uri){
        String realPath="";
    // SDK < API11
        if (Build.VERSION.SDK_INT < 11) {
            String[] proj = { MediaStore.Images.Media.DATA };
            @SuppressLint("Recycle") Cursor cursor = getContentResolver().query(uri, proj, null, null, null);
            int column_index = 0;
            String result="";
            if (cursor != null) {
                column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
                realPath=cursor.getString(column_index);
            }
        }
        // SDK >= 11 && SDK < 19
        else if (Build.VERSION.SDK_INT < 19){
            String[] proj = { MediaStore.Images.Media.DATA };
            CursorLoader cursorLoader = new CursorLoader(this, uri, proj, null, null, null);
            Cursor cursor = cursorLoader.loadInBackground();
            if(cursor != null){
                int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
                cursor.moveToFirst();
                realPath = cursor.getString(column_index);
            }
        }
        // SDK > 19 (Android 4.4)
        else{
            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 = getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, column, sel, new String[]{ id }, null);
            int columnIndex = 0;
            if (cursor != null) {
                columnIndex = cursor.getColumnIndex(column[0]);
                if (cursor.moveToFirst()) {
                    realPath = cursor.getString(columnIndex);
                }
                cursor.close();
            }
        }
        return realPath;
     }
    
  2. Use this method like this

    Log.e(TAG, "getRealPathFromURI: "+getPathFromURI(your_selected_uri) );
    

Output:-

04-06 12:39:46.993 6138-6138/com.app.qtm E/tag: getRealPathFromURI: /storage/emulated/0/Video/avengers_infinity_war_4k_8k-7680x4320.jpg

Peers answered 6/4, 2018 at 7:34 Comment(3)
My physical device with API level 25 returns FATAL EXCEPTION with the command String wholeID = DocumentsContract.getDocumentId(uri); I get : java.lang.RuntimeException: Failure delivering resultScientism
In my case this example return path nullChampionship
Bro ! you're a genius ! The above examples did not work for me either , so I gave the last try to your code and it works !!!!!Muslim
N
5

try this get image file path from Uri

public void getImageFilePath(Context context, Uri uri) {

    Cursor cursor = context.getContentResolver().query(uri, null, null, null, null);
    cursor.moveToFirst();
    String image_id = cursor.getString(0);
    image_id = image_id.substring(image_id.lastIndexOf(":") + 1);
    cursor.close();
    cursor = context.getContentResolver().query(android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI, null, MediaStore.Images.Media._ID + " = ? ", new String[]{image_id}, null);
    cursor.moveToFirst();
    String path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
    cursor.close();
    upLoadImageOrLogo(path);
}
Noctambulous answered 4/11, 2017 at 9:56 Comment(0)
S
4

Solution for those, who have problem after moving to KitKat:

"This will get the file path from the MediaProvider, DownloadsProvider, and ExternalStorageProvider, while falling back to the unofficial ContentProvider method" https://mcmap.net/q/18043/-get-real-path-from-uri-android-kitkat-new-storage-access-framework-duplicate

Saxony answered 29/11, 2014 at 22:53 Comment(1)
it seems the perfect answerHorticulture
F
3

After getting an image from the gallery, just pass the URI in the below method only for Android 4.4 (KitKat):

public String getPath(Uri contentUri) {// Will return "image:x*"

    String wholeID = DocumentsContract.getDocumentId(contentUri);

    // 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 = getContentResolver().query(
            MediaStore.Images.Media.EXTERNAL_CONTENT_URI, column, sel,
            new String[] { id }, null);

    String filePath = "";

    int columnIndex = cursor.getColumnIndex(column[0]);

    if (cursor.moveToFirst()) {
        filePath = cursor.getString(columnIndex);
    }

    cursor.close();
    return filePath;
}
Franctireur answered 28/5, 2014 at 19:57 Comment(1)
This is the only one worked for me. I wanted something from the gallery. Do you have a working method for below Kitkat? @sharma_kunaiSoulier
B
3

I've done like this:

    Uri queryUri = MediaStore.Files.getContentUri("external");
    String columnData = MediaStore.Files.FileColumns.DATA;
    String columnSize = MediaStore.Files.FileColumns.SIZE;

    String[] projectionData = {MediaStore.Files.FileColumns.DATA};


    String name = null;
    String size = null;

    Cursor cursor = getContentResolver().query(contentURI, null, null, null, null);
    if ((cursor != null)&&(cursor.getCount()>0)) {
        int nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
        int sizeIndex = cursor.getColumnIndex(OpenableColumns.SIZE);

        cursor.moveToFirst();

        name = cursor.getString(nameIndex);
        size = cursor.getString(sizeIndex);

        cursor.close();
    }

    if ((name!=null)&&(size!=null)){
        String selectionNS = columnData + " LIKE '%" + name + "' AND " +columnSize + "='" + size +"'";

        Cursor cursorLike = getContentResolver().query(queryUri, projectionData, selectionNS, null, null);

        if ((cursorLike != null)&&(cursorLike.getCount()>0)) {
            cursorLike.moveToFirst();
            int indexData = cursorLike.getColumnIndex(columnData);
            if (cursorLike.getString(indexData) != null) {
                result = cursorLike.getString(indexData);
            }
            cursorLike.close();
        }
    }

    return result;
Bertle answered 8/9, 2018 at 18:31 Comment(0)
A
3

Unfortunately none of the answer worked which are mentioned above. Finally I made this working.

This will convert your URI to Image.

Uri selectedImage = data.getData();
String[] filePathColumn = {MediaStore.Images.Media.DATA};

Cursor cursor = getContentResolver().query(
        selectedImage, filePathColumn, null, null, null);
cursor.moveToFirst();

int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
String filePath = cursor.getString(columnIndex);
cursor.close();

Below code I used to select image.

Intent intent = new Intent(Intent.ACTION_PICK,MediaStore.Images.Media.EXTERNAL_CONTENT_URI);

startActivityForResult(intent, SELECT_PICTURES);
Abstemious answered 13/3, 2021 at 9:17 Comment(1)
does this work on all android versionMotorize
T
2

Since managedQuery has been deprecated, you could try:

CursorLoader cursorLoader = new CursorLoader(context, uri, proj, null, null, null);
Cursor cursor = cursorLoader.loadInBackground();
Transmissible answered 30/1, 2013 at 13:47 Comment(0)
S
2

Here I am going to show you that how to create a BROWSE button, which when you will click, it will open up the SD card, you will select a File and as a result you will get the file name and file path of the selected one:

A button which you will hit

browse.setOnClickListener(new OnClickListener()
{
    public void onClick(View v)
    {
        Intent intent = new Intent();
        intent.setAction(Intent.ACTION_PICK);
        Uri startDir = Uri.fromFile(new File("/sdcard"));
        startActivityForResult(intent, PICK_REQUEST_CODE);
    }
});

The function which will get the Resulted File Name and File Path

protected void onActivityResult(int requestCode, int resultCode, Intent intent)
{
    if (requestCode == PICK_REQUEST_CODE)
    {
        if (resultCode == RESULT_OK)
        {
            Uri uri = intent.getData();

            if (uri.getScheme().toString().compareTo("content")==0)
            {
                Cursor cursor =getContentResolver().query(uri, null, null, null, null);
                if (cursor.moveToFirst())
                {
                    int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);//Instead of "MediaStore.Images.Media.DATA" can be used "_data"
                    Uri filePathUri = Uri.parse(cursor.getString(column_index));
                    String file_name = filePathUri.getLastPathSegment().toString();
                    String file_path=filePathUri.getPath();
                    Toast.makeText(this,"File Name & PATH are:"+file_name+"\n"+file_path, Toast.LENGTH_LONG).show();
                }
            }
        }
    }
}
Salado answered 21/3, 2013 at 10:44 Comment(1)
I followed the suggestions here, and didn't work. When I click in a K9 email client attachment, I get content://com.fsck.k9.attachmentprovider/34fc2cc9-aa46-45e9-9e3f-2f27f0457249/1‌​/VIEW. After applying the methods here, I still get the same string, not the correct path, that is /mnt/sdcard/Android/data/com.fsck.k9/files/34fc2cc9-aa46-45e9-9e3f-2f27f0457249‌​.db_att/1. Any clues?Trophoblast
M
2

Slightly modified version of @PercyPercy - it doesn't throw and just returns null if anything goes wrong:

public String getPathFromMediaUri(Context context, Uri uri) {
    String result = null;

    String[] projection = { MediaStore.Images.Media.DATA };
    Cursor cursor = context.getContentResolver().query(uri, projection, null, null, null);
    int col = cursor.getColumnIndex(MediaStore.Images.Media.DATA);
    if (col >= 0 && cursor.moveToFirst())
        result = cursor.getString(col);
    cursor.close();

    return result;
}
Muzhik answered 24/2, 2015 at 10:23 Comment(0)
D
2
  public String getPath(Uri uri) {
    Cursor cursor = getContentResolver().query(uri, null, null, null, null);
    cursor.moveToFirst();
    String document_id = cursor.getString(0);
    document_id = document_id.substring(document_id.lastIndexOf(":") + 1);
    cursor.close();

    cursor = getContentResolver().query(
            android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
            null, MediaStore.Images.Media._ID + " = ? ", new String[]{document_id}, null);
    cursor.moveToFirst();
    String path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
    cursor.close();

    return path;
}

Perfectly working method to convert File URI into String filePath

Dour answered 14/10, 2020 at 18:44 Comment(2)
It's not working while getting images from download folder in some phones including nexus & oppoFlan
@AliAzazAlam Please check logs deeply, there maybe some other issue. By the way it should work, I have tested it in emulator & physical device as well.Dour
E
1

This solution works for every case:

It is too hard in some cases get the path from the URL. Then why do you need the path? To copy the file in other place? You don't need the path.

public void SavePhotoUri (Uri imageuri, String Filename){

    File FilePath = context.getDir(Environment.DIRECTORY_PICTURES,Context.MODE_PRIVATE);
    try {
        Bitmap selectedImage = MediaStore.Images.Media.getBitmap(context.getContentResolver(), imageuri);
        String destinationImagePath = FilePath + "/" + Filename;
        FileOutputStream destination = new FileOutputStream(destinationImagePath);
        selectedImage.compress(Bitmap.CompressFormat.JPEG, 100, destination);
        destination.close();
    }
    catch (Exception e) {
        Log.e("error", e.toString());
    }
}
Enthusiast answered 13/4, 2015 at 5:14 Comment(1)
Yeah this is what I went with since I actually want to copy the image the user selected from the Image PIcker anyway, to my app's data folder (actually a subfolder under it that I create). However the MediaStore.Images.Media.getBitmap() call is deprecated in API level >= 29. For API levels 29 and greater, use instead: val bitmap = ImageDecoder.decodeBitmap(ImageDecoder.createSource(context.contentResolver, imageUri))Wiggle
H
1

Here you get the name of the file

String[] projection = {MediaStore.MediaColumns.DISPLAY_NAME};
                    Uri uri = data.getData();
                    String fileName = null;
                    ContentResolver cr = getActivity().getApplicationContext().getContentResolver();

                    Cursor metaCursor = cr.query(uri,
                            projection, null, null, null);
                    if (metaCursor != null) {
                        try {
                            if (metaCursor.moveToFirst()) {
                                fileName = metaCursor.getString(0);
                            }
                        } finally {
                            metaCursor.close();
                        }
                    }
Horsepower answered 1/12, 2015 at 13:3 Comment(1)
Probably not that helpful to the op since he was looking for the absolute path (not just the filename)... but it sure as hell helped ME in understanding the process.Kesterson
L
1

Simple and easy. You can do this from the URI just like below!

public void getContents(Uri uri)
{
    Cursor vidCursor = getActivity.getContentResolver().query(uri, null, null,
                                                              null, null);
    if (vidCursor.moveToFirst())
    {
        int column_index =
        vidCursor .getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
        Uri filePathUri = Uri.parse(vidCursor .getString(column_index));
        String video_name =  filePathUri.getLastPathSegment().toString();
        String file_path=filePathUri.getPath();
        Log.i("TAG", video_name + "\b" file_path);
    }
}
Logjam answered 9/6, 2016 at 8:49 Comment(0)
T
1

I do this with a one liner:

val bitmap = MediaStore.Images.Media.getBitmap(contentResolver, uri)

Which in the onActivityResult looks like:

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    if (resultCode == Activity.RESULT_OK && requestCode == REQUEST_CODE_IMAGE_PICKER ) {
        data?.data?.let { imgUri: Uri ->
            val bitmap = MediaStore.Images.Media.getBitmap(contentResolver, imgUri)
        }
    }
}
Topless answered 31/3, 2020 at 7:52 Comment(2)
For some reason, this approach doesn't work if I use Samsung gallery app to select an imageUnaccountedfor
Weird. I was developing on a Samsung Galaxy S10.Tajo
P
0

Perfectly working for me fixed code from this post:

  public static String getRealPathImageFromUri(Uri uri) {
        String fileName =null;
        if (uri.getScheme().equals("content")) {
            try (Cursor cursor = MyApplication.getInstance().getContentResolver().query(uri, null, null, null, null)) {
                if (cursor.moveToFirst()) {
                    fileName = cursor.getString(cursor.getColumnIndexOrThrow(ediaStore.Images.Media.DATA));
                }
            } catch (IllegalArgumentException e) {
                Log.e(mTag, "Get path failed", e);
            }
        }
        return fileName;
    }
Preglacial answered 28/12, 2017 at 11:26 Comment(0)
N
0

As an add-on, if you need to see if a file exists before you try to open an input stream, you can use the DocumentsContract.

(Kotlin code)

var iStream = null
if(DocumentsContract.isDocumentUri(context,myUri)) {
   val pfd: ParcelFileDescriptor? = context.contentResolver.openFileDescriptor(
            myUri, "r") ?: return null
   iStream = ParcelFileDescriptor.AutoCloseInputStream(pfd)
}
Newel answered 7/6, 2018 at 16:46 Comment(0)
T
0

Since the above answers didn't work for me, here is the solution that worked for me:

For both >19 and <=19 API Levels.

This method covers all the cases to get filePath from uri

/**
 * 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 activity.
 * @param uri The Uri to query.
 * @author paulburke
 */
public static String getPath(final Context context, final Uri uri) {

    // DocumentProvider
    if ( Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && 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];
            }else{
                Toast.makeText(context, "Could not get file path. Please try again", Toast.LENGTH_SHORT).show();
            }
        }
        // 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;
            } else {
                contentUri = MediaStore.Files.getContentUri("external");
            }

            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 getDataColumn(context, uri, null, null);
    }
    // File
    else if ("file".equalsIgnoreCase(uri.getScheme())) {
        return uri.getPath();
    }

    return null;
}
Torras answered 16/7, 2018 at 9:17 Comment(1)
For my case, it goes into isDownloadsDocument(uri) check. But URI is msf:12, thus unable to fetch path. Anyone help?Thiamine
K
0

To get any sort of file path use this :

/*
 * Copyright (C) 2007-2008 OpenIntents.org
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.yourpackage;

import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.database.DatabaseUtils;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.provider.DocumentsContract;
import android.provider.MediaStore;
import android.util.Log;
import android.webkit.MimeTypeMap;

import java.io.File;
import java.io.FileFilter;
import java.text.DecimalFormat;
import java.util.Comparator;
import java.util.List;

/**
 * @author Peli
 * @author paulburke (ipaulpro)
 * @version 2013-12-11
 */
public class FileUtils {
    private FileUtils() {
    } //private constructor to enforce Singleton pattern

    /**
     * TAG for log messages.
     */
    static final String TAG = "FileUtils";
    private static final boolean DEBUG = true; // Set to true to enable logging

    public static final String MIME_TYPE_AUDIO = "audio/*";
    public static final String MIME_TYPE_TEXT = "text/*";
    public static final String MIME_TYPE_IMAGE = "image/*";
    public static final String MIME_TYPE_VIDEO = "video/*";
    public static final String MIME_TYPE_APP = "application/*";

    public static final String HIDDEN_PREFIX = ".";

    /**
     * Gets the extension of a file name, like ".png" or ".jpg".
     *
     * @param uri
     * @return Extension including the dot("."); "" if there is no extension;
     * null if uri was null.
     */
    public static String getExtension(String uri) {
        if (uri == null) {
            return null;
        }

        int dot = uri.lastIndexOf(".");
        if (dot >= 0) {
            return uri.substring(dot);
        } else {
            // No extension.
            return "";
        }
    }

    /**
     * @return Whether the URI is a local one.
     */
    public static boolean isLocal(String url) {
        if (url != null && !url.startsWith("http://") && !url.startsWith("https://")) {
            return true;
        }
        return false;
    }

    /**
     * @return True if Uri is a MediaStore Uri.
     * @author paulburke
     */
    public static boolean isMediaUri(Uri uri) {
        return "media".equalsIgnoreCase(uri.getAuthority());
    }

    /**
     * Convert File into Uri.
     *
     * @param file
     * @return uri
     */
    public static Uri getUri(File file) {
        if (file != null) {
            return Uri.fromFile(file);
        }
        return null;
    }

    /**
     * Returns the path only (without file name).
     *
     * @param file
     * @return
     */
    public static File getPathWithoutFilename(File file) {
        if (file != null) {
            if (file.isDirectory()) {
                // no file to be split off. Return everything
                return file;
            } else {
                String filename = file.getName();
                String filepath = file.getAbsolutePath();

                // Construct path without file name.
                String pathwithoutname = filepath.substring(0,
                        filepath.length() - filename.length());
                if (pathwithoutname.endsWith("/")) {
                    pathwithoutname = pathwithoutname.substring(0, pathwithoutname.length() - 1);
                }
                return new File(pathwithoutname);
            }
        }
        return null;
    }

    /**
     * @return The MIME type for the given file.
     */
    public static String getMimeType(File file) {

        String extension = getExtension(file.getName());

        if (extension.length() > 0)
            return MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension.substring(1));

        return "application/octet-stream";
    }

    /**
     * @return The MIME type for the give Uri.
     */
    public static String getMimeType(Context context, Uri uri) {
        File file = new File(getPath(context, uri));
        return getMimeType(file);
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is {@link LocalStorageProvider}.
     * @author paulburke
     */
    public static boolean isLocalStorageDocument(Uri uri) {
        return LocalStorageProvider.AUTHORITY.equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is ExternalStorageProvider.
     * @author paulburke
     */
    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.
     * @author paulburke
     */
    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.
     * @author paulburke
     */
    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());
    }

    /**
     * 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.
     * @author paulburke
     */
    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()) {
                if (DEBUG)
                    DatabaseUtils.dumpCursor(cursor);

                final int column_index = cursor.getColumnIndexOrThrow(column);
                return cursor.getString(column_index);
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if (cursor != null)
                cursor.close();
        }
        return null;
    }

    /**
     * Get a file path from a Uri. This will quickGet the the path for Storage Access
     * Framework Documents, as well as the _data field for the MediaStore and
     * other file-based ContentProviders.<br>
     * <br>
     * Callers should check whether the path is local before assuming it
     * represents a local file.
     *
     * @param context The context.
     * @param uri     The Uri to query.
     * @author paulburke
     * @see #isLocal(String)
     * @see #getFile(Context, Uri)
     */
    public static String getPath(final Context context, final Uri uri) {

        if (DEBUG)
            Log.d(TAG + " File -",
                    "Authority: " + uri.getAuthority() +
                            ", Fragment: " + uri.getFragment() +
                            ", Port: " + uri.getPort() +
                            ", Query: " + uri.getQuery() +
                            ", Scheme: " + uri.getScheme() +
                            ", Host: " + uri.getHost() +
                            ", Segments: " + uri.getPathSegments().toString()
            );
        // DocumentProvider
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && DocumentsContract.isDocumentUri(context, uri)) {
            // LocalStorageProvider
            if (isLocalStorageDocument(uri)) {
                // The path is the id
                return DocumentsContract.getDocumentId(uri);
            }
            // ExternalStorageProvider
            else 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];
//                }
                return Environment.getExternalStorageDirectory() + "/" + split[1];

                // TODO handle non-primary volumes
            }
            // DownloadsProvider
            else if (isDownloadsDocument(uri)) {
                try {
                    final String id = DocumentsContract.getDocumentId(uri);
                    Log.d(TAG, "getPath: id= " + id);
                    final Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
                    return getDataColumn(context, contentUri, null, null);
                }catch (Exception e){
                    e.printStackTrace();
                    List<String> segments = uri.getPathSegments();
                    if(segments.size() > 1) {
                        String rawPath = segments.get(1);
                        if(!rawPath.startsWith("/")){
                            return rawPath.substring(rawPath.indexOf("/"));
                        }else {
                            return rawPath;
                        }
                    }
                }
            }
            // 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;
    }

    /**
     * Convert Uri into File, if possible.
     *
     * @return file A local file that the Uri was pointing to, or null if the
     * Uri is unsupported or pointed to a remote resource.
     * @author paulburke
     * @see #getPath(Context, Uri)
     */
    public static File getFile(Context context, Uri uri) {
        if (uri != null) {
            String path = getPath(context, uri);
            if (path != null && isLocal(path)) {
                return new File(path);
            }
        }
        return null;
    }

    /**
     * Get the file size in a human-readable string.
     *
     * @param size
     * @return
     * @author paulburke
     */
    public static String getReadableFileSize(int size) {
        final int BYTES_IN_KILOBYTES = 1024;
        final DecimalFormat dec = new DecimalFormat("###.#");
        final String KILOBYTES = " KB";
        final String MEGABYTES = " MB";
        final String GIGABYTES = " GB";
        float fileSize = 0;
        String suffix = KILOBYTES;

        if (size > BYTES_IN_KILOBYTES) {
            fileSize = size / BYTES_IN_KILOBYTES;
            if (fileSize > BYTES_IN_KILOBYTES) {
                fileSize = fileSize / BYTES_IN_KILOBYTES;
                if (fileSize > BYTES_IN_KILOBYTES) {
                    fileSize = fileSize / BYTES_IN_KILOBYTES;
                    suffix = GIGABYTES;
                } else {
                    suffix = MEGABYTES;
                }
            }
        }
        return String.valueOf(dec.format(fileSize) + suffix);
    }

    /**
     * Attempt to retrieve the thumbnail of given File from the MediaStore. This
     * should not be called on the UI thread.
     *
     * @param context
     * @param file
     * @return
     * @author paulburke
     */
    public static Bitmap getThumbnail(Context context, File file) {
        return getThumbnail(context, getUri(file), getMimeType(file));
    }

    /**
     * Attempt to retrieve the thumbnail of given Uri from the MediaStore. This
     * should not be called on the UI thread.
     *
     * @param context
     * @param uri
     * @return
     * @author paulburke
     */
    public static Bitmap getThumbnail(Context context, Uri uri) {
        return getThumbnail(context, uri, getMimeType(context, uri));
    }

    /**
     * Attempt to retrieve the thumbnail of given Uri from the MediaStore. This
     * should not be called on the UI thread.
     *
     * @param context
     * @param uri
     * @param mimeType
     * @return
     * @author paulburke
     */
    public static Bitmap getThumbnail(Context context, Uri uri, String mimeType) {
        if (DEBUG)
            Log.d(TAG, "Attempting to quickGet thumbnail");

        if (!isMediaUri(uri)) {
            Log.e(TAG, "You can only retrieve thumbnails for images and videos.");
            return null;
        }

        Bitmap bm = null;
        if (uri != null) {
            final ContentResolver resolver = context.getContentResolver();
            Cursor cursor = null;
            try {
                cursor = resolver.query(uri, null, null, null, null);
                if (cursor.moveToFirst()) {
                    final int id = cursor.getInt(0);
                    if (DEBUG)
                        Log.d(TAG, "Got thumb ID: " + id);

                    if (mimeType.contains("video")) {
                        bm = MediaStore.Video.Thumbnails.getThumbnail(
                                resolver,
                                id,
                                MediaStore.Video.Thumbnails.MINI_KIND,
                                null);
                    } else if (mimeType.contains(FileUtils.MIME_TYPE_IMAGE)) {
                        bm = MediaStore.Images.Thumbnails.getThumbnail(
                                resolver,
                                id,
                                MediaStore.Images.Thumbnails.MINI_KIND,
                                null);
                    }
                }
            } catch (Exception e) {
                if (DEBUG)
                    Log.e(TAG, "getThumbnail", e);
            } finally {
                if (cursor != null)
                    cursor.close();
            }
        }
        return bm;
    }

    /**
     * File and folder comparator. TODO Expose sorting option method
     *
     * @author paulburke
     */
    public static Comparator<File> sComparator = new Comparator<File>() {
        @Override
        public int compare(File f1, File f2) {
            // Sort alphabetically by lower case, which is much cleaner
            return f1.getName().toLowerCase().compareTo(
                    f2.getName().toLowerCase());
        }
    };

    /**
     * File (not directories) filter.
     *
     * @author paulburke
     */
    public static FileFilter sFileFilter = new FileFilter() {
        @Override
        public boolean accept(File file) {
            final String fileName = file.getName();
            // Return files only (not directories) and skip hidden files
            return file.isFile() && !fileName.startsWith(HIDDEN_PREFIX);
        }
    };

    /**
     * Folder (directories) filter.
     *
     * @author paulburke
     */
    public static FileFilter sDirFilter = new FileFilter() {
        @Override
        public boolean accept(File file) {
            final String fileName = file.getName();
            // Return directories only and skip hidden directories
            return file.isDirectory() && !fileName.startsWith(HIDDEN_PREFIX);
        }
    };

    /**
     * Get the Intent for selecting content to be used in an Intent Chooser.
     *
     * @return The intent for opening a file with Intent.createChooser()
     * @author paulburke
     */
    public static Intent createGetContentIntent() {
        // Implicitly allow the user to select a particular kind of data
        final Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
        // The MIME data type filter
        intent.setType("*/*");
        // Only return URIs that can be opened with ContentResolver
        intent.addCategory(Intent.CATEGORY_OPENABLE);
        return intent;
    }
}
Keen answered 29/5, 2019 at 7:56 Comment(1)
Finally, a method that works! (from this code I just removed the LocalStorageProvider)Blaisdell
S
0

This works for me perfectly if your system version is above 19, Hope this can help you.

  @TargetApi(Build.VERSION_CODES.KITKAT)
    public static String getPath(final Context context, final Uri uri) {
        final boolean isOverKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
        // DocumentProvider
        if (isOverKitKat && 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];
                }
            }
            // 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;
    }
Sauls answered 10/6, 2020 at 13:47 Comment(0)
B
0

Get Uri like below.

//* get cursor like normal

Then

while (cursor.moveToNext()) {
    Uri uri = ContentUris.withAppendedId(
    MediaStore.Images.Media.EXTERNAL_CONTENT_URI, id);
}
Badtempered answered 20/6, 2021 at 0:15 Comment(0)
S
-1

Check below method is working awesome also Oreo 8.1 ..

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    // TODO ManualMT-generated method stub
    switch (requestCode) {
        case PICKFILE_RESULT_CODE:
            if (resultCode == RESULT_OK) {

                try {
                    FilePath = data.getData().getPath();
                    Uri selectedImageUri = data.getData();

                    if (selectedImageUri.toString().contains("storage/emulated")){
                        String[] split = selectedImageUri.toString().split("storage/");
                        FilePath = "storage/"+split[1];
                    } else {
                        FilePath = ImageFilePath.getPath(getApplicationContext(), selectedImageUri);
                    }

                    recyclerview.setVisibility(View.VISIBLE);

                    if (FilePath == null) {
                        FilePath = "";
                    }
                    File file = new File(FilePath);
                    reqFile = RequestBody.create(MediaType.parse("multipart/form-data"), file);
                    image_list.add(FilePath);
                    composeImageAdapter.notifyDataSetChanged();
                } catch (Exception e){
                    Toast.makeText(ClusterCreateNote.this , e.toString(),Toast.LENGTH_SHORT).show();
                }
            }
            break;
    }

}

URI path Class:

public static class ImageFilePath {

    /**
     * Method for return file path of Gallery image
     *
     * @param context
     * @param uri
     * @return path of the selected image file from gallery
     */
    public static String getPath(final Context context, final Uri uri) {
        String selection = null;
        String[] selectionArgs = null;

        // DocumentProvider
        if (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];
                }
            }
            // DownloadsProvider
            else if (isDownloadsDocument(uri)) {

                final String id = DocumentsContract.getDocumentId(uri);
                final Uri contentUri = ContentUris.wifAppendedId(
                        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];

                Log.e("typetype",type);

                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;
                }

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

                Log.e("gddhjf",getDataColumn(context, contentUri, selection, selectionArgs));

                return getDataColumn(context, contentUri, selection, selectionArgs);
            }
        }
        if ("content".equalsIgnoreCase(uri.getScheme())) {


            if (isGooglePhotosUri(uri)) {
                return uri.getLastPathSegment();
            }

            String[] projection = {
                    MediaStore.Images.Media.DATA
            };
            Cursor cursor = null;
            try {
                cursor = context.getContentResolver()
                        .query(uri, projection, selection, selectionArgs, null);
                int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
                if (cursor.moveToFirst()) {
                    return cursor.getString(column_index);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        // File
        else if ("file".equalsIgnoreCase(uri.getScheme())) {
            return uri.getPath();
        }

        return null;
    }


    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;
    }

    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());
    }

    public static boolean isMediaDocument(Uri uri) {
        return "com.android.providers.media.documents".equals(uri.getAuthority());
    }

    public static boolean isGooglePhotosUri(Uri uri) {
        return
                "com.google.android.apps.photos.content".equals(uri.getAuthority());
    }
}
Simplehearted answered 6/2, 2020 at 7:28 Comment(1)
You are using the data column, this will no longer work.Flavopurpurin
G
-2

Bitmap bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), uri);

Galibi answered 18/10, 2016 at 13:59 Comment(2)
This does not provide an answer to the question. Once you have sufficient reputation you will be able to comment on any post; instead, provide answers that don't require clarification from the asker. - From ReviewAzimuth
" I want to load the image into a bitmap without having to copy it somewhere." , i think this answer provides an answer to the question!Galibi

© 2022 - 2024 — McMap. All rights reserved.