Obtenir le nom du fichier et le chemin depuis l’URI de mediastore

J’ai un onActivityResult renvoyant d’une sélection d’image de médiastore que je peux obtenir un URI pour une image en utilisant ce qui suit:

 Uri selectedImage = data.getData(); 

Convertir ceci en chaîne donne ceci:

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

Ou à un chemin donne:

 /external/images/media/47 

Cependant, je n’arrive pas à trouver un moyen de convertir cela en un chemin absolu, car je veux charger l’image dans un bitmap sans avoir à la copier quelque part. Je sais que cela peut être fait en utilisant l’URI et le résolveur de contenu, mais cela semble rompre au redémarrage du téléphone, je suppose que MediaStore ne garde pas la même numérotation entre les redémarrages.

Au-dessous de l’API 19, utilisez ce code pour obtenir le chemin de fichier depuis l’URI:

 public Ssortingng getRealPathFromURI(Context context, Uri contentUri) { Cursor cursor = null; try { Ssortingng[] 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.getSsortingng(column_index); } finally { if (cursor != null) { cursor.close(); } } } 

Juste une simple mise à jour sur la première réponse: mActivity.managedQuery() est maintenant obsolète. J’ai mis à jour le code avec la nouvelle méthode.

 private Ssortingng getRealPathFromURI(Uri contentUri) { Ssortingng[] 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(); Ssortingng result = cursor.getSsortingng(column_index); cursor.close(); return result; } 

source de dev Android

N’essayez pas de trouver un uri dans le système de fichiers, c’est lent à aller chercher des choses dans la firebase database.

Vous pouvez obtenir un bitmap d’un uri en donnant un stream d’entrée à la fabrique, comme si vous donniez un fichier à la fabrique:

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

Pour tous les version j’ai fait cette méthode qui obtient un vrai chemin de uri

  @SuppressLint("NewApi") public static Ssortingng getFilePath(Context context, Uri uri) throws URISyntaxException { Ssortingng selection = null; Ssortingng[] 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 Ssortingng docId = DocumentsContract.getDocumentId(uri); final Ssortingng[] split = docId.split(":"); return Environment.getExternalStorageDirectory() + "/" + split[1]; } else if (isDownloadsDocument(uri)) { final Ssortingng id = DocumentsContract.getDocumentId(uri); uri = ContentUris.withAppendedId( Uri.parse("content://downloads/public_downloads"), Long.valueOf(id)); } else if (isMediaDocument(uri)) { final Ssortingng docId = DocumentsContract.getDocumentId(uri); final Ssortingng[] split = docId.split(":"); final Ssortingng 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 Ssortingng[]{ split[1] }; } } if ("content".equalsIgnoreCase(uri.getScheme())) { Ssortingng[] 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.getSsortingng(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()); } 

Voici mon exemple pour obtenir un nom de fichier, à partir d’URI comme fichier: // … et contenu: // …. Cela fonctionne pour moi non seulement avec Android MediaStore mais aussi avec une application tierce comme EzExplorer.

 public static Ssortingng getFileNameByUri(Context context, Uri uri) { Ssortingng fileName="unknown";//default fileName Uri filePathUri = uri; if (uri.getScheme().toSsortingng().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.getSsortingng(column_index)); fileName = filePathUri.getLastPathSegment().toSsortingng(); } } else if (uri.getScheme().compareTo("file")==0) { fileName = filePathUri.getLastPathSegment().toSsortingng(); } else { fileName = fileName+"_"+filePathUri.getLastPathSegment(); } return fileName; } 

Bonnes réponses existantes, dont certaines dont je me suis servi:

Je dois trouver le chemin des URI et obtenir l’URI des chemins, et Google a du mal à faire la différence, donc pour tous ceux qui ont le même problème (par exemple, obtenir la vignette du MediaStore d’une vidéo dont vous avez déjà l’emplacement physique) avoir). L’ancien:

 /** * 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 ssortingng */ private Ssortingng getFilePathFromContentUri(Uri selectedVideoUri, ContentResolver contentResolver) { Ssortingng filePath; Ssortingng[] filePathColumn = {MediaColumns.DATA}; Cursor cursor = contentResolver.query(selectedVideoUri, filePathColumn, null, null, null); cursor.moveToFirst(); int columnIndex = cursor.getColumnIndex(filePathColumn[0]); filePath = cursor.getSsortingng(columnIndex); cursor.close(); return filePath; } 

Le dernier (que je fais pour les vidéos, mais peut également être utilisé pour les fichiers audio ou les fichiers ou d’autres types de contenu stocké en substituant MediaStore.Audio (etc) pour 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(Ssortingng 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.toSsortingng()); Ssortingng[] 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 Ssortingng[] { 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; } 

Fondamentalement, la colonne DATA de MediaStore (ou de la sous-section que vous interrogez) stocke le chemin du fichier. Vous pouvez donc utiliser ce que vous savez pour rechercher ce champ DATA ou utiliser le champ pour rechercher tout ce que vous voulez. .

J’utilise ensuite le Scheme ci-dessus pour déterminer ce qu’il faut faire avec mes données:

  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); Ssortingng filePath; Ssortingng 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/")){ Ssortingng sortingmmedFilePath = filePath.subssortingng("/mimetype/".length()); filePath = sortingmmedFilePath.subssortingng(sortingmmedFilePath.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.toSsortingng()); return false; } return true; } 

Aucune de ces réponses n’a fonctionné pour moi dans tous les cas. Je devais aller directement à la documentation de Google https://developer.android.com/guide/topics/providers/document-provider.html sur ce sujet et trouvé cette méthode utile:

 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; } 

Vous pouvez utiliser ce bitmap pour l’afficher dans une vue d’image.

