Join FlipAndroid.COM Telegram Group: https://t.me/joinchat/F_aqThGkhwcLzmI49vKAiw


Android obtener el camino real por Uri.getPath ()

Estoy intentando conseguir la 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 un dato, que contiene Uri. Parece que:

 content://media/external/images/1 

¿Cómo puedo convertir esta ruta a una real (como ' /sdcard/image.png ')?

Gracias

  • Selecciona varias imágenes de la galería de Android
  • Android elige la imagen de la galería que muestra el error de memoria
  • Puntos de navegación similares a iPhone para Android
  • 8 Solutions collect form web for “Android obtener el camino real por Uri.getPath ()”

    ¿Es realmente necesario para que usted consiga un camino físico?
    Por ejemplo, ImageView.setImageURI() y ContentResolver.openInputStream() permiten acceder al contenido de un archivo sin conocer su ruta real.

    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á obsoleto, por lo que no lo managedQuery() .

    Última edición: Mejora. Debemos cerrar el cursor !!

    @Rene Juuse – arriba en comentarios … Gracias por este enlace!

    . El código para obtener el camino real es un poco diferente de un SDK a otro por lo que a continuación tenemos tres métodos que se ocupa de diferentes SDK.

    GetRealPathFromURI_API19 (): devuelve la ruta real para la API 19 (o superior pero no probada) getRealPathFromURI_API11to18 (): devuelve la ruta real para la API 11 a la API 18 getRealPathFromURI_below11 (): devuelve la ruta real para la API inferior a 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: http://hmkcode.com/android-display-selected-image-and-its-real-path/


    ACTUALIZACIÓN 2016 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 sólo puede utilizar 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 de la galería, si elige de la galería que tiene un cajón con los álbumes y sólo mostrar archivos locales)

    Nota Esta es una mejora en la respuesta @ user3516549 y lo he comprobado en Moto G3 con Android 6.0.1
    Tengo este problema así que he intentado la respuesta de @ user3516549 pero en algunos casos no estaba funcionando correctamente. He encontrado que en Android 6.0 (o superior) cuando comenzamos la imagen de la galería de selección de intención, a continuación, una pantalla se abrirá que muestra imágenes recientes cuando el usuario seleccione la imagen de esta lista vamos a obtener 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 vez de reciente entonces conseguiremos uri como

     content://media/external/images/media/52530 

    Así que tengo manejarlo 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) } } 

    EDIT: si usted está intentando conseguir la trayectoria de la imagen del archivo en sdcard externo en versión más alta después comprueba mi pregunta

    EDIT: Utilice esta solución aquí: https://stackoverflow.com/a/20559175/2033223 Funciona perfecto!

    Primero de, gracias por su solución @luizfelipetx

    Cambié su 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 los documentos y la imagen, dependiendo, si la imagen viene de 'recents', 'galería' o lo que sea. Así que extraigo el ID de la imagen primero antes de buscarlo.

    Hii aquí es 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 resto de 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); } 

    Como saben los programadores reales, no hay un camino real .

    Un Uri con un esquema de content es un mango opaco a algún contenido. Si ese Uri representa contenido ContentResolver , puede utilizar ContentResolver y openInputStream() para obtener un InputStream en ese contenido. De manera similar, un Uri con un esquema http o https no representa un archivo local, y necesitaría usar una API de cliente HTTP para acceder a él.

    Sólo un Uri con un esquema de file identifica un archivo (salvo los casos en los que el archivo fue movido o eliminado después de crear el Uri ).

    Lo que la gente estúpida hace es intentar derivar una trayectoria del sistema de archivos intentando descodificar el contenido del Uri , posiblemente acoplado con los hechizos del bastidor para invocar $EVIL_DEITY . En el mejor de los casos, esto será poco fiable, por tres razones:

    1. Las reglas para decodificar los valores de Uri pueden cambiar con el tiempo, como con versiones de versiones de Android, ya que la estructura del Uri representa un detalle de implementación, no una interfaz

    2. Incluso si obtiene una ruta de sistema de archivos, es posible que no tenga derechos para acceder al archivo

    3. No todos los valores Uri pueden ser descodificados a través de algoritmos fijos, ya que muchas aplicaciones tienen sus propios proveedores y pueden apuntar a todo, desde activos a columnas BLOB a datos que necesitan ser transmitidos desde Internet

    Ningún desarrollador con ningún sentido común va por este camino.

    Si tiene alguna API limitada que requiere un archivo, utilice InputStream de openInputStream() para realizar una copia de dicho contenido. Si se trata de una copia transitoria (por ejemplo, se utiliza para una operación de carga de archivos y, a continuación, se elimina) o una copia duradera (por ejemplo, para una función de "importación" de su aplicación) depende de usted.

    Esto me ayudó a obtener uri de Galería y convertirlo a un archivo para la carga múltiple

     File file = FileUtils.getFile(this, fileUri); 

    https://github.com/iPaulPro/aFileChooser/blob/master/aFileChooser/src/com/ipaulpro/afilechooser/utils/FileUtils.java

    FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.