309

I know the absolute path of an image (say for eg, /sdcard/cats.jpg). Is there any way to get the content uri for this file ?

Actually in my code, I download an image and save it at a particular location. In order to set the image in an ImageView instance, currently I open the file using the path, get the bytes and create a bitmap and then set the bitmap in the ImageView instance. This is a very slow process, instead if I could get the content uri then I could very easily use the method imageView.setImageUri(uri)

YoussefDir
  • 287
  • 1
  • 3
  • 16
pankajagarwal
  • 13,462
  • 14
  • 54
  • 65

10 Answers10

532

Try with:

ImageView.setImageURI(Uri.fromFile(new File("/sdcard/cats.jpg")));

Or with:

ImageView.setImageURI(Uri.parse(new File("/sdcard/cats.jpg").toString()));
alkber
  • 1,426
  • 2
  • 20
  • 26
Francesco Laurita
  • 23,434
  • 8
  • 55
  • 63
  • 3
    thanks! second method works fine on 1.6, 2.1 and 2.2 but first one only on 2.2 – mishkin Nov 30 '10 at 02:45
  • 39
    neither of those methods resolves a file path to a content URI. i understand it solved the immediate problem though. – Jeffrey Blattman Apr 26 '11 at 20:46
  • in case when have sdcard path but wants content uri @Jon O idea work perfectly : http://stackoverflow.com/a/11603841/336990 – CoDe Sep 09 '12 at 08:29
  • 42
    Do not hardcode "/sdcard/"; use Environment.getExternalStorageDirectory().getPath() instead – ekatz Sep 13 '12 at 17:51
  • you can also load image from Uri file path. Code is as follows imgView.setImageURI(selectedImageUri); – Ravikumar11 Jul 15 '13 at 12:02
  • 11
    This is what both the above solutions returns: 1. file:///storage/emulated/0/DCIM/Camera/VID_20140312_171146.mp4 2. /storage/emulated/0/DCIM/Camera/VID_20140312_171146.mp4 But what i was looking for is something different. I need the content:// format URI. The answer from Jinal seems to work perfect – Ajith M A Mar 12 '14 at 11:56
  • strictly speaking, `Uri.parse(new File("/sdcard/cats.jpg").toString())` is wrong. `getContentResolver().openOutputStream(Uri.parse(new File("/sdcard/cats.jpg").toString()))` will throw exception "File not found exception: No content provider" – Helin Wang Oct 07 '14 at 19:35
  • 6
    hey `Uri.fromFile` will not work on android 26+, you should use file provider – vuhung3990 May 24 '18 at 02:52
  • @JeffreyBlattman here the same https://stackoverflow.com/a/27603026/7767664 – user924 Oct 30 '18 at 19:38
  • I agree with vuhung3990. Try Uri p; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { p = FileProvider.getUriForFile(this, "com.example.android.fileprovider", imgFile); } else { p = Uri.fromFile(imgFile); } – Orlov Const Nov 26 '19 at 09:24
  • hey none of this doesn't work with api => 29, only one way to get uri by path that i found is - https://stackoverflow.com/a/53349110/5215604 – whereismaxmax Mar 22 '20 at 08:45
99

UPDATE

Here it is assumed that your media (Image/Video) is already added to content media provider. If not then you will not able to get the content URL as exact what you want. Instead there will be file Uri.

I had same question for my file explorer activity. You should know that the contenturi for file only supports mediastore data like image, audio and video. I am giving you the code for getting image content uri from selecting an image from sdcard. Try this code, maybe it will work for you...

public static Uri getImageContentUri(Context context, File imageFile) {
  String filePath = imageFile.getAbsolutePath();
  Cursor cursor = context.getContentResolver().query(
      MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
      new String[] { MediaStore.Images.Media._ID },
      MediaStore.Images.Media.DATA + "=? ",
      new String[] { filePath }, null);
  if (cursor != null && cursor.moveToFirst()) {
    int id = cursor.getInt(cursor.getColumnIndex(MediaStore.MediaColumns._ID));
    cursor.close();
    return Uri.withAppendedPath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "" + id);
  } else {
    if (imageFile.exists()) {
      ContentValues values = new ContentValues();
      values.put(MediaStore.Images.Media.DATA, filePath);
      return context.getContentResolver().insert(
          MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
    } else {
      return null;
    }
  }
}

For support android Q