Solution pour ceux qui ont des problèmes après avoir déménagé à KitKat:

“Cela permettra d’obtenir le chemin du fichier à partir de MediaProvider, DownloadsProvider et ExternalStorageProvider, tout en retombant sur la méthode non officielle ContentProvider” https://stackoverflow.com/a/20559175/690777

Puisque managedQuery est obsolète, vous pouvez essayer:

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

Ici, je vais vous montrer comment créer un bouton BROWSE, qui, lorsque vous cliquerez, ouvrira la carte SD, vous sélectionnerez un fichier et vous obtiendrez ainsi le nom du fichier et le chemin du fichier sélectionné. un:

Un bouton que vous allez toucher

 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 fonction qui obtiendra le nom du fichier résultant et le chemin du fichier

 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().toSsortingng().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.getSsortingng(column_index)); Ssortingng file_name = filePathUri.getLastPathSegment().toSsortingng(); Ssortingng file_path=filePathUri.getPath(); Toast.makeText(this,"File Name & PATH are:"+file_name+"\n"+file_path, Toast.LENGTH_LONG).show(); } } } } } 

Après avoir obtenu une image à partir de la galerie, transmettez simplement l’URI dans la méthode ci-dessous uniquement pour Android 4.4 (KitKat):

 public Ssortingng getPath(Uri contentUri) {// Will return "image:x*" Ssortingng wholeID = DocumentsContract.getDocumentId(contentUri); // Split at colon, use second item in the array Ssortingng id = wholeID.split(":")[1]; Ssortingng[] column = { MediaStore.Images.Media.DATA }; // Where id is equal to Ssortingng sel = MediaStore.Images.Media._ID + "=?"; Cursor cursor = getContentResolver().query( MediaStore.Images.Media.EXTERNAL_CONTENT_URI, column, sel, new Ssortingng[] { id }, null); Ssortingng filePath = ""; int columnIndex = cursor.getColumnIndex(column[0]); if (cursor.moveToFirst()) { filePath = cursor.getSsortingng(columnIndex); } cursor.close(); return filePath; } 

Cette solution fonctionne pour tous les cas:

Dans certains cas, il est trop difficile d’obtenir le chemin depuis l’URL. Alors pourquoi avez-vous besoin du chemin? Pour copier le fichier à un autre endroit? Vous n’avez pas besoin du chemin.

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

essayez ce chemin d’access au fichier image depuis Uri

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

Ici vous obtenez le nom du fichier

 Ssortingng[] projection = {MediaStore.MediaColumns.DISPLAY_NAME}; Uri uri = data.getData(); Ssortingng 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.getSsortingng(0); } } finally { metaCursor.close(); } } 

Simple et facile. Vous pouvez le faire depuis l’URI comme ci-dessous!

 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 .getSsortingng(column_index)); Ssortingng video_name = filePathUri.getLastPathSegment().toSsortingng(); Ssortingng file_path=filePathUri.getPath(); Log.i("TAG", video_name + "\b" file_path); } } 

API 19 et supérieur , le chemin de fichier image d’Uri fonctionne parfaitement. Je vérifie également cette dernière API Oreo 27 .

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

Version légèrement modifiée de @PercyPercy – elle ne lance pas et renvoie simplement null si quelque chose ne va pas :

 public Ssortingng getPathFromMediaUri(Context context, Uri uri) { Ssortingng result = null; Ssortingng[] 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.getSsortingng(col); cursor.close(); return result; } 

En tant que module complémentaire, si vous avez besoin de voir si un fichier existe avant d’essayer d’ouvrir un stream d’entrée, vous pouvez utiliser le DocumentsContract.

(Code Kotlin)

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

Puisque les réponses ci-dessus n’ont pas fonctionné pour moi, voici la solution qui a fonctionné pour moi:

Pour les niveaux API> 19 et < = 19.

Cette méthode couvre tous les cas pour obtenir un fichierPath 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 Ssortingng 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 Ssortingng docId = DocumentsContract.getDocumentId(uri); final Ssortingng[] split = docId.split(":"); final Ssortingng 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 Ssortingng 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 Ssortingng docId = DocumentsContract.getDocumentId(uri); final Ssortingng[] split = docId.split(":"); final Ssortingng 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 Ssortingng selection = "_id=?"; final Ssortingng[] selectionArgs = new Ssortingng[] { 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; } 

Essaye ça

Cependant, si vous rencontrez le problème pour obtenir le vrai chemin, vous pouvez essayer mes réponses. Les réponses ci-dessus ne m’ont pas aidé.

Explication : – Cette méthode récupère l’URI, puis vérifie le niveau de l’API de votre appareil Android, après quoi, selon le niveau de l’API, il générera le chemin réel. Le code pour générer la méthode du chemin réel est différent selon les niveaux de l’API.

  1. méthode pour obtenir le chemin réel d’URI

     @SuppressLint("ObsoleteSdkInt") public Ssortingng getPathFromURI(Uri uri){ Ssortingng 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{ Ssortingng wholeID = DocumentsContract.getDocumentId(uri); // Split at colon, use second item in the array Ssortingng id = wholeID.split(":")[1]; Ssortingng[] column = { MediaStore.Images.Media.DATA }; // where id is equal to Ssortingng sel = MediaStore.Images.Media._ID + "=?"; Cursor cursor = getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, column, sel, new Ssortingng[]{ id }, null); int columnIndex = 0; if (cursor != null) { columnIndex = cursor.getColumnIndex(column[0]); if (cursor.moveToFirst()) { realPath = cursor.getSsortingng(columnIndex); } cursor.close(); } } return realPath; } 
  2. Utilisez cette méthode comme celle-ci

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

Sortie:-

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

Travailler parfaitement pour moi code fixe de cet article :

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

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