Ottieni il nome di file e il path da URI dal mediastore

Ho un onActivityResult ritorna da una selezione di immagini mediastore che posso get un URI per un'image utilizzando quanto segue:

 Uri selectedImage = data.getData(); 

La conversione in una string fornisce:

  • La galleria scrolla un'image alla volta
  • Android: Come posso albind un'image temporanea, generata a un'email?
  • È davvero imansible proteggere le applicazioni Android dall'inverso dell'inverso?
  • Cambiare l'orientamento dello schermo in Android senza ricaricare l'attività
  • Sviluppo di Android: Come sostituire una parte di un EditText con una parola chiave che è spannabile
  • Android 4.4 Stampa in PDF senza coinvolgimento dell'utente
  •  content://media/external/images/media/47 

    O ad un path dà:

     /external/images/media/47 

    Tuttavia non riesco a trovare un modo per trasformarlo in un path assoluto, in quanto voglio caricare l'image in una bitmap senza wherer copiare da qualche parte. So che questo può essere fatto utilizzando l'URI e il resolver del contenuto, ma questo sembra rompere il riavvio del telefono, suppongo che MediaStore non mantiene la stessa numerazione tra i riavvoti.

  • Come distriggersre CalendarView in un DataPicker?
  • Nascondi un ProgressDialog su Firebase su un dispositivo senza internet
  • Come faccio ad triggersre un'azione quando l'utente ha premuto l'inserimento?
  • Il video di YouTube incorporato in WebView non rispetta le impostazioni a schermo integer
  • Problemi con ListView all'interno di un PopupWindow
  • driver adb per usb di android per htc desiderio hd
  • 16 Solutions collect form web for “Ottieni il nome di file e il path da URI dal mediastore”

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

    Solo un semplice aggiornamento sulla prima risposta: mActivity.managedQuery() è ormai obsoleto. Ho aggiornato il codice con il nuovo metodo.

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

    android dev source

    Non cercare di trovare un uri nel filesystem, che è lento per andare a guardare le cose nel database.

    È ansible get una bitmap da un uri, fornendo un stream di input alla fabbrica, come si fornisce un file alla fabbrica:

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

    Per tutte le versioni ho fatto questo metodo che ottiene un path reale da 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()); } 

    Ecco il mio esempio di get il nome di file, da URI come file: // … e contenuto: // …. Funziona per me non solo con Android MediaStore ma anche con applicazioni di terza parte come 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; } 

    Buone risposte esistenti, alcune delle quali ho usato per arrivare al mio:

    Devo get il path da URI e get l'URI dai routes, e Google ha difficoltà a dire la differenza per tutti coloro che hanno lo stesso problema (per esempio, per get la miniatura di MediaStore di un video la cui posizione fisica è già avere). L'ex:

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

    Quest'ultimo (che faccio per i video, ma può anche essere usato per Audio o File o altri tipi di contenuti memorizzati sostituendo MediaStore.Audio (ecc.) Per 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; } 

    In sostanza, la colonna DATA di MediaStore (o di qualunque sottosezione di esso che stai cercando) memorizza il path del file, pertanto usi quello che sai per cercare quel field DATA o utilizza il field per cercare qualunque cosa desideri .

    Quindi poi utilizzare lo Scheme come sopra per capire cosa fare con i miei dati:

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

    Nessuna di queste risposte ha funzionato per me in tutti i casi. Dovevo andare direttamente alla documentazione di Google https://developer.android.com/guide/topics/providers/document-provider.html su questo argomento e ho trovato questo metodo 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; } 

    È ansible utilizzare questa bitmap per visualizzarla in una vista di image.

    Soluzione per coloro che hanno problemi dopo aver trasferito a KitKat:

    "Questo ottenerà il path di file da MediaProvider, DownloadsProvider e ExternalStorageProvider, ritornando al metodo ContentProvider non ufficiale" https://stackoverflow.com/a/20559175/690777

    Poiché ManagedQuery è stato deprecato, è ansible provare:

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

    Qui vi mostrerò come creare un button BROWSE che, quando cliccherai, aprirà la scheda SD, selezionerà un file e di conseguenza otterrà il nome del file e il path del file selezionato uno:

    Un button da colpire

     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 function che otterrà il nome del file e il path del file risultante

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

    Dopo aver ottenuto un'image dalla galleria, basta passare l'URI nel metodo riportto di seguito solo per 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 arrays 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; } 

    Questa soluzione funziona per each caso:

    È troppo difficile in alcuni casi get il path dall'URL. Allora perché hai bisogno del path? Per copiare il file in un altro luogo? Non hai bisogno del path.

     public void SavePhotoUri (Uri imageuri, String Filename){ File FilePath = new File(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()); } } 

    Versione leggermente modificata di @PercyPercy – non getta e restituisce solo nulla se qualcosa va storto :

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

    Qui si ottiene il nome del file

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

    Semplice e facile. Puoi farlo dall'URI proprio come qui sotto!

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

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

    L'Android è un fan Android di Google, tutto su telefoni Android, Android Wear, Android Dev e applicazioni Android Games e così via.