Ответ 1
Действительно ли вам необходимо получить физический путь?
Например, ImageView.setImageURI()
и ContentResolver.openInputStream()
позволяют вам получать доступ к содержимому файла, не зная его реального пути.
Я пытаюсь получить изображение из галереи.
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
" )?
Спасибо
Действительно ли вам необходимо получить физический путь?
Например, 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);
}
font: 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 (или выше), когда мы запустим намерение выбора изображения галереи, откроется экран, показывающий последние изображения, когда пользователь выбирает изображение из этого списка, мы получим 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)
}
}
РЕДАКТИРОВАТЬ:, если вы пытаетесь получить путь к файлу файла во внешней SD-карте в более высокой версии, а затем проверьте мой вопрос
EDIT: Используйте это решение здесь: fooobar.com/questions/12193/... Прекрасно работает!
Во-первых, спасибо за ваше решение @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", "gallery" или того, что когда-либо было. Поэтому сначала я извлекаю идентификатор изображения, прежде чем искать его.
Как знают фактические программисты, нет реального пути.
A Uri
с схемой content
- непрозрачный дескриптор некоторого содержимого. Если этот Uri
представляет открываемый контент, вы можете использовать ContentResolver
и openInputStream()
, чтобы получить InputStream
в этом контенте. Аналогично, a Uri
с схемой http
или https
не представляет собой локальный файл, и вам нужно будет использовать API-интерфейс HTTP для доступа к нему.
Только Uri
с схемой file
идентифицирует файл (запрет на случай, когда файл был перемещен или удален после создания Uri
).
Какие глупые люди пытаются получить путь к файловой системе, пытаясь декодировать содержимое Uri
, возможно, в сочетании с заклинаниями заклинания для вызова $EVIL_DEITY
. В лучшем случае это будет ненадежным по трем причинам:
Правила для декодирования значений Uri
могут меняться со временем, например, с версиями версий для Android, поскольку структура Uri
представляет деталь реализации, а не интерфейс
Даже если вы получите путь к файловой системе, у вас могут не быть прав на доступ к файлу
Не все значения Uri
могут быть декодированы с помощью фиксированных алгоритмов, так как у многих приложений есть свои собственные поставщики, и они могут указывать на все: от активов до столбцов BLOB
до данных, которые необходимо передавать из Интернета
Ни один разработчик с каким-либо здравым смыслом не идет по этому пути.
Если у вас есть ограниченный API, для которого требуется файл, используйте InputStream
from openInputStream()
, чтобы сделать копию этого содержимого. Независимо от того, является ли это временной копией (например, используется для операции загрузки файла, затем удаляется) или долговечной копией (например, для функции "импорта" вашего приложения) зависит от вас.
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();
}
//тело метода
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 из галереи и конвертировать в файл для загрузки Multipart
File file = FileUtils.getFile(this, fileUri);