public static Uri getImageContentUri(Context context, File imageFile) {
String filePath = imageFile.getAbsolutePath();
Cursor cursor = context.getContentResolver().query(
        MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
        new String[]{MediaStore.Images.Media._ID},
        MediaStore.Images.Media.DATA + "=? ",
        new String[]{filePath}, null);
if (cursor != null && cursor.moveToFirst()) {
    int id = cursor.getInt(cursor.getColumnIndex(MediaStore.MediaColumns._ID));
    cursor.close();
    return Uri.withAppendedPath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "" + id);
} else {
    if (imageFile.exists()) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            ContentResolver resolver = context.getContentResolver();
            Uri picCollection = MediaStore.Images.Media
                    .getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY);
            ContentValues picDetail = new ContentValues();
            picDetail.put(MediaStore.Images.Media.DISPLAY_NAME, imageFile.getName());
            picDetail.put(MediaStore.Images.Media.MIME_TYPE, "image/jpg");
            picDetail.put(MediaStore.Images.Media.RELATIVE_PATH,"DCIM/" + UUID.randomUUID().toString());
            picDetail.put(MediaStore.Images.Media.IS_PENDING,1);
            Uri finaluri = resolver.insert(picCollection, picDetail);
            picDetail.clear();
            picDetail.put(MediaStore.Images.Media.IS_PENDING, 0);
            resolver.update(picCollection, picDetail, null, null);
            return finaluri;
        }else {
            ContentValues values = new ContentValues();
            values.put(MediaStore.Images.Media.DATA, filePath);
            return context.getContentResolver().insert(
                    MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
        }

    } else {
        return null;
    }
  }
}
Mostafa Anter
  • 3,445
  • 24
  • 26
Jinal Jogiyani
  • 1,199
  • 1
  • 9
  • 5
  • I was looking for a method to find the content:// URI of my recorded video file and the above code seems to work perfect on Nexus 4(Android 4.3). It would be nice if you can please explain the code. – Ajith M A Mar 12 '14 at 12:35
  • I have tried this to get the Content Uri for a File with the Absolute path "/sdcard/Image Depo/picture.png". It didn't work, so i debuged the code path and found that the Cursor is empty, and when the entry is being added to ContentProvider, its giving null as the Content Uri. Please help. – Sri Krishna Apr 02 '15 at 08:56
  • This should be the accepted answer! Also this is the fix for Apps crashing in Android preview N (upcoming API level 24), when trying to take a photo with ACTION_IMAGE_CAPTURE using a file: Uri value for EXTRA_OUTPUT resulting in a FileUriExposedException. Just replace your `putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(imageFile))` with `putExtra(MediaStore.EXTRA_OUTPUT, getImageContentUri(context, imageFile))`. – sec_aw Apr 08 '16 at 13:53
  • 1
    I have the file path - file:///storage/emulated/0/Android/data/com.packagename/files/out.mp4, but getting null when I try to get contentUri. I also tried changing `MediaStore.Images.Media` to `MediaStore.Video.Media`, but still no luck. – Narendra Singh Nov 30 '16 at 09:32
  • 1
    This is not working on android Pie api 28. Cursor returns null – Ibrahim Gharyali Nov 15 '18 at 07:26
  • 2
    Can you update this method for Android 10 as DATA column is not accessible in Android 10 ? – Khushbu Shah Dec 23 '19 at 15:28
  • This is the best solution after the release of android Q. – Mubashir Murtaza Sep 29 '20 at 07:55
18

The accepted solution is probably the best bet for your purposes, but to actually answer the question in the subject line:

In my app, I have to get the path from URIs and get the URI from paths. 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 use that info to look it up.

Jon O
  • 6,532
  • 1
  • 46
  • 57
  • Not always the case, there are two semi-guaranteed columns returned, and that is `OpenableColumns.DISPLAY_NAME & OpenableColumns.SIZE` if the sending app even follows the "rules". I found that some major apps only returns these two fields and not always the `_data` field. In the case where you don't have the data field which normally contains a direct path to the content, you have to first read the content and write it to a file or into memory and then you have your own path. – Pierre Mar 28 '19 at 05:27
16

