studio real images from content android uri absolute-path mediastore

android - real - Obtener nombre de archivo y ruta de URI de mediastore



get real path from uri android (23)

Tengo un onActivityResult regresa de una selección de imágenes de mediastore, que puedo obtener un URI para una imagen usando lo siguiente:

Uri selectedImage = data.getData();

Convertir esto a una cadena da esto:

content://media/external/images/media/47

O a un camino da:

/external/images/media/47

Sin embargo, parece que no puedo encontrar una manera de convertir esto en una ruta absoluta, ya que quiero cargar la imagen en un mapa de bits sin tener que copiarla en algún lugar. Sé que esto se puede hacer usando el URI y el sistema de resolución de contenido, pero esto parece irrumpir en el reinicio del teléfono, supongo que MediaStore no mantiene su número igual entre los reinicios.


Prueba esto

Aún así, si está obteniendo el problema para obtener el camino 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 API de su dispositivo Android después de eso, según el nivel de API, generará la ruta real. El código para generar el método de ruta real es diferente según los niveles de API.

  1. Método para obtener la ruta real de URI

    @SuppressLint("ObsoleteSdkInt") public String getPathFromURI(Uri uri){ String realPath=""; // SDK < API11 if (Build.VERSION.SDK_INT < 11) { String[] proj = { MediaStore.Images.Media.DATA }; @SuppressLint("Recycle") Cursor cursor = getContentResolver().query(uri, proj, null, null, null); int column_index = 0; String result=""; if (cursor != null) { column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); realPath=cursor.getString(column_index); } } // SDK >= 11 && SDK < 19 else if (Build.VERSION.SDK_INT < 19){ String[] proj = { MediaStore.Images.Media.DATA }; CursorLoader cursorLoader = new CursorLoader(this, uri, proj, null, null, null); Cursor cursor = cursorLoader.loadInBackground(); if(cursor != null){ int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); cursor.moveToFirst(); realPath = cursor.getString(column_index); } } // SDK > 19 (Android 4.4) else{ 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 = getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, column, sel, new String[]{ id }, null); int columnIndex = 0; if (cursor != null) { columnIndex = cursor.getColumnIndex(column[0]); if (cursor.moveToFirst()) { realPath = cursor.getString(columnIndex); } cursor.close(); } } return realPath; }

  2. Usa este método como este

    Log.e(TAG, "getRealPathFromURI: "+getPathFromURI(your_selected_uri) );

Salida:-

04-06 12: 39: 46.993 6138-6138 / com.app.qtm E / tag: getRealPathFromURI: /storage/emulated/0/Video/avengers_infinity_war_4k_8k-7680x4320.jpg


intente esto obtener la ruta del archivo de imagen de Uri

public void getImageFilePath(Context context, Uri uri) { Cursor cursor = context.getContentResolver().query(uri, null, null, null, null); cursor.moveToFirst(); String image_id = cursor.getString(0); image_id = image_id.substring(image_id.lastIndexOf(":") + 1); cursor.close(); cursor = context.getContentResolver().query(android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI, null, MediaStore.Images.Media._ID + " = ? ", new String[]{image_id}, null); cursor.moveToFirst(); String path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA)); cursor.close(); upLoadImageOrLogo(path); }


Aquí está mi ejemplo de obtener el nombre del archivo, desde URI como archivo: // ... y contenido: // .... Funciona para mí, no solo con Android MediaStore, sino también con aplicaciones de terceros como EzExplorer.

public static String getFileNameByUri(Context context, Uri uri) { String fileName="unknown";//default fileName Uri filePathUri = uri; if (uri.getScheme().toString().compareTo("content")==0) { Cursor cursor = context.getContentResolver().query(uri, null, null, null, null); if (cursor.moveToFirst()) { int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);//Instead of "MediaStore.Images.Media.DATA" can be used "_data" filePathUri = Uri.parse(cursor.getString(column_index)); fileName = filePathUri.getLastPathSegment().toString(); } } else if (uri.getScheme().compareTo("file")==0) { fileName = filePathUri.getLastPathSegment().toString(); } else { fileName = fileName+"_"+filePathUri.getLastPathSegment(); } return fileName; }


Aquí tienes el nombre del archivo.

String[] projection = {MediaStore.MediaColumns.DISPLAY_NAME}; Uri uri = data.getData(); String fileName = null; ContentResolver cr = getActivity().getApplicationContext().getContentResolver(); Cursor metaCursor = cr.query(uri, projection, null, null, null); if (metaCursor != null) { try { if (metaCursor.moveToFirst()) { fileName = metaCursor.getString(0); } } finally { metaCursor.close(); } }


Aquí voy a mostrarles cómo crear un botón de BROWSE, que cuando haga clic, abrirá la tarjeta SD, seleccionará un archivo y, como resultado, obtendrá el nombre del archivo y la ruta del archivo seleccionado. uno:

Un botón que pulsará.

browse.setOnClickListener(new OnClickListener() { public void onClick(View v) { Intent intent = new Intent(); intent.setAction(Intent.ACTION_PICK); Uri startDir = Uri.fromFile(new File("/sdcard")); startActivityForResult(intent, PICK_REQUEST_CODE); } });

La función que obtendrá el nombre del archivo resultante y la ruta del archivo.

protected void onActivityResult(int requestCode, int resultCode, Intent intent) { if (requestCode == PICK_REQUEST_CODE) { if (resultCode == RESULT_OK) { Uri uri = intent.getData(); if (uri.getScheme().toString().compareTo("content")==0) { Cursor cursor =getContentResolver().query(uri, null, null, null, null); if (cursor.moveToFirst()) { int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);//Instead of "MediaStore.Images.Media.DATA" can be used "_data" Uri filePathUri = Uri.parse(cursor.getString(column_index)); String file_name = filePathUri.getLastPathSegment().toString(); String file_path=filePathUri.getPath(); Toast.makeText(this,"File Name & PATH are:"+file_name+"/n"+file_path, Toast.LENGTH_LONG).show(); } } } } }


Buenas respuestas existentes, algunas de las cuales solía encontrar las mías:

Tengo que obtener la ruta de los URI y obtener la URI de las rutas, y Google tiene dificultades para decir la diferencia, así que para cualquier persona que tenga el mismo problema (por ejemplo, para obtener la miniatura del MediaStore de un video cuya ubicación física ya tiene). tener). El primero

/** * Gets the corresponding path to a file from the given content:// URI * @param selectedVideoUri The content:// URI to find the file path from * @param contentResolver The content resolver to use to perform the query. * @return the file path as a string */ private String getFilePathFromContentUri(Uri selectedVideoUri, ContentResolver contentResolver) { String filePath; String[] filePathColumn = {MediaColumns.DATA}; Cursor cursor = contentResolver.query(selectedVideoUri, filePathColumn, null, null, null); cursor.moveToFirst(); int columnIndex = cursor.getColumnIndex(filePathColumn[0]); filePath = cursor.getString(columnIndex); cursor.close(); return filePath; }

Este último (lo que hago para los videos, pero también se puede usar para audio o archivos u otros tipos de contenido almacenado sustituyendo MediaStore.Audio (etc.) por MediaStore.Video):

/** * Gets the MediaStore video ID of a given file on external storage * @param filePath The path (on external storage) of the file to resolve the ID of * @param contentResolver The content resolver to use to perform the query. * @return the video ID as a long */ private long getVideoIdFromFilePath(String filePath, ContentResolver contentResolver) { long videoId; Log.d(TAG,"Loading file " + filePath); // This returns us content://media/external/videos/media (or something like that) // I pass in "external" because that''s the MediaStore''s name for the external // storage on my device (the other possibility is "internal") Uri videosUri = MediaStore.Video.Media.getContentUri("external"); Log.d(TAG,"videosUri = " + videosUri.toString()); String[] projection = {MediaStore.Video.VideoColumns._ID}; // TODO This will break if we have no matching item in the MediaStore. Cursor cursor = contentResolver.query(videosUri, projection, MediaStore.Video.VideoColumns.DATA + " LIKE ?", new String[] { filePath }, null); cursor.moveToFirst(); int columnIndex = cursor.getColumnIndex(projection[0]); videoId = cursor.getLong(columnIndex); Log.d(TAG,"Video ID is " + videoId); cursor.close(); return videoId; }

Básicamente, la columna DATA de MediaStore (o la subsección de la que esté consultando) almacena la ruta del archivo, por lo que puede usar lo que sabe para buscar ese campo de DATA , o usar el campo para buscar lo que desee. .

Luego utilizo el Scheme como se Scheme arriba para averiguar qué hacer con mis datos:

private boolean getSelectedVideo(Intent imageReturnedIntent, boolean fromData) { Uri selectedVideoUri; //Selected image returned from another activity // A parameter I pass myself to know whether or not I''m being "shared via" or // whether I''m working internally to my app (fromData = working internally) if(fromData){ selectedVideoUri = imageReturnedIntent.getData(); } else { //Selected image returned from SEND intent // which I register to receive in my manifest // (so people can "share via" my app) selectedVideoUri = (Uri)getIntent().getExtras().get(Intent.EXTRA_STREAM); } Log.d(TAG,"SelectedVideoUri = " + selectedVideoUri); String filePath; String scheme = selectedVideoUri.getScheme(); ContentResolver contentResolver = getContentResolver(); long videoId; // If we are sent file://something or content://org.openintents.filemanager/mimetype/something... if(scheme.equals("file") || (scheme.equals("content") && selectedVideoUri.getEncodedAuthority().equals("org.openintents.filemanager"))){ // Get the path filePath = selectedVideoUri.getPath(); // Trim the path if necessary // openintents filemanager returns content://org.openintents.filemanager/mimetype//mnt/sdcard/xxxx.mp4 if(filePath.startsWith("/mimetype/")){ String trimmedFilePath = filePath.substring("/mimetype/".length()); filePath = trimmedFilePath.substring(trimmedFilePath.indexOf("/")); } // Get the video ID from the path videoId = getVideoIdFromFilePath(filePath, contentResolver); } else if(scheme.equals("content")){ // If we are given another content:// URI, look it up in the media provider videoId = Long.valueOf(selectedVideoUri.getLastPathSegment()); filePath = getFilePathFromContentUri(selectedVideoUri, contentResolver); } else { Log.d(TAG,"Failed to load URI " + selectedVideoUri.toString()); return false; } return true; }


Como complemento, si necesita ver si un archivo existe antes de intentar abrir una secuencia de entrada, puede usar DocumentsContract.

(Código Kotlin)

var iStream = null if(DocumentsContract.isDocumentUri(context,myUri)) { val pfd: ParcelFileDescriptor? = context.contentResolver.openFileDescriptor( myUri, "r") ?: return null iStream = ParcelFileDescriptor.AutoCloseInputStream(pfd) }


Dado que las respuestas anteriores no funcionaron para mí, aquí está la solución que funcionó para mí:

Para ambos> 19 y <= 19 niveles de API.

Este método cubre todos los casos para obtener filePath de uri

/** * Get a file path from a Uri. This will get the the path for Storage Access * Framework Documents, as well as the _data field for the MediaStore and * other file-based ContentProviders. * * @param context The activity. * @param uri The Uri to query. * @author paulburke */ public static String getPath(final Context context, final Uri uri) { // DocumentProvider if ( Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && DocumentsContract.isDocumentUri(context, uri)) { // ExternalStorageProvider if (isExternalStorageDocument(uri)) { final String docId = DocumentsContract.getDocumentId(uri); final String[] split = docId.split(":"); final String type = split[0]; if ("primary".equalsIgnoreCase(type)) { return Environment.getExternalStorageDirectory() + "/" + split[1]; }else{ Toast.makeText(context, "Could not get file path. Please try again", Toast.LENGTH_SHORT).show(); } } // DownloadsProvider else if (isDownloadsDocument(uri)) { final String id = DocumentsContract.getDocumentId(uri); final Uri contentUri = ContentUris.withAppendedId( Uri.parse("content://downloads/public_downloads"), Long.valueOf(id)); return getDataColumn(context, contentUri, null, null); } // MediaProvider else if (isMediaDocument(uri)) { final String docId = DocumentsContract.getDocumentId(uri); final String[] split = docId.split(":"); final String type = split[0]; Uri contentUri = null; if ("image".equals(type)) { contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; } else if ("video".equals(type)) { contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI; } else if ("audio".equals(type)) { contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; } else { contentUri = MediaStore.Files.getContentUri("external"); } final String selection = "_id=?"; final String[] selectionArgs = new String[] { split[1] }; return getDataColumn(context, contentUri, selection, selectionArgs); } } // MediaStore (and general) else if ("content".equalsIgnoreCase(uri.getScheme())) { return getDataColumn(context, uri, null, null); } // File else if ("file".equalsIgnoreCase(uri.getScheme())) { return uri.getPath(); } return null; }


Dado que managedQuery ha quedado en desuso, puede intentar:

CursorLoader cursorLoader = new CursorLoader(context, uri, proj, null, null, null); Cursor cursor = cursorLoader.loadInBackground();


Después de obtener una imagen de la galería, simplemente pase la URI en el método a continuación solo para Android 4.4 (KitKat):

public String getPath(Uri contentUri) {// Will return "image:x*" String wholeID = DocumentsContract.getDocumentId(contentUri); // 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 = getContentResolver().query( MediaStore.Images.Media.EXTERNAL_CONTENT_URI, column, sel, new String[] { id }, null); String filePath = ""; int columnIndex = cursor.getColumnIndex(column[0]); if (cursor.moveToFirst()) { filePath = cursor.getString(columnIndex); } cursor.close(); return filePath; }


Esta solución funciona para cada caso:

Es demasiado difícil en algunos casos obtener la ruta desde la URL. Entonces, ¿por qué necesitas el camino? ¿Para copiar el archivo en otro lugar? No necesitas el camino.

public void SavePhotoUri (Uri imageuri, String Filename){ File FilePath = context.getDir(Environment.DIRECTORY_PICTURES,Context.MODE_PRIVATE); try { Bitmap selectedImage = MediaStore.Images.Media.getBitmap(context.getContentResolver(), imageuri); String destinationImagePath = FilePath + "/" + Filename; FileOutputStream destination = new FileOutputStream(destinationImagePath); selectedImage.compress(Bitmap.CompressFormat.JPEG, 100, destination); destination.close(); } catch (Exception e) { Log.e("error", e.toString()); } }


He hecho así:

Uri queryUri = MediaStore.Files.getContentUri("external"); String columnData = MediaStore.Files.FileColumns.DATA; String columnSize = MediaStore.Files.FileColumns.SIZE; String[] projectionData = {MediaStore.Files.FileColumns.DATA}; String name = null; String size = null; Cursor cursor = getContentResolver().query(contentURI, null, null, null, null); if ((cursor != null)&&(cursor.getCount()>0)) { int nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME); int sizeIndex = cursor.getColumnIndex(OpenableColumns.SIZE); cursor.moveToFirst(); name = cursor.getString(nameIndex); size = cursor.getString(sizeIndex); cursor.close(); } if ((name!=null)&&(size!=null)){ String selectionNS = columnData + " LIKE ''%" + name + "'' AND " +columnSize + "=''" + size +"''"; Cursor cursorLike = getContentResolver().query(queryUri, projectionData, selectionNS, null, null); if ((cursorLike != null)&&(cursorLike.getCount()>0)) { cursorLike.moveToFirst(); int indexData = cursorLike.getColumnIndex(columnData); if (cursorLike.getString(indexData) != null) { result = cursorLike.getString(indexData); } cursorLike.close(); } } return result;


Ninguna de estas respuestas funcionó para mí en todos los casos. Tuve que ir directamente a la Documentación de Google https://developer.android.com/guide/topics/providers/document-provider.html sobre este tema y encontré este método útil:

private Bitmap getBitmapFromUri(Uri uri) throws IOException { ParcelFileDescriptor parcelFileDescriptor = getContentResolver().openFileDescriptor(uri, "r"); FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor(); Bitmap image = BitmapFactory.decodeFileDescriptor(fileDescriptor); parcelFileDescriptor.close(); return image; }

Puede utilizar este mapa de bits para mostrarlo en una vista de imagen.


No trates de encontrar un uri en el sistema de archivos, eso es lento para buscar cosas en la base de datos.

Puede obtener un mapa de bits de un uri dando un flujo de entrada a la fábrica como le da un archivo a la fábrica:

InputStream is = getContentResolver().openInputStream(uri); Bitmap bitmap = BitmapFactory.decodeStream(is); is.close();


Para Oreo

Uri uri = data.getData(); File file = new File(uri.getPath());//create path from uri final String[] split = file.getPath().split(":");//split the path. filePath = split[1];//assign it to a string(your choice).

Para todas las versiones debajo de Oreo, he creado este método que obtiene una ruta real desde uri.

@SuppressLint("NewApi") public static String getFilePath(Context context, Uri uri) throws URISyntaxException { String selection = null; String[] selectionArgs = null; // Uri is different in versions after KITKAT (Android 4.4), we need to if (Build.VERSION.SDK_INT >= 19 && DocumentsContract.isDocumentUri(context.getApplicationContext(), uri)) { if (isExternalStorageDocument(uri)) { final String docId = DocumentsContract.getDocumentId(uri); final String[] split = docId.split(":"); return Environment.getExternalStorageDirectory() + "/" + split[1]; } else if (isDownloadsDocument(uri)) { final String id = DocumentsContract.getDocumentId(uri); uri = ContentUris.withAppendedId( Uri.parse("content://downloads/public_downloads"), Long.valueOf(id)); } else if (isMediaDocument(uri)) { final String docId = DocumentsContract.getDocumentId(uri); final String[] split = docId.split(":"); final String type = split[0]; if ("image".equals(type)) { uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; } else if ("video".equals(type)) { uri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI; } else if ("audio".equals(type)) { uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; } selection = "_id=?"; selectionArgs = new String[]{ split[1] }; } } if ("content".equalsIgnoreCase(uri.getScheme())) { String[] projection = { MediaStore.Images.Media.DATA }; Cursor cursor = null; try { cursor = context.getContentResolver() .query(uri, projection, selection, selectionArgs, null); int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); if (cursor.moveToFirst()) { return cursor.getString(column_index); } } catch (Exception e) { } } else if ("file".equalsIgnoreCase(uri.getScheme())) { return uri.getPath(); } return null; } public static boolean isExternalStorageDocument(Uri uri) { return "com.android.externalstorage.documents".equals(uri.getAuthority()); } public static boolean isDownloadsDocument(Uri uri) { return "com.android.providers.downloads.documents".equals(uri.getAuthority()); } public static boolean isMediaDocument(Uri uri) { return "com.android.providers.media.documents".equals(uri.getAuthority()); }


Simple y fácil. ¡Puedes hacer esto desde la URI como abajo!

public void getContents(Uri uri) { Cursor vidCursor = getActivity.getContentResolver().query(uri, null, null, null, null); if (vidCursor.moveToFirst()) { int column_index = vidCursor .getColumnIndexOrThrow(MediaStore.Images.Media.DATA); Uri filePathUri = Uri.parse(vidCursor .getString(column_index)); String video_name = filePathUri.getLastPathSegment().toString(); String file_path=filePathUri.getPath(); Log.i("TAG", video_name + "/b" file_path); } }


Solo una actualización simple en la primera respuesta: mActivity.managedQuery() ahora está en desuso. He actualizado el código con el nuevo método.

private String getRealPathFromURI(Uri contentUri) { String[] proj = { MediaStore.Images.Media.DATA }; CursorLoader loader = new CursorLoader(mContext, contentUri, proj, null, null, null); Cursor cursor = loader.loadInBackground(); int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); cursor.moveToFirst(); String result = cursor.getString(column_index); cursor.close(); return result; }

fuente de Android android


Solución para aquellos que tienen problemas después de mudarse a KitKat:

"Esto obtendrá la ruta del archivo de MediaProvider, DownloadsProvider y ExternalStorageProvider, mientras que recurre al método no oficial de ContentProvider" https://.com/a/20559175/690777


Trabajando perfectamente para mi código fijo de este post :

public static String getRealPathImageFromUri(Uri uri) { String fileName =null; if (uri.getScheme().equals("content")) { try (Cursor cursor = MyApplication.getInstance().getContentResolver().query(uri, null, null, null, null)) { if (cursor.moveToFirst()) { fileName = cursor.getString(cursor.getColumnIndexOrThrow(ediaStore.Images.Media.DATA)); } } catch (IllegalArgumentException e) { Log.e(mTag, "Get path failed", e); } } return fileName; }


Versión ligeramente modificada de @PercyPercy: no se lanza y simplemente devuelve nulo si algo sale mal :

public String getPathFromMediaUri(Context context, Uri uri) { String result = null; String[] projection = { MediaStore.Images.Media.DATA }; Cursor cursor = context.getContentResolver().query(uri, projection, null, null, null); int col = cursor.getColumnIndex(MediaStore.Images.Media.DATA); if (col >= 0 && cursor.moveToFirst()) result = cursor.getString(col); cursor.close(); return result; }


Bitmap bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), uri);


A continuación, API 19 usa este código para obtener la ruta del archivo desde URI:

public String getRealPathFromURI(Context context, Uri contentUri) { Cursor cursor = null; try { String[] proj = { MediaStore.Images.Media.DATA }; 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); } finally { if (cursor != null) { cursor.close(); } } }


API 19 y superior , la ruta del archivo de imagen de Uri funciona perfectamente. También reviso este último Oreo API 27 .

public String getImageFilePath(Uri uri) { String path = null, image_id = null; Cursor cursor = getContentResolver().query(uri, null, null, null, null); if (cursor != null) { cursor.moveToFirst(); image_id = cursor.getString(0); image_id = image_id.substring(image_id.lastIndexOf(":") + 1); cursor.close(); } Cursor cursor = getContentResolver().query(android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI, null, MediaStore.Images.Media._ID + " = ? ", new String[]{image_id}, null); if (cursor!=null) { cursor.moveToFirst(); path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA)); cursor.close(); } return path; }