android 通过 Uri.getPath() 获取真实路径
Posted
技术标签:
【中文标题】android 通过 Uri.getPath() 获取真实路径【英文标题】:android get real path by Uri.getPath() 【发布时间】:2011-02-16 20:55:15 【问题描述】:我正在尝试从图库中获取图片。
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
')?
谢谢
【问题讨论】:
这显然是一个很晚的评论,但我只想指出 startActivityForResultCode 方法将请求代码作为参数,而不是结果代码。uri.getPath()
没有给你真正的路径吗?
#Try This 尽管如此,如果您遇到问题以获取真正的路径,您可以尝试我的答案。以上答案对我没有帮助。 说明:-该方法获取URI,然后根据API级别检查您的android设备的API级别,它将生成真实路径。 生成真实路径的代码根据API级别不同。 Here is my Answer
【参考方案1】:
这就是我的工作:
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()
方法已弃用,所以我没有使用它。
上次编辑:改进。我们应该关闭光标!!
【讨论】:
嗨@m3n0R,在 Moto G 中,MediaStore.Images.ImageColumns.DATA 列根本不存在。没有此列如何获取图像? 错误确保游标在访问数据之前已正确初始化.. 签入 API 19 无法从 CursorWindow 读取第 0 行,第 -1 列。确保在从光标访问数据之前正确初始化光标。 崩溃:java.lang.IllegalStateException:无法从 CursorWindow 读取第 0 行,列 -1。确保在从光标访问数据之前正确初始化光标。 MediaStore.Images.ImageColumns.DATA 已弃用【参考方案2】:你真的有必要获得物理路径吗?
例如,ImageView.setImageURI()
和 ContentResolver.openInputStream()
允许您在不知道文件真实路径的情况下访问文件的内容。
【讨论】:
这正是我一直在寻找的,但找不到。谢谢。 对不起,如果我想将此图像转换为文件,而没有获得真实路径怎么办? 物理路径可以访问文件名和扩展名。在文件上传的情况下。 如何存入数据库?【参考方案3】:@Rene Juuse - 以上在 cmets...感谢此链接!
。 获取真实路径的代码从一个 SDK 到另一个 SDK 有点不同,所以下面我们提供了三种处理不同 SDK 的方法。
getRealPathFromURI_API19():返回 API 19(或更高版本但未测试)的真实路径 getRealPathFromURI_API11to18():返回 API 11 到 API 18 的真实路径 getRealPathFromURI_below11():返回11以下API的真实路径
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 年 3 月更新
为了解决图像路径的所有问题,我尝试创建一个自定义画廊作为 facebook 和其他应用程序。这是因为您可以只使用本地文件(真实文件,而不是虚拟或临时文件),我解决了这个库的所有问题。
https://github.com/nohana/Laevatein(这个库是从相机拍照或从画廊中选择,如果你从画廊中选择,他有一个带相册的抽屉,只显示本地文件)
【讨论】:
@Clocker 在三星 S4 上也没有 我真的很难在android中管理所有类型的源图像。如果您上传或从图库中选择,最好的解决方案是从 facebook 创建为图库。它是一个自定义画廊,只有设备中的真实图像,没有虚拟或临时的。我使用这个库修复了我的应用程序中的所有问题。 github.com/nohana/Laevatein 非常好的图书馆。自定义并不简单,但您可以打开代码并进行更改。我希望这可以帮助你。 在我的三星 S2 上用 4.4.1 坏了 我需要获取pdf或doc之类的文件,我无法获取路径。你能帮帮我吗? 太棒了!最后是真正有效的东西。找这个找了很久。谢谢。【参考方案4】:注意这是对@user3516549 answer 的改进,我已经在装有 Android 6.0.1 的 Moto G3 上进行了检查 我有这个问题,所以我尝试了@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)
EDIT1 :如果您尝试在更高版本的外部 sdcard 中获取文件的图像路径,请检查my question
EDIT2 Here 是处理虚拟文件和主机而不是com.android.providers
的完整代码我已经用content://com.adobe.scan.android.documents/document/
测试了这个方法
【讨论】:
嗨,朋友,是的,没错。但这正在发生,因为现在谷歌有一个默认格式,可以将所有照片从您的手机上传到谷歌文档。只需将缩略图保存在手机中即可。如果您从 google docs 获得此 uri,则需要在使用之前下载照片。这一般都不好。所以,为了解决这里的所有问题,现在我正在使用这个库。 (此库仅使用本地文件,通过此解决方案您的问题将得到解决),或者您可以从库中提取代码并改进自己以解决您的问题。 github.com/nohana/Laevatein希望对你有帮助。 1+,它的工作非常适合我。正如@JaiprakasSoni 在他的回答中所说,当我在 Moto G4 游戏中运行我的应用程序时,我遇到了同样的问题,但是当我使用上面的代码时,它对我来说很好。谢谢。你节省了我的时间【参考方案5】:编辑: 在此处使用此解决方案:https://***.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;
注意:所以我们得到了文档和图片,这取决于图片来自“最近”、“画廊”还是其他任何地方。所以我在查找之前先提取图像ID。
【讨论】:
【参考方案6】:一种简单且最佳的方法将文件复制到真实路径,然后获取它们的路径我检查了 android API-16 到 API-30 上的 10 台设备工作正常。
@Nullable
public static String createCopyAndReturnRealPath(
@NonNull Context context, @NonNull Uri uri)
final ContentResolver contentResolver = context.getContentResolver();
if (contentResolver == null)
return null;
// Create file path inside app's data dir
String filePath = context.getApplicationInfo().dataDir + File.separator + "temp_file";
File file = new File(filePath);
try
InputStream inputStream = contentResolver.openInputStream(uri);
if (inputStream == null)
return null;
OutputStream outputStream = new FileOutputStream(file);
byte[] buf = new byte[1024];
int len;
while ((len = inputStream.read(buf)) > 0)
outputStream.write(buf, 0, len);
outputStream.close();
inputStream.close();
catch (IOException ignore)
return null;
return file.getAbsolutePath();
【讨论】:
只是最好的 Uri-to-path 。对于大文件可能会很麻烦,但对于小文件来说效果很好。 轻松找到最好的解决方案。非常适合我需要获取小文件路径的用例。不需要文件选择库或其他复杂的解决方案来获取真实路径。最好的部分是,它适用于我所有的设备。感谢分享 由于某种原因,当我使用它时,该文件未在应用程序文件夹中创建,然后我得到它不存在 @YakirMalka 使用 temp_file 的名称创建,但没有 jpg、png ....等扩展名 是的,昨天想通了 :) 谢谢!【参考方案7】:您好,这是我从相机或画廊拍摄图像的完整代码
//我的变量声明
protected static final int CAMERA_REQUEST = 0;
protected static final int GALLERY_REQUEST = 1;
Bitmap bitmap;
Uri uri;
Intent picIntent = null;
//点击
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);
【讨论】:
你怎么知道这一行是100options.inSampleSize = calculateInSampleSize(options, 100, 100);
【参考方案8】:
这帮助我从图库中获取 uri 并转换为文件以进行分段上传
File file = FileUtils.getFile(this, fileUri);
https://github.com/iPaulPro/aFileChooser/blob/master/aFileChooser/src/com/ipaulpro/afilechooser/utils/FileUtils.java
【讨论】:
以上是关于android 通过 Uri.getPath() 获取真实路径的主要内容,如果未能解决你的问题,请参考以下文章