android получить реальный путь по Uri.getPath()
Я пытаюсь получить изображение из галереи.
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, "Select picture"), resultCode );
после того, как я вернулся из этой деятельности у меня есть данные, которые содержат Uri. Это выглядит так:
content://media/external/images/1
как я могу преобразовать этот путь в реальный (так же, как'/sdcard/image.png')?
спасибо
9 ответов:
это действительно необходимо для вас, чтобы получить физический путь?
Например,ImageView.setImageURI()иContentResolver.openInputStream()позволит вам получить доступ к содержимому файла, не зная его реальный путь.
вот что я делаю:
Uri selectedImageURI = data.getData(); imageFile = new File(getRealPathFromURI(selectedImageURI));и:
private String getRealPathFromURI(Uri contentURI) { String result; Cursor cursor = getContentResolver().query(contentURI, null, null, null, null); if (cursor == null) { // Source is Dropbox or other similar local file path result = contentURI.getPath(); } else { cursor.moveToFirst(); int idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA); result = cursor.getString(idx); cursor.close(); } return result; }Примечание:
managedQuery()метод устарел, поэтому я его не использую.последнее редактирование: улучшение. Мы должны закрыть курсор!!
@Rene Juuse-выше в комментариях... Спасибо за эту ссылку !
. код для получения реального пути немного отличается от одного SDK к другому, поэтому ниже мы имеем три метода, которые имеют дело с различными SDK.
getRealPathFromURI_API19 (): возвращает реальный путь для API 19 (или выше, но не протестирован) getRealPathFromURI_API11to18 (): возвращает реальный путь для API 11 в API 18 getRealPathFromURI_below11 (): возвращает реальный путь для API ниже 11
public class RealPathUtil { @SuppressLint("NewApi") public static String getRealPathFromURI_API19(Context context, Uri uri){ String filePath = ""; 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 = context.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, column, sel, new String[]{ id }, null); int columnIndex = cursor.getColumnIndex(column[0]); if (cursor.moveToFirst()) { filePath = cursor.getString(columnIndex); } cursor.close(); return filePath; } @SuppressLint("NewApi") public static String getRealPathFromURI_API11to18(Context context, Uri contentUri) { String[] proj = { MediaStore.Images.Media.DATA }; String result = null; CursorLoader cursorLoader = new CursorLoader( context, contentUri, proj, null, null, null); Cursor cursor = cursorLoader.loadInBackground(); if(cursor != null){ int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); cursor.moveToFirst(); result = cursor.getString(column_index); } return result; } public static String getRealPathFromURI_BelowAPI11(Context context, Uri contentUri){ String[] proj = { MediaStore.Images.Media.DATA }; Cursor 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); }шрифт:http://hmkcode.com/android-display-selected-image-and-its-real-path/
обновление 2016 марта
чтобы исправить все проблемы с путем изображений я пытаюсь создать пользовательскую галерею, как facebook и другие приложения. Это потому, что вы можете использовать только локальные файлы ( реальные файлы , а не виртуальные или временные), я решаю все проблемы с этой библиотекой.
https://github.com/nohana/Laevatein (эта библиотека, чтобы сделать снимок с камеры или выбрать из галереи , если вы выбираете из галереи у него есть ящик с альбомами и просто показать локальные файлы)
Примечание это улучшение в @user3516549 ответ и я должен проверить его на Moto G3 с Android 6.0.1
У меня есть эта проблема, поэтому я попытался ответить на @user3516549, но в некоторых случаях он не работал должным образом. Я обнаружил, что в Android 6.0(или выше) при запуске gallery image pick intent откроется экран, который показывает последние изображения, когда пользователь выбирает изображение из этого списка, мы получим uri какcontent://com.android.providers.media.documents/document/image%3A52530в то время как если пользователь выбирает галерея из выдвижного ящика вместо недавнего, то мы получим uri как
content://media/external/images/media/52530так что я должен справиться с этим в
getRealPathFromURI_API19()public static String getRealPathFromURI_API19(Context context, Uri uri) { String filePath = ""; if (uri.getHost().contains("com.android.providers.media")) { // Image pick from recent 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 = context.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, column, sel, new String[]{id}, null); int columnIndex = cursor.getColumnIndex(column[0]); if (cursor.moveToFirst()) { filePath = cursor.getString(columnIndex); } cursor.close(); return filePath; } else { // image pick from gallery return getRealPathFromURI_BelowAPI11(context,uri) } }EDIT: если вы пытаетесь получить путь к изображению файла во внешней sdcard в более высокой версии, то проверьте у меня вопрос
нет никакого реального пути.
A
Uriсcontentсхема является непрозрачным дескриптором для некоторого содержимого. Если чтоUriпредставляет собой открытый контент, вы можете использоватьContentResolverиopenInputStream()для полученияInputStreamна этот контент. Кроме того,Uriсhttpилиhttpsсхема не представляет локальный файл, и вам нужно будет использовать API HTTP-клиента для доступа к нему.только a
Uriсfileсхема идентифицирует файл (за исключением случаях, когда файл был перемещен или удален после ).что делают глупые люди, это пытаются получить путь к файловой системе, пытаясь декодировать содержимое
Uri, возможно, в сочетании с заклинаниями для вызова$EVIL_DEITY. В лучшем случае, это будет ненадежно, по трем причинам:
правила декодирования
Uriзначения могут меняться с течением времени, например, с выпусками версий Android, как структураUriпредставляет деталь реализации, а не интерфейсдаже если вы получаете путь к файловой системе, у вас может не быть прав доступа к файлу
не все
Uriзначения могут быть декодированы с помощью фиксированных алгоритмов, так как многие приложения имеют своих поставщиков, а те могут указать на все активыBLOBстолбцы для данных, которые должны быть переданы из интернетаесли у вас есть некоторые ограниченные API, что требуется файл, используйте
InputStreamСopenInputStream()создать копию этого контента. Является ли это временной копией (например, используется для операции загрузки файла, а затем удаляется) или прочной копией (например, для функции "импорт" вашего приложения) зависит от вас.
EDIT: Используйте это решение здесь:https://stackoverflow.com/a/20559175/2033223 Работает отлично!
во-первых, спасибо за ваше решение @luizfelipetx
Я немного изменил ваше решение. Это работает для меня:
public static String getRealPathFromDocumentUri(Context context, Uri uri){ String filePath = ""; Pattern p = Pattern.compile("(\d+)$"); Matcher m = p.matcher(uri.toString()); if (!m.find()) { Log.e(ImageConverter.class.getSimpleName(), "ID for requested image not found: " + uri.toString()); return filePath; } String imgId = m.group(); String[] column = { MediaStore.Images.Media.DATA }; String sel = MediaStore.Images.Media._ID + "=?"; Cursor cursor = context.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, column, sel, new String[]{ imgId }, null); int columnIndex = cursor.getColumnIndex(column[0]); if (cursor.moveToFirst()) { filePath = cursor.getString(columnIndex); } cursor.close(); return filePath; }Примечание: таким образом, мы получили документы и изображения, в зависимости от того, если изображение приходит из "recents", "галерея" или что-либо еще. Поэтому я сначала извлекаю идентификатор изображения, прежде чем искать его.
Hii вот мой полный код для получения изображения с камеры или galeery
/ / мое объявление переменной
protected static final int CAMERA_REQUEST = 0; protected static final int GALLERY_REQUEST = 1; Bitmap bitmap; Uri uri; Intent picIntent = null;/ / Onclick
if (v.getId()==R.id.image_id){ startDilog(); }/ / метод body
private void startDilog() { AlertDialog.Builder myAlertDilog = new AlertDialog.Builder(yourActivity.this); myAlertDilog.setTitle("Upload picture option.."); myAlertDilog.setMessage("Where to upload picture????"); myAlertDilog.setPositiveButton("Gallery", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { picIntent = new Intent(Intent.ACTION_GET_CONTENT,null); picIntent.setType("image/*"); picIntent.putExtra("return_data",true); startActivityForResult(picIntent,GALLERY_REQUEST); } }); myAlertDilog.setNegativeButton("Camera", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { picIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); startActivityForResult(picIntent,CAMERA_REQUEST); } }); myAlertDilog.show(); }/ / и все остальное
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode==GALLERY_REQUEST){ if (resultCode==RESULT_OK){ if (data!=null) { uri = data.getData(); BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; try { BitmapFactory.decodeStream(getContentResolver().openInputStream(uri), null, options); options.inSampleSize = calculateInSampleSize(options, 100, 100); options.inJustDecodeBounds = false; Bitmap image = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri), null, options); imageofpic.setImageBitmap(image); } catch (FileNotFoundException e) { e.printStackTrace(); } }else { Toast.makeText(getApplicationContext(), "Cancelled", Toast.LENGTH_SHORT).show(); } }else if (resultCode == RESULT_CANCELED) { Toast.makeText(getApplicationContext(), "Cancelled", Toast.LENGTH_SHORT).show(); } }else if (requestCode == CAMERA_REQUEST) { if (resultCode == RESULT_OK) { if (data.hasExtra("data")) { bitmap = (Bitmap) data.getExtras().get("data"); uri = getImageUri(YourActivity.this,bitmap); File finalFile = new File(getRealPathFromUri(uri)); imageofpic.setImageBitmap(bitmap); } else if (data.getExtras() == null) { Toast.makeText(getApplicationContext(), "No extras to retrieve!", Toast.LENGTH_SHORT) .show(); BitmapDrawable thumbnail = new BitmapDrawable( getResources(), data.getData().getPath()); pet_pic.setImageDrawable(thumbnail); } } else if (resultCode == RESULT_CANCELED) { Toast.makeText(getApplicationContext(), "Cancelled", Toast.LENGTH_SHORT).show(); } } } private String getRealPathFromUri(Uri tempUri) { Cursor cursor = null; try { String[] proj = { MediaStore.Images.Media.DATA }; cursor = this.getContentResolver().query(tempUri, 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(); } } } public static int calculateInSampleSize( BitmapFactory.Options options, int reqWidth, int reqHeight) { // Raw height and width of image final int height = options.outHeight; final int width = options.outWidth; int inSampleSize = 1; if (height > reqHeight || width > reqWidth) { final int halfHeight = height / 2; final int halfWidth = width / 2; // Calculate the largest inSampleSize value that is a power of 2 and keeps both // height and width larger than the requested height and width. while ((halfHeight / inSampleSize) > reqHeight && (halfWidth / inSampleSize) > reqWidth) { inSampleSize *= 2; } } return inSampleSize; } private Uri getImageUri(YourActivity youractivity, Bitmap bitmap) { ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.JPEG, 100, byteArrayOutputStream); String path = MediaStore.Images.Media.insertImage(youractivity.getContentResolver(), bitmap, "Title", null); return Uri.parse(path); }
это помогло мне получить uri из галереи и конвертировать в файл для многоступенчатой загрузки
File file = FileUtils.getFile(this, fileUri);
Попробуй Такое
тем не менее, если вы получаете проблему, чтобы получить реальный путь, вы можете попробовать мои ответы. Выше ответы мне не помогли.
объяснение: - этот метод получает URI, а затем проверить уровень API вашего Android устройства после этого в соответствии с уровнем API он будет генерировать реальный путь. код для генерации реального пути отличается в зависимости от уровней API.
Comments