android - visor - load image from gallery with glide
android get real path por Uri.getPath() (9)
Estoy tratando de obtener una imagen de la galería.
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, "Select picture"), resultCode );
Después de regresar de esta actividad, tengo una información que contiene Uri. Parece que:
content://media/external/images/1
¿Cómo puedo convertir esta ruta en real (como '' /sdcard/image.png
'')?
Gracias
Prueba esto
Aún así, si obtiene el problema para obtener la ruta real, puede probar mis respuestas. Las respuestas anteriores no me ayudaron.
Explicación : - Este método obtiene el URI y luego verifica el nivel de la API de su dispositivo Android luego de que, de acuerdo con el nivel de API, generará la ruta real. El código para generar una ruta real es diferente según los niveles de API.
Aquí está mi respuesta
¿Es realmente necesario que obtengas un camino físico?
Por ejemplo, ImageView.setImageURI()
y ContentResolver.openInputStream()
permiten acceder al contenido de un archivo sin conocer su ruta real.
@Rene Juuse - arriba en comentarios ... ¡Gracias por este enlace!
. el código para obtener la ruta real es un poco diferente de un SDK a otro, por lo que a continuación tenemos tres métodos que tratan con diferentes SDK.
getRealPathFromURI_API19 (): devuelve una ruta real para API 19 (o superior pero no probado) getRealPathFromURI_API11to18 (): devuelve la ruta real para API 11 a API 18 getRealPathFromURI_below11 (): devuelve una ruta real para API por debajo de 11
public class RealPathUtil {
@SuppressLint("NewApi")
public static String getRealPathFromURI_API19(Context context, Uri uri){
String filePath = "";
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 = context.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
column, sel, new String[]{ id }, null);
int columnIndex = cursor.getColumnIndex(column[0]);
if (cursor.moveToFirst()) {
filePath = cursor.getString(columnIndex);
}
cursor.close();
return filePath;
}
@SuppressLint("NewApi")
public static String getRealPathFromURI_API11to18(Context context, Uri contentUri) {
String[] proj = { MediaStore.Images.Media.DATA };
String result = null;
CursorLoader cursorLoader = new CursorLoader(
context,
contentUri, proj, null, null, null);
Cursor cursor = cursorLoader.loadInBackground();
if(cursor != null){
int column_index =
cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
result = cursor.getString(column_index);
}
return result;
}
public static String getRealPathFromURI_BelowAPI11(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);
}
fuente: link
ACTUALIZACIÓN 2016 de marzo
Para solucionar todos los problemas con la ruta de las imágenes, intento crear una galería personalizada como Facebook y otras aplicaciones. Esto se debe a que puede usar solo archivos locales (archivos reales, no virtuales o temporales), resuelvo todos los problemas con esta biblioteca.
https://github.com/nohana/Laevatein (esta biblioteca es para tomar fotos de la cámara o elegir entre galery, si eliges de la galería tiene un cajón con álbumes y solo muestra los archivos locales)
Esto es lo que hago:
Uri selectedImageURI = data.getData();
imageFile = new File(getRealPathFromURI(selectedImageURI));
y:
private String getRealPathFromURI(Uri contentURI) {
String result;
Cursor cursor = getContentResolver().query(contentURI, null, null, null, null);
if (cursor == null) { // Source is Dropbox or other similar local file path
result = contentURI.getPath();
} else {
cursor.moveToFirst();
int idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
result = cursor.getString(idx);
cursor.close();
}
return result;
}
NOTA: el método managedQuery()
está en desuso, por lo que no lo estoy usando.
Última edición: Mejora. ¡Deberíamos cerrar el cursor!
Esto me ayudó a obtener uri de la Galería y convertirlo a un archivo para la carga de varias partes.
File file = FileUtils.getFile(this, fileUri);
Hii aquí está mi código completo para tomar la imagen de la cámara o galeery
// Mi declaración de variables
protected static final int CAMERA_REQUEST = 0;
protected static final int GALLERY_REQUEST = 1;
Bitmap bitmap;
Uri uri;
Intent picIntent = null;
//Al hacer clic
if (v.getId()==R.id.image_id){
startDilog();
}
// cuerpo del método
private void startDilog() {
AlertDialog.Builder myAlertDilog = new AlertDialog.Builder(yourActivity.this);
myAlertDilog.setTitle("Upload picture option..");
myAlertDilog.setMessage("Where to upload picture????");
myAlertDilog.setPositiveButton("Gallery", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
picIntent = new Intent(Intent.ACTION_GET_CONTENT,null);
picIntent.setType("image/*");
picIntent.putExtra("return_data",true);
startActivityForResult(picIntent,GALLERY_REQUEST);
}
});
myAlertDilog.setNegativeButton("Camera", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
picIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(picIntent,CAMERA_REQUEST);
}
});
myAlertDilog.show();
}
// Y el resto de las cosas
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode==GALLERY_REQUEST){
if (resultCode==RESULT_OK){
if (data!=null) {
uri = data.getData();
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
try {
BitmapFactory.decodeStream(getContentResolver().openInputStream(uri), null, options);
options.inSampleSize = calculateInSampleSize(options, 100, 100);
options.inJustDecodeBounds = false;
Bitmap image = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri), null, options);
imageofpic.setImageBitmap(image);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}else {
Toast.makeText(getApplicationContext(), "Cancelled",
Toast.LENGTH_SHORT).show();
}
}else if (resultCode == RESULT_CANCELED) {
Toast.makeText(getApplicationContext(), "Cancelled",
Toast.LENGTH_SHORT).show();
}
}else if (requestCode == CAMERA_REQUEST) {
if (resultCode == RESULT_OK) {
if (data.hasExtra("data")) {
bitmap = (Bitmap) data.getExtras().get("data");
uri = getImageUri(YourActivity.this,bitmap);
File finalFile = new File(getRealPathFromUri(uri));
imageofpic.setImageBitmap(bitmap);
} else if (data.getExtras() == null) {
Toast.makeText(getApplicationContext(),
"No extras to retrieve!", Toast.LENGTH_SHORT)
.show();
BitmapDrawable thumbnail = new BitmapDrawable(
getResources(), data.getData().getPath());
pet_pic.setImageDrawable(thumbnail);
}
} else if (resultCode == RESULT_CANCELED) {
Toast.makeText(getApplicationContext(), "Cancelled",
Toast.LENGTH_SHORT).show();
}
}
}
private String getRealPathFromUri(Uri tempUri) {
Cursor cursor = null;
try {
String[] proj = { MediaStore.Images.Media.DATA };
cursor = this.getContentResolver().query(tempUri, 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();
}
}
}
public static int calculateInSampleSize(
BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int halfHeight = height / 2;
final int halfWidth = width / 2;
// Calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
while ((halfHeight / inSampleSize) > reqHeight
&& (halfWidth / inSampleSize) > reqWidth) {
inSampleSize *= 2;
}
}
return inSampleSize;
}
private Uri getImageUri(YourActivity youractivity, Bitmap bitmap) {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, byteArrayOutputStream);
String path = MediaStore.Images.Media.insertImage(youractivity.getContentResolver(), bitmap, "Title", null);
return Uri.parse(path);
}
EDITAR: Utilice esta solución aquí: https://.com/a/20559175/2033223 Funciona perfecto!
Primero de, gracias por su solución @luizfelipetx
Cambié tu solución un poco. Esto funciona para mí:
public static String getRealPathFromDocumentUri(Context context, Uri uri){
String filePath = "";
Pattern p = Pattern.compile("(//d+)$");
Matcher m = p.matcher(uri.toString());
if (!m.find()) {
Log.e(ImageConverter.class.getSimpleName(), "ID for requested image not found: " + uri.toString());
return filePath;
}
String imgId = m.group();
String[] column = { MediaStore.Images.Media.DATA };
String sel = MediaStore.Images.Media._ID + "=?";
Cursor cursor = context.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
column, sel, new String[]{ imgId }, null);
int columnIndex = cursor.getColumnIndex(column[0]);
if (cursor.moveToFirst()) {
filePath = cursor.getString(columnIndex);
}
cursor.close();
return filePath;
}
Nota: Así que tenemos documentos e imágenes, dependiendo, si la imagen proviene de ''recientes'', ''galería'' o cualquier otra cosa. Así que extraigo la identificación de la imagen primero antes de buscarla.
No hay un camino real
Un Uri
con un esquema de content
es un identificador opaco para algunos contenidos. Si ese Uri
representa contenido que se puede ContentResolver
, puede usar ContentResolver
y openInputStream()
para obtener un InputStream
en ese contenido. De forma similar, un Uri
con un esquema http
o https
no representa un archivo local, y usted necesitaría usar una API de cliente HTTP para acceder a él.
Solo un Uri
con un esquema de file
identifica un archivo (salvo casos donde el archivo fue movido o eliminado después de que se creó el Uri
).
Lo que las personas estúpidas hacen es tratar de derivar una ruta del sistema de archivos intentando decodificar el contenido del Uri
, posiblemente junto con conjuros de lanzamiento para invocar $EVIL_DEITY
. En el mejor de los casos, esto no será confiable, por tres razones:
Las reglas para decodificar los valores de
Uri
pueden cambiar con el tiempo, como con las versiones de Android, ya que la estructura deUri
representa un detalle de implementación, no una interfazIncluso si obtiene una ruta del sistema de archivos, es posible que no tenga derechos para acceder al archivo
No todos los valores de
Uri
pueden decodificarse mediante algoritmos fijos, ya que muchas aplicaciones tienen sus propios proveedores, y pueden indicar desde columnas de activos hasta columnasBLOB
y datos que deben transmitirse desde Internet.
Si tiene alguna API limitada que requiere un archivo, use el InputStream
de openInputStream()
para hacer una copia de ese contenido. Ya sea que se trate de una copia transitoria (por ejemplo, utilizada para una operación de carga de archivos, luego eliminada) o una copia duradera (por ejemplo, para una función de "importación" de su aplicación), depende de usted.
Nota: esta es una mejora en la respuesta de @ user3516549 y la he comprobado en Moto G3 con Android 6.0.1
Tengo este problema, así que he intentado con la respuesta de @ user3516549, pero en algunos casos no funcionaba correctamente. He encontrado que en Android 6.0 (o superior) cuando comenzamos la intención de selección de imágenes de galería, se abre una pantalla que muestra imágenes recientes cuando el usuario selecciona la imagen de esta lista, obtendremos uri como
content://com.android.providers.media.documents/document/image%3A52530
mientras que si el usuario selecciona la galería del cajón deslizante en lugar de reciente, obtendremos uri como
content://media/external/images/media/52530
Así que lo he manejado en getRealPathFromURI_API19()
public static String getRealPathFromURI_API19(Context context, Uri uri) {
String filePath = "";
if (uri.getHost().contains("com.android.providers.media")) {
// Image pick from recent
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 = context.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
column, sel, new String[]{id}, null);
int columnIndex = cursor.getColumnIndex(column[0]);
if (cursor.moveToFirst()) {
filePath = cursor.getString(columnIndex);
}
cursor.close();
return filePath;
} else {
// image pick from gallery
return getRealPathFromURI_BelowAPI11(context,uri)
}
}
EDITAR: si está tratando de obtener la ruta de imagen del archivo en una tarjeta SD externa en una versión superior, entonces verifique mi pregunta