// This code works for images on 2.2, not sure if any other media types

   //Your file path - Example here is "/sdcard/cats.jpg"
   final String filePathThis = imagePaths.get(position).toString();

   MediaScannerConnectionClient mediaScannerClient = new
   MediaScannerConnectionClient() {
    private MediaScannerConnection msc = null;
    {
        msc = new MediaScannerConnection(getApplicationContext(), this);
        msc.connect();
    }

    public void onMediaScannerConnected(){
        msc.scanFile(filePathThis, null);
    }


    public void onScanCompleted(String path, Uri uri) {
        //This is where you get your content uri
            Log.d(TAG, uri.toString());
        msc.disconnect();
    }
   };
AndroidDebaser
  • 369
  • 3
  • 5
  • 1
    great, helped me with sharing to Google+, as that app requires a media stream with a content Uri -- absolute path does not work. – Ridcully Jun 18 '12 at 20:02
  • 1
    Excellent! I can confirm this works with Audio media types as well. – Matt M Aug 28 '12 at 20:00
9

Easiest and the robust way for creating Content Uri content:// from a File is to use FileProvider. Uri provided by FileProvider can be used also providing Uri for sharing files with other apps too. To get File Uri from a absolute path of File you can use DocumentFile.fromFile(new File(path, name)), it's added in Api 22, and returns null for versions below.

File imagePath = new File(Context.getFilesDir(), "images");
File newFile = new File(imagePath, "default_image.jpg");
Uri contentUri = FileProvider.getUriForFile(getContext(), "com.mydomain.fileprovider", newFile);
Bugs Happen
  • 2,169
  • 4
  • 33
  • 59
Thracian
  • 43,021
  • 16
  • 133
  • 222
9

You can use these two ways based on use

Uri uri = Uri.parse("String file location");

or

Uri uri = Uri.fromFile(new File("string file location"));

I have tried both ways and both works.

Hemanth Raj
  • 32,555
  • 10
  • 92
  • 82
8

Its late, but may help someone in future.

To get content URI for a file, you may use the following method:

FileProvider.getUriForFile(Context context, String authority, File file)

It returns the content URI.

Check this out to learn how to setup a FileProvider

jasxir
  • 808
  • 9
  • 18
artenson.art98
  • 1,543
  • 15
  • 15
4

Obtaining the File ID without writing any code, just with adb shell CLI commands:

adb shell content query --uri "content://media/external/video/media" | grep FILE_NAME | grep -Eo " _id=([0-9]+)," | grep -Eo "[0-9]+"
BogdanBiv
  • 1,485
  • 1
  • 16
  • 33
  • Google "adb get real path from content uri" and this question is top 1, with your 0-vote answer's content in search result summary. So let me be the first to vote. THANK YOU bro! – Weekend Aug 13 '18 at 09:59
  • This is cool. But it seem you will get: `Permission Denial: Do not have permission in call getContentProviderExternal() from pid=15660, uid=10113 requires android.permission.ACCESS_CONTENT_PROVIDERS_EXTERNALLY`, unless you're rooted. – not2qubit Oct 04 '18 at 15:49
  • so this does need root access of phone? – skaveesh May 25 '20 at 05:50
2

Is better to use a validation to support versions pre Android N, example:

  if (Build.VERSION.SDK_INT >=  Build.VERSION_CODES.N) {
     imageUri = Uri.parse(filepath);
  } else{
     imageUri = Uri.fromFile(new File(filepath));
  }

  if (Build.VERSION.SDK_INT >=  Build.VERSION_CODES.N) {
     ImageView.setImageURI(Uri.parse(new File("/sdcard/cats.jpg").toString()));         
  } else{
     ImageView.setImageURI(Uri.fromFile(new File("/sdcard/cats.jpg")));
  }

https://es.stackoverflow.com/questions/71443/reporte-crash-android-os-fileuriexposedexception-en-android-n

Jorgesys
  • 124,308
  • 23
  • 334
  • 268
0

U can try below code snippet

    public Uri getUri(ContentResolver cr, String path){
    Uri mediaUri = MediaStore.Files.getContentUri(VOLUME_NAME);
    Cursor ca = cr.query(mediaUri, new String[] { MediaStore.MediaColumns._ID }, MediaStore.MediaColumns.DATA + "=?", new String[] {path}, null);
    if (ca != null && ca.moveToFirst()) {
        int id = ca.getInt(ca.getColumnIndex(MediaStore.MediaColumns._ID));
        ca.close();
        return  MediaStore.Files.getContentUri(VOLUME_NAME,id);
    }
    if(ca != null) {
        ca.close();
    }
    return null;
}
Dale K
  • 25,246
  • 15
  • 42
  • 71
caopeng
  • 914
  • 13
  • 23