Convert file: Uri to File in Android
Solution 1
What you want is...
new File(uri.getPath());
... and not...
new File(uri.toString());
Notes
- For an
android.net.Uri
object which is nameduri
and created exactly as in the question,uri.toString()
returns aString
in the format"file:///mnt/sdcard/myPicture.jpg"
, whereasuri.getPath()
returns aString
in the format"/mnt/sdcard/myPicture.jpg"
. - 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
Add dependency for Kotlin Android extensions:
implementation 'androidx.core:core-ktx:{latestVersion}'
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();
}
![hpique](https://i.stack.imgur.com/7mgUt.jpg?s=256&g=1)
hpique
iOS, Android & Mac developer. Founder of Robot Media. @hpique
Updated on February 17, 2022Comments
-
hpique over 2 years
What's the easiest way to convert from a
file:
android.net.Uri
to aFile
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 over 12 yearsWhat is the difference between the two? What does
toString
do? -
Adil Hussain over 12 years
url.toString()
return a String in the following format: "file:///mnt/sdcard/myPicture.jpg", whereasurl.getPath()
returns a String in the following format: "/mnt/sdcard/myPicture.jpg", i.e. without the scheme type pre-fixed. -
Nuthatch over 12 yearsIf 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 over 10 yearsAh, but the question is Uri, not URI. People have to watch out for that :)
-
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 over 10 yearsCan't we just do: new File(uri.getPath());
-
Zorb about 10 yearscombinated with @Adil Hussain comment this two answers illuminated me about uri/strings/files thanks
-
Jacek Kwiecień about 10 yearsThis just throws: IllegalArgumentException: Expected file scheme in URI: content://media/external/images/media/80038
-
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 about 10 years
managedQuery
is now deprecated. usegetContentResolver().query(...)
instead, which works on API 11+. Add a conditional for devices older than API 11. -
Shajeel Afzal almost 10 yearsI am getting
java.lang.IllegalArgumentException: Expected file scheme in URI: content://com.shajeel.daily_monitoring.localstorage.documents.localstorage.documents/document/%2Fstorage%2Femulated%2F0%2FBook1.xlsx
exception after using this method. -
Matthew Flaschen almost 10 years@ShajeelAfzal the question says it's using the "file:" protocol. Like Xylian, you're using the content:// protocol.
-
Chlebta over 9 years@AdilHussain and then how to display this File from imageView ?
-
erkinyldz almost 9 yearsThis returns null to me for some reason. And my android uri is returns something like that:{content://com.android.providers.media.documents/document/image%3A2741} Android.Net.UriInvoker
-
Virat Singh almost 9 years@Chlebta check out a library called Picasso for loading Files (even URLs) into ImageViews very easily.
-
shoke almost 9 yearsMost 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 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 almost 8 yearsThis 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 about 7 yearsopen failed: ENOENT (No such file or directory) , how i will get storage path of anytype of File, like pdf
-
Pratibha sarve about 7 yearsthis is only for image type file, what about others?
-
Muhammad Natiq almost 7 yearshow 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 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 almost 7 yearsi 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 over 6 yearsCommonsWare'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 over 6 yearsThis should be an answer ! :) I tested it on API 25.
-
LarsH over 6 yearsThe 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 aboutcontent:
Uri's, notfile:
Uri's. -
Denys Lobur about 6 yearsMake 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 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_ almost 6 years@juanmirocks "CommonsWare's is the right solution." great! Where was that again?
-
juanmirocks almost 6 years@me_ don't know now, sorry, he might have changed his username :/
-
Pankaj Talaviya over 5 yearscrash in java.lang.IllegalArgumentException: column ''_data'' does not exist at android.database.AbstractCursor.getColumnIndexOrThrow(FileUtils.java)
-
Vahid Akbari over 5 yearsthis is worked but when i select image from gallery it throws error in line of: InputStream inputStream = context.getContentResolver().openInputStream(uri);
-
vishwajit76 over 5 yearsIt worked very well but it throws FileNotFoundException on some android devices.
-
mayank1513 over 5 yearsWhen I create file from the uri returned by content provider - it says file does not exist
-
ansh sachdeva over 5 yearsYear 2019, androidOne device, SDK 28(android pie) : both
uri.getPath()
anduri.toString()
points to/mnt/sdcard/myPicture.jpg
-
CommonsWare about 5 yearsNote 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 about 5 yearsNote 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 about 5 yearsNote 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 about 5 yearsThis 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 over 4 yearsUse this code for pick photo from camera stackoverflow.com/a/51095098/7008132
-
DragonFire over 4 yearsYou my friend are a life saver... this worked perfectly for me
-
Xenolion about 4 yearsI want to add another upVote, but it turns out I can do only once!
-
M. Usman Khan almost 4 yearsI tried this: androidx.core:core-ktx:1.5.0-alpha01 . Dont see this function "toFile"
-
M. Usman Khan almost 4 yearsWe selected a file from a chooser and then we'll first have to copy the file? :/
-
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 try1.4.0-alpha01
or stable release1.3.0
. More info: developer.android.com/jetpack/androidx/releases/… -
Hemant Kaushik almost 4 years@M.UsmanKhan it exists in version
1.3.0
, developer.android.com/kotlin/ktx/… -
M. Usman Khan almost 4 yearsI had 1.3.0 previously and it was not there :s
-
M. Usman Khan almost 4 yearsI moved the ktx to my library build file and then i see it. Thanks !
-
Ram almost 4 yearsNot working in Android 10 i got file not found exception?
-
Raii over 3 yearsMediaStore.Images.Media.DATA deprecated for SDK >= 29
-
Kishan Solanki over 3 yearsError: java.lang.IllegalArgumentException: Uri lacks 'file' scheme: content://media/external/images/media/54545
-
DeveloperApps about 3 yearsWorks great in 2021
-
badadin about 3 years
uri.toString()
gives me "content://com.google.android.apps.nbu.files.provider/1/file%3A%2F%2F%2Fstorage%2Femulated%2F0%2FDownload%2Fbackup.file",uri.getPath()
gives me "/1/file:///storage/emulated/0/Download/backup.file" andnew File(uri.getPath())
gives me "/1/file:/storage/emulated/0/Download/backup.file". So answer is not fully correct -
chezi shem tov about 3 yearsthis is a better answer stackoverflow.com/a/50522739/1023441
-
Sever about 3 yearsBad answer, especially for images it return "Uri lacks 'file' scheme: content://"
-
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 almost 3 years@VaiTon86 . We want a File object from URI, without copying the file.
-
Astha Garg over 2 yearsThis does not work in android 10
-
MG Developer over 2 yearsAgreed 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 over 2 yearsThis 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 over 2 yearsWhat do you mean by "Just move to top" for Android + Java? Thanks
-
Nims over 2 yearsAgreed, this is the real answer write here!
-
Hemant Kaushik over 2 yearsAnswer already given by Adil for Java: stackoverflow.com/a/8370299/7784230
-
Franz Andel over 2 yearshave tested and works on API 31
-
Vitaly about 2 yearsNot working solution. I get following error message /document/msf:2391: open failed: ENOENT (No such file or directory)
-
Julius Naeumann about 2 yearsThis isn't working for me with URIs returned by the file picker:
java.lang.IllegalArgumentException: URI is not absolute