Получить имя файла и путь из URI из mediastore
у меня есть onActivityResult
возврат из выбора изображения mediastore, который я могу получить URI для изображения, используя следующее:
Uri selectedImage = data.getData();
преобразование этого в строку дает следующее:
content://media/external/images/media/47
или путь дает:
/external/images/media/47
однако я не могу найти способ преобразовать это в абсолютный путь, так как я хочу загрузить изображение в растровое изображение без необходимости копировать его где-то. Я знаю, что это можно сделать с помощью URI и распознавателя содержимого, но это кажется, сломается при перезагрузке телефона, я думаю 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;
}
хорошие существующие ответы, некоторые из которых я привык придумывать самостоятельно:
Я должен получить путь от URIs и получить 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
отлично работает для меня фиксированный код из этого в должности:
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;
}