Получить имя файла и путь из Ури из Система хранения mediastore
у меня есть onActivityResult
возвращаясь из выбора изображения mediastore, который я могу получить URI для изображения, используя следующее:
Uri selectedImage = data.getData();
преобразование этого в строку дает следующее:
content://media/external/images/media/47
или в путь дает:
/external/images/media/47
однако я не могу найти способ преобразовать это в абсолютный путь, так как я хочу загрузить изображение в растровое изображение, не копируя его где-то. Я знаю, что это можно сделать с помощью URI и Content resolver, но это кажется, ломается при перезагрузке телефона, я думаю MediaStore
не сохраняет свою нумерацию одинаковой между перезагрузками.
23 ответа:
ниже API 19 используйте этот код, чтобы получить путь к файлу из 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(); } } }
простое обновление на первый ответ:
mActivity.managedQuery()
теперь устарел. Я обновил код с помощью нового метода.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; }
Не пытайтесь найти uri в файловой системе, это медленно, чтобы посмотреть вещи в базе данных.
вы можете получить растровое изображение из uri, предоставив входной поток на фабрику, как вы даете файл на фабрику:
InputStream is = getContentResolver().openInputStream(uri); Bitmap bitmap = BitmapFactory.decodeStream(is); is.close();
для всех версий я сделал этот метод, который получает реальный путь от 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()); }
вот мой пример получения имени файла из URI like file://... и содержание://... . Это работает для меня не только с Android MediaStore, но и с третьей частью приложения, как 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; }
хорошие существующие ответы, некоторые из которых я привык придумывать самостоятельно:
Я должен получить путь от URI и получить URI от путей, и Google трудно сказать разницу так для тех, кто имеет ту же проблему (например, чтобы получить миниатюру из
MediaStore
видео, физическое местоположение которого у вас уже есть). Первый:/** * 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; }
последний (который я делаю для видео, но также может использоваться для аудио или файлов или других типов сохраненного контента подставляя система хранения mediastore.Аудио (и т. д.) Для система хранения mediastore.Видео):
/** * 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; }
в основном
ни один из этих ответов не работал для меня во всех случаях. Мне пришлось перейти непосредственно к документации Googlehttps://developer.android.com/guide/topics/providers/document-provider.html на эту тему и нашел этот полезный метод:
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; }
вы можете использовать эту картинку для отображения его в виде изображения.
решение для тех, у кого есть проблемы после переезда в KitKat:
"Это позволит получить путь к файлу из MediaProvider, DownloadsProvider и ExternalStorageProvider, возвращаясь к неофициальному методу ContentProvider"https://stackoverflow.com/a/20559175/690777
поскольку managedQuery был устаревшим, вы можете попробовать:
CursorLoader cursorLoader = new CursorLoader(context, uri, proj, null, null, null); Cursor cursor = cursorLoader.loadInBackground();
здесь я покажу вам, как создать кнопку обзора, которая, когда вы нажмете, откроет SD-карту, вы выберете файл, и в результате вы получите имя файла и путь к файлу выбранного:
кнопка, которую вы нажмете
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); } });
функция, которая получит в результате имя файла и путь к файлу
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(); } } } } }
после получения изображения из галереи, просто передайте URI в методе ниже только для 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; }
Это решение работает для каждого случая:
это слишком трудно в некоторых случаях получить путь от URL. Тогда зачем вам нужен путь? Скопировать файл в другое место? Вам не нужен путь.
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()); } }
попробуйте это получить путь к файлу изображения из 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); }
здесь вы получаете имя файла
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(); } }
просто и легко. Вы можете сделать это из URI, как показано ниже!
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); } }
слегка измененная версия @PercyPercy - она не бросает, а просто возвращает null, если что-то пойдет не так:
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; }
API 19 и выше, путь к файлу изображения из Uri отлично работает. Я также проверяю эту последнюю 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; }
Я сделал так:
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;
Попробуй Такое
тем не менее, если вы получаете проблему, чтобы получить реальный путь, вы можете попробовать мои ответы. Выше ответы мне не помогли.
объяснение: - этот метод получает URI, а затем проверить уровень API вашего Android устройства после этого в соответствии с уровнем API он будет генерировать реальный путь. код для генерации метода реального пути отличается в зависимости от уровней API.
метод, чтобы получить реальный путь от Ури
@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; }
используйте этот метод вот так
Log.e(TAG, "getRealPathFromURI: "+getPathFromURI(your_selected_uri) );
выход:-
04-06 12:39:46.993 6138-6138/com.приложение.qtm E / tag: getRealPathFromURI: / хранение / эмуляция/0/видео / avengers_infinity_war_4k_8k-7680x4320.jpg
отлично работает для меня фиксированный код из этого 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; }
в качестве дополнения, Если вам нужно увидеть, существует ли файл, прежде чем пытаться открыть входной поток, вы можете использовать DocumentsContract.
(код Котлин)
var iStream = null if(DocumentsContract.isDocumentUri(context,myUri)) { val pfd: ParcelFileDescriptor? = context.contentResolver.openFileDescriptor( myUri, "r") ?: return null iStream = ParcelFileDescriptor.AutoCloseInputStream(pfd) }
поскольку приведенные выше ответы не работали для меня, вот решение, которое сработало для меня:
для обоих > 19 и
этот метод охватывает все случаи, чтобы получить путь к файлу из 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; }