real - Convertir archivo: Uri a File en Android
uri android studio (15)
@CommonsWare explicó todas las cosas bastante bien. Y realmente deberíamos usar la solución que él propuso.
Por cierto, solo la información en la que podríamos confiar al consultar ContentResolver
es el nombre y el tamaño de un archivo como se menciona aquí: Recuperar información de archivos | Desarrolladores de Android
Como puede ver, hay una interfaz OpenableColumns
que contiene solo dos campos: DISPLAY_NAME y SIZE.
En mi caso, tuve que recuperar información EXIF sobre una imagen JPEG y rotarla si fuera necesario antes de enviarla a un servidor. Para hacer eso copié el contenido de un archivo en un archivo temporal usando ContentResolver
y openInputStream()
¿Cuál es la forma más fácil de convertir un file:
android.net.Uri
a un File
en Android?
Intenté lo siguiente pero no funciona:
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());
Archivo imageToUpload = nuevo archivo (nuevo URI (androidURI.toString ())); Funciona si este es un archivo que has creado en el almacenamiento externo.
Por ejemplo, archivo: /// storage / emulated / 0 / (algún directorio y nombre de archivo)
Cadena pública getRealPathFromURI (Uri uri) {
String result;
Cursor cursor = getContentResolver().query(uri, null, null, null, null);
if (cursor == null) {
result = uri.getPath();
cursor.close();
return result;
}
cursor.moveToFirst();
int idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
result = cursor.getString(idx);
cursor.close();
return result;
}
Luego usando para obtener el archivo de URI:
File finalFile = newFile(getRealPathFromURI(uri));
- LA ESPERANZA PUEDE AYUDARTE ----
Con Kotlin es aún más fácil:
val file = File(uri.path)
O si está utilizando las extensiones de Kotlin para Android :
val file = uri.toFile()
Con el siguiente código, puedo obtener un archivo pdf compartido de la aplicación de adobe como una transmisión y guardar en la ruta de la aplicación de Android
Android.Net.Uri fileuri =
(Android.Net.Uri)Intent.GetParcelableExtra(Intent.ExtraStream);
fileuri i am getting as {content://com.adobe.reader.fileprovider/root_external/
data/data/com.adobe.reader/files/Downloads/sample.pdf}
string filePath = fileuri.Path;
filePath I am gettings as root_external/data/data/com.adobe.reader/files/Download/sample.pdf
using (var stream = ContentResolver.OpenInputStream(fileuri))
{
byte[] fileByteArray = ToByteArray(stream); //only once you can read bytes from stream second time onwards it has zero bytes
string fileDestinationPath ="<path of your destination> "
convertByteArrayToPDF(fileByteArray, fileDestinationPath);//here pdf copied to your destination path
}
public static byte[] ToByteArray(Stream stream)
{
var bytes = new List<byte>();
int b;
while ((b = stream.ReadByte()) != -1)
bytes.Add((byte)b);
return bytes.ToArray();
}
public static string convertByteArrayToPDF(byte[] pdfByteArray, string filePath)
{
try
{
Java.IO.File data = new Java.IO.File(filePath);
Java.IO.OutputStream outPut = new Java.IO.FileOutputStream(data);
outPut.Write(pdfByteArray);
return data.AbsolutePath;
}
catch (System.Exception ex)
{
return string.Empty;
}
}
Después de buscar por mucho tiempo esto es lo que funcionó para mí:
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;
}
EDIT: Lo siento, debería haber probado mejor antes. Esto debería funcionar:
new File(new URI(androidURI.toString()));
URI es java.net.URI.
Extensión de la base en la respuesta de @Jacek Kwiecień para convertir la imagen uri en un archivo
fun Uri.toImageFile(context: Context): File? {
val filePathColumn = arrayOf(MediaStore.Images.Media.DATA)
val cursor = context.contentResolver.query(this, filePathColumn, null, null, null)
if (cursor != null) {
if (cursor.moveToFirst()) {
val columnIndex = cursor.getColumnIndex(filePathColumn[0])
val filePath = cursor.getString(columnIndex)
cursor.close()
return File(filePath)
}
cursor.close()
}
return null
}
Si usamos File(uri.getPath())
, no funcionará
Si usamos la extensión de android-ktx , todavía no funciona también porque https://github.com/android/android-ktx/blob/master/src/main/java/androidx/core/net/Uri.kt
Hice esto de la siguiente manera:
try {
File file = FileUtil.from(MainActivity.this,fileUri);
Log.d("file", "File...:::: uti - "+file .getPath()+" file -" + file + " : " + file .exists());
} catch (IOException e) {
e.printStackTrace();
}
Básicamente, primero trato de usar un archivo, es decir, una imagen tomada por la cámara y guardada en la tarjeta SD. Esto no funciona para la imagen devuelta por: Intent photoPickerIntent = new Intent (Intent.ACTION_PICK); Ese caso es necesario convertir Uri a una ruta real mediante la función getRealPathFromURI()
. Entonces, la conclusión es que depende del tipo de Uri que desee convertir a Archivo.
Lo que quieres es ...
new File(uri.getPath());
... y no...
new File(uri.toString());
NOTA: uri.toString()
devuelve una Cadena en el formato: "file:///mnt/sdcard/myPicture.jpg"
, mientras que uri.getPath()
devuelve una Cadena en el formato: "/mnt/sdcard/myPicture.jpg"
.
Nada de esto funciona para mí. He encontrado que esta es la solución de trabajo. Pero mi caso es específico a las imágenes .
String[] filePathColumn = { MediaStore.Images.Media.DATA };
Cursor cursor = getActivity().getContentResolver().query(uri, filePathColumn, null, null, null);
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
String filePath = cursor.getString(columnIndex);
cursor.close();
Para las personas que están aquí buscando una solución para las imágenes, en particular aquí está.
private Bitmap getBitmapFromUri(Uri contentUri) {
String path = null;
String[] projection = { MediaStore.Images.Media.DATA };
Cursor cursor = getContentResolver().query(contentUri, projection, null, null, null);
if (cursor.moveToFirst()) {
int columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
path = cursor.getString(columnIndex);
}
cursor.close();
Bitmap bitmap = BitmapFactory.decodeFile(path);
return bitmap;
}
utilizar
InputStream inputStream = getContentResolver().openInputStream(uri);
directamente y copiar el archivo. Ver también:
https://developer.android.com/guide/topics/providers/document-provider.html
Android + Kotlin
Agregue dependencia para las extensiones Kotlin de Android:
implementation ''androidx.core:core-ktx:{latestVersion}''
Obtener archivo de uri:
uri.toFile()
Android + Java
Sólo mueve hacia arriba;)
Mejor solución
Cree una clase java simple de FileUtil y utilícela para crear, copiar y renombrar el archivo
Soy uri.toString()
y uri.getPath()
pero no trabajo para mí. Finalmente encontré esta solución.
try {
readImageInformation(new File(contentUri.getPath()));
} catch (IOException e) {
readImageInformation(new File(getRealPathFromURI(context,
contentUri)));
}
public static String getRealPathFromURI(Context context, Uri contentUri) {
String[] proj = { MediaStore.Images.Media.DATA };
Cursor 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);
}
Usuario de la clase FileUtil en tu código
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;
}
}