Convert file: Uri to File in Android

512,613

Solution 1

What you want is...

new File(uri.getPath());

... and not...

new File(uri.toString());
Notes
  1. For an android.net.Uri object which is named uri and created exactly as in the question, uri.toString() returns a String in the format "file:///mnt/sdcard/myPicture.jpg", whereas uri.getPath() returns a String in the format "/mnt/sdcard/myPicture.jpg".
  2. I understand that there are nuances to file storage in Android. My intention in this answer is to answer exactly what the questioner asked and not to get into the nuances.

Solution 2

use

InputStream inputStream = getContentResolver().openInputStream(uri);    

directly and copy the file. Also see:

https://developer.android.com/guide/topics/providers/document-provider.html

Solution 3

After searching for a long time this is what worked for me:

File file = new File(getPath(uri));


public String getPath(Uri uri) 
    {
        String[] projection = { MediaStore.Images.Media.DATA };
        Cursor cursor = getContentResolver().query(uri, projection, null, null, null);
        if (cursor == null) return null;
        int column_index =             cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
        cursor.moveToFirst();
        String s=cursor.getString(column_index);
        cursor.close();
        return s;
    }

Solution 4

Android + Kotlin

  1. Add dependency for Kotlin Android extensions:

    implementation 'androidx.core:core-ktx:{latestVersion}'

  2. Get file from uri:

    uri.toFile()

Android + Java

Just move to top ;)

Solution 5

Best Solution

Create one simple FileUtil class & use to create, copy and rename the file

I used uri.toString() and uri.getPath() but not work for me. I finally found this solution.

import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.provider.OpenableColumns;
import android.util.Log;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class FileUtil {
    private static final int EOF = -1;
    private static final int DEFAULT_BUFFER_SIZE = 1024 * 4;

    private FileUtil() {

    }

    public static File from(Context context, Uri uri) throws IOException {
        InputStream inputStream = context.getContentResolver().openInputStream(uri);
        String fileName = getFileName(context, uri);
        String[] splitName = splitFileName(fileName);
        File tempFile = File.createTempFile(splitName[0], splitName[1]);
        tempFile = rename(tempFile, fileName);
        tempFile.deleteOnExit();
        FileOutputStream out = null;
        try {
            out = new FileOutputStream(tempFile);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        if (inputStream != null) {
            copy(inputStream, out);
            inputStream.close();
        }

        if (out != null) {
            out.close();
        }
        return tempFile;
    }

    private static String[] splitFileName(String fileName) {
        String name = fileName;
        String extension = "";
        int i = fileName.lastIndexOf(".");
        if (i != -1) {
            name = fileName.substring(0, i);
            extension = fileName.substring(i);
        }

        return new String[]{name, extension};
    }

    private static String getFileName(Context context, Uri uri) {
        String result = null;
        if (uri.getScheme().equals("content")) {
            Cursor cursor = context.getContentResolver().query(uri, null, null, null, null);
            try {
                if (cursor != null && cursor.moveToFirst()) {
                    result = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (cursor != null) {
                    cursor.close();
                }
            }
        }
        if (result == null) {
            result = uri.getPath();
            int cut = result.lastIndexOf(File.separator);
            if (cut != -1) {
                result = result.substring(cut + 1);
            }
        }
        return result;
    }

    private static File rename(File file, String newName) {
        File newFile = new File(file.getParent(), newName);
        if (!newFile.equals(file)) {
            if (newFile.exists() && newFile.delete()) {
                Log.d("FileUtil", "Delete old " + newName + " file");
            }
            if (file.renameTo(newFile)) {
                Log.d("FileUtil", "Rename file to " + newName);
            }
        }
        return newFile;
    }

    private static long copy(InputStream input, OutputStream output) throws IOException {
        long count = 0;
        int n;
        byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
        while (EOF != (n = input.read(buffer))) {
            output.write(buffer, 0, n);
            count += n;
        }
        return count;
    }
}

Use FileUtil class in your code

try {
         File file = FileUtil.from(MainActivity.this,fileUri);
         Log.d("file", "File...:::: uti - "+file .getPath()+" file -" + file + " : " + file .exists());

  } catch (IOException e) {
          e.printStackTrace();
  }
Share:
512,613
hpique
Author by

hpique

iOS, Android & Mac developer. Founder of Robot Media. @hpique

Updated on February 17, 2022

Comments

  • hpique
    hpique over 2 years

    What's the easiest way to convert from a file: android.net.Uri to a File in Android?

    Tried the following but it doesn't work:

     final File file = new File(Environment.getExternalStorageDirectory(), "read.me");
     Uri uri = Uri.fromFile(file);
     File auxFile = new File(uri.toString());
     assertEquals(file.getAbsolutePath(), auxFile.getAbsolutePath());
    
  • Merlyn Morgan-Graham
    Merlyn Morgan-Graham over 12 years
    What is the difference between the two? What does toString do?
  • Adil Hussain
    Adil Hussain over 12 years
    url.toString() return a String in the following format: "file:///mnt/sdcard/myPicture.jpg", whereas url.getPath() returns a String in the following format: "/mnt/sdcard/myPicture.jpg", i.e. without the scheme type pre-fixed.
  • Nuthatch
    Nuthatch over 12 years
    If the URI is a Images.Media.EXTERNAL_CONTENT_URI (e.g. from Intent.ACTION_PICK for the Gallery) from you will need to look it up as in stackoverflow.com/q/6935497/42619
  • Muz
    Muz over 10 years
    Ah, but the question is Uri, not URI. People have to watch out for that :)
  • Matthew Flaschen
    Matthew Flaschen over 10 years
    @Muz, I believe the answer is correct. androidURI is an android.net.Uri. java.net.URI (which does exist on Android) is only used as part of the conversion process.
  • Bart Burg
    Bart Burg over 10 years
    Can't we just do: new File(uri.getPath());
  • Zorb
    Zorb about 10 years
    combinated with @Adil Hussain comment this two answers illuminated me about uri/strings/files thanks
  • Jacek Kwiecień
    Jacek Kwiecień about 10 years
    This just throws: IllegalArgumentException: Expected file scheme in URI: content://media/external/images/media/80038
  • Matthew Flaschen
    Matthew Flaschen about 10 years
    @Xylian, yes, the question asks, "What's the easiest way to convert from a file: android.net.Uri to a File". You're not using a file: URL.
  • Kyle Falconer
    Kyle Falconer about 10 years
    managedQuery is now deprecated. use getContentResolver().query(...) instead, which works on API 11+. Add a conditional for devices older than API 11.
  • Shajeel Afzal
    Shajeel Afzal almost 10 years
    I am getting java.lang.IllegalArgumentException: Expected file scheme in URI: content://com.shajeel.daily_monitoring.localstorage.document‌​s.localstorage.docum‌​ents/document/%2Fsto‌​rage%2Femulated%2F0%‌​2FBook1.xlsx exception after using this method.
  • Matthew Flaschen
    Matthew Flaschen almost 10 years
    @ShajeelAfzal the question says it's using the "file:" protocol. Like Xylian, you're using the content:// protocol.
  • Chlebta
    Chlebta over 9 years
    @AdilHussain and then how to display this File from imageView ?
  • erkinyldz
    erkinyldz almost 9 years
    This returns null to me for some reason. And my android uri is returns something like that:{content://com.android.providers.media.documents/docume‌​nt/image%3A2741} And‌​roid.Net.UriInvoker
  • Virat Singh
    Virat Singh almost 9 years
    @Chlebta check out a library called Picasso for loading Files (even URLs) into ImageViews very easily.
  • shoke
    shoke almost 9 years
    Most of the time I'm getting open failed: ENOENT (No such file or directory) When I try to open the File given with this. Also, if the Uri is the Content Uri of an Image for example, it definitely doesn't work.
  • HendraWD
    HendraWD over 8 years
    @AdilHussain in one of my test device, "Uri.getPath();" sometimes return "file:///pathToTheFile". I don't know why is that happens, so i need to substring that path to get the path without scheme type.
  • Liran Cohen
    Liran Cohen almost 8 years
    This is not a good solution since it wont work across all platforms. Some devices do not even populate this column, i recommend letting the content provider handle this as suggested by @CommonWare in previous answer
  • Pratibha sarve
    Pratibha sarve about 7 years
    open failed: ENOENT (No such file or directory) , how i will get storage path of anytype of File, like pdf
  • Pratibha sarve
    Pratibha sarve about 7 years
    this is only for image type file, what about others?
  • Muhammad Natiq
    Muhammad Natiq almost 7 years
    how to read actual file fro its uri in onActivityForResult? i am working on audio file want to pick audio File instead of just its url...the above solution is for only to create new file on that path of uri instead of getting that existing audio/any file
  • Adil Hussain
    Adil Hussain almost 7 years
    @natiqjavid you are asking a question that is outside the scope of this thread. Please start a different thread for your issue that stating what you've tried and what hasn't worked.
  • Muhammad Natiq
    Muhammad Natiq almost 7 years
    i solved my problem with this instead of getting that actual file i copied that input stream from uri and write my own same file by outputsteam stackoverflow.com/questions/28224612/…
  • juanmirocks
    juanmirocks over 6 years
    CommonsWare's is the right solution. A URI can mean mean things, not only a localsystem file. Either way, if you are forcing the URI to be a file, with at least java 8 you can do new File(uri)
  • iroiroys
    iroiroys over 6 years
    This should be an answer ! :) I tested it on API 25.
  • LarsH
    LarsH over 6 years
    The OP did not ask about Uri's in general, but file: Uri's. As such, this answer is correct. @Nuthatch: I think you're talking about content: Uri's, not file: Uri's.
  • Denys Lobur
    Denys Lobur about 6 years
    Make sure you're getting your uri from Intent.ACTION_PICK and not Intent.ACTION_GET_CONTENT, because the later has no MediaStore.Images.Media.DATA
  • Kent Lauridsen
    Kent Lauridsen about 6 years
    @Adil Hussain It looks like you show url.toString (with a lower case L in url) instead of the uri.toString (with lower case I in uri). Just in case someone was trying urL with no luck
  • me_
    me_ almost 6 years
    @juanmirocks "CommonsWare's is the right solution." great! Where was that again?
  • juanmirocks
    juanmirocks almost 6 years
    @me_ don't know now, sorry, he might have changed his username :/
  • Pankaj Talaviya
    Pankaj Talaviya over 5 years
    crash in java.lang.IllegalArgumentException: column ''_data'' does not exist at android.database.AbstractCursor.getColumnIndexOrThrow(FileUt‌​ils.java)
  • Vahid Akbari
    Vahid Akbari over 5 years
    this is worked but when i select image from gallery it throws error in line of: InputStream inputStream = context.getContentResolver().openInputStream(uri);
  • vishwajit76
    vishwajit76 over 5 years
    It worked very well but it throws FileNotFoundException on some android devices.
  • mayank1513
    mayank1513 over 5 years
    When I create file from the uri returned by content provider - it says file does not exist
  • ansh sachdeva
    ansh sachdeva over 5 years
    Year 2019, androidOne device, SDK 28(android pie) : both uri.getPath() and uri.toString() points to /mnt/sdcard/myPicture.jpg
  • CommonsWare
    CommonsWare about 5 years
    Note that this technique is banned on Android Q. You can no longer access the DATA column (and that was an unreliable approach in the first place).
  • CommonsWare
    CommonsWare about 5 years
    Note that this technique is banned on Android Q. You can no longer access the DATA column (and that was an unreliable approach in the first place).
  • CommonsWare
    CommonsWare about 5 years
    Note that this technique is banned on Android Q. You can no longer access the DATA column (and that was an unreliable approach in the first place).
  • Mike Makarov
    Mike Makarov about 5 years
    This should be upvoted much much more. ContentResolver is what it seems you'll look at by default to resolve the path from Android.Net.Uri.
  • vishwajit76
    vishwajit76 over 4 years
    Use this code for pick photo from camera stackoverflow.com/a/51095098/7008132
  • DragonFire
    DragonFire over 4 years
    You my friend are a life saver... this worked perfectly for me
  • Xenolion
    Xenolion about 4 years
    I want to add another upVote, but it turns out I can do only once!
  • M. Usman Khan
    M. Usman Khan almost 4 years
    I tried this: androidx.core:core-ktx:1.5.0-alpha01 . Dont see this function "toFile"
  • M. Usman Khan
    M. Usman Khan almost 4 years
    We selected a file from a chooser and then we'll first have to copy the file? :/
  • Hemant Kaushik
    Hemant Kaushik almost 4 years
    @M.UsmanKhan as per the documentation version 1.5.0-alpha01 can be used with minimum Android 11 Beta 01, so you can try 1.4.0-alpha01 or stable release 1.3.0. More info: developer.android.com/jetpack/androidx/releases/…
  • Hemant Kaushik
    Hemant Kaushik almost 4 years
    @M.UsmanKhan it exists in version 1.3.0, developer.android.com/kotlin/ktx/…
  • M. Usman Khan
    M. Usman Khan almost 4 years
    I had 1.3.0 previously and it was not there :s
  • M. Usman Khan
    M. Usman Khan almost 4 years
    I moved the ktx to my library build file and then i see it. Thanks !
  • Ram
    Ram almost 4 years
    Not working in Android 10 i got file not found exception?
  • Raii
    Raii over 3 years
    MediaStore.Images.Media.DATA deprecated for SDK >= 29
  • Kishan Solanki
    Kishan Solanki over 3 years
    Error: java.lang.IllegalArgumentException: Uri lacks 'file' scheme: content://media/external/images/media/54545
  • DeveloperApps
    DeveloperApps about 3 years
    Works great in 2021
  • badadin
    badadin about 3 years
    uri.toString() gives me "content://com.google.android.apps.nbu.files.provider/1/file‌​%3A%2F%2F%2Fstorage%‌​2Femulated%2F0%2FDow‌​nload%2Fbackup.file"‌​, uri.getPath() gives me "/1/file:///storage/emulated/0/Download/backup.file" and new File(uri.getPath()) gives me "/1/file:/storage/emulated/0/Download/backup.file". So answer is not fully correct
  • chezi shem tov
    chezi shem tov about 3 years
    this is a better answer stackoverflow.com/a/50522739/1023441
  • Sever
    Sever about 3 years
    Bad answer, especially for images it return "Uri lacks 'file' scheme: content://"
  • VaiTon
    VaiTon almost 3 years
    @M.UsmanKhan it depends. If you want to use the file later on copy it. Otherwise just use it as an input stream. You should not rely on other apps keeping the file for you.
  • M. Usman Khan
    M. Usman Khan almost 3 years
    @VaiTon86 . We want a File object from URI, without copying the file.
  • Astha Garg
    Astha Garg over 2 years
    This does not work in android 10
  • MG Developer
    MG Developer over 2 years
    Agreed this should be the top answer. File to URI will not work because permissions, especially in Android 11 and above. Must use contentResolver. developer.android.com/guide/topics/providers/…
  • MG Developer
    MG Developer over 2 years
    This will not work Android API 11 and above on external storage unless you have manage external storage permission, which is very sensitive and most likely will not be granted. See the answer from Juan Camilo Rodriguez Durán
  • Syl OR
    Syl OR over 2 years
    What do you mean by "Just move to top" for Android + Java? Thanks
  • Nims
    Nims over 2 years
    Agreed, this is the real answer write here!
  • Hemant Kaushik
    Hemant Kaushik over 2 years
    Answer already given by Adil for Java: stackoverflow.com/a/8370299/7784230
  • Franz Andel
    Franz Andel over 2 years
    have tested and works on API 31
  • Vitaly
    Vitaly about 2 years
    Not working solution. I get following error message /document/msf:2391: open failed: ENOENT (No such file or directory)
  • Julius Naeumann
    Julius Naeumann about 2 years
    This isn't working for me with URIs returned by the file picker: java.lang.IllegalArgumentException: URI is not absolute