我知道一张图片的绝对路径(例如,/sdcard/cats.jpg)。有没有办法获取此文件的内容URI?
实际上,在我的代码中,我下载一张图片并将其保存在特定位置。为了将图像设置在ImageView实例中,目前我使用路径打开文件,获取字节并创建位图,然后将位图设置在ImageView实例中。这是一个非常慢的过程,如果我能够获得内容URI,那么我就可以很容易地使用方法imageView.setImageUri(uri)
我知道一张图片的绝对路径(例如,/sdcard/cats.jpg)。有没有办法获取此文件的内容URI?
实际上,在我的代码中,我下载一张图片并将其保存在特定位置。为了将图像设置在ImageView实例中,目前我使用路径打开文件,获取字节并创建位图,然后将位图设置在ImageView实例中。这是一个非常慢的过程,如果我能够获得内容URI,那么我就可以很容易地使用方法imageView.setImageUri(uri)
请尝试以下操作:
ImageView.setImageURI(Uri.fromFile(new File("/sdcard/cats.jpg")));
或者使用:
ImageView.setImageURI(Uri.parse(new File("/sdcard/cats.jpg").toString()));
Uri.fromFile
在Android 26及以上版本将无法使用,你应该使用文件提供程序(file provider)。 - vuhung3990更新
假设您的媒体(图像/视频)已添加到内容媒体提供程序中。如果没有,则将无法获取所需的内容URL。相反,将会是文件URI。
我在我的文件浏览器活动中遇到了同样的问题。您应该知道,仅支持媒体存储数据,如图像、音频和视频的文件的contenturi。我将为您提供从sd卡中选择图像时获取图像内容uri的代码。尝试这段代码,也许对您有用...
public static Uri getImageContentUri(Context context, File imageFile) {
String filePath = imageFile.getAbsolutePath();
Cursor cursor = context.getContentResolver().query(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
new String[] { MediaStore.Images.Media._ID },
MediaStore.Images.Media.DATA + "=? ",
new String[] { filePath }, null);
if (cursor != null && cursor.moveToFirst()) {
int id = cursor.getInt(cursor.getColumnIndex(MediaStore.MediaColumns._ID));
cursor.close();
return Uri.withAppendedPath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "" + id);
} else {
if (imageFile.exists()) {
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.DATA, filePath);
return context.getContentResolver().insert(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
} else {
return null;
}
}
}
支持 Android Q
public static Uri getImageContentUri(Context context, File imageFile) {
String filePath = imageFile.getAbsolutePath();
Cursor cursor = context.getContentResolver().query(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
new String[]{MediaStore.Images.Media._ID},
MediaStore.Images.Media.DATA + "=? ",
new String[]{filePath}, null);
if (cursor != null && cursor.moveToFirst()) {
int id = cursor.getInt(cursor.getColumnIndex(MediaStore.MediaColumns._ID));
cursor.close();
return Uri.withAppendedPath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "" + id);
} else {
if (imageFile.exists()) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
ContentResolver resolver = context.getContentResolver();
Uri picCollection = MediaStore.Images.Media
.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY);
ContentValues picDetail = new ContentValues();
picDetail.put(MediaStore.Images.Media.DISPLAY_NAME, imageFile.getName());
picDetail.put(MediaStore.Images.Media.MIME_TYPE, "image/jpg");
picDetail.put(MediaStore.Images.Media.RELATIVE_PATH,"DCIM/" + UUID.randomUUID().toString());
picDetail.put(MediaStore.Images.Media.IS_PENDING,1);
Uri finaluri = resolver.insert(picCollection, picDetail);
picDetail.clear();
picDetail.put(MediaStore.Images.Media.IS_PENDING, 0);
resolver.update(picCollection, picDetail, null, null);
return finaluri;
}else {
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.DATA, filePath);
return context.getContentResolver().insert(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
}
} else {
return null;
}
}
}
MediaStore.Images.Media
更改为MediaStore.Video.Media
,但仍然没有成功。 - Narendra Singh被接受的解决方案可能是您的最佳选择,但实际上回答主题中的问题:
在我的应用程序中,我必须从URI获取路径并从路径获取URI。 前者:
/**
* 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.Video替换为MediaStore.Audio等来处理音频、文件或其他类型的存储内容):
/**
* 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;
}
基本上,MediaStore
的DATA
列(或者你正在查询的其它子段)存储了文件路径信息,因此您可以使用该信息来查找它。
OpenableColumns.DISPLAY_NAME和OpenableColumns.SIZE
,如果发送应用程序遵循“规则”的话。我发现一些主要的应用程序只返回这两个字段,而不总是返回_data
字段。在没有数据字段的情况下,通常包含内容的直接路径,您必须首先读取内容并将其写入文件或内存中,然后您就拥有了自己的路径。 - Pierre// 这段代码适用于 2.2 版本的图片,不确定是否适用于其他媒体类型
//Your file path - Example here is "/sdcard/cats.jpg"
final String filePathThis = imagePaths.get(position).toString();
MediaScannerConnectionClient mediaScannerClient = new
MediaScannerConnectionClient() {
private MediaScannerConnection msc = null;
{
msc = new MediaScannerConnection(getApplicationContext(), this);
msc.connect();
}
public void onMediaScannerConnected(){
msc.scanFile(filePathThis, null);
}
public void onScanCompleted(String path, Uri uri) {
//This is where you get your content uri
Log.d(TAG, uri.toString());
msc.disconnect();
}
};
content://
最简单和最有效的方法是使用FileProvider。 由FileProvider提供的Uri也可以用于向其他应用程序共享文件的Uri。 要从File
的绝对路径获取文件Uri,可以使用DocumentFile.fromFile(new File(path,name)),它在Api 22中添加,并且对版本低于此的返回null。File imagePath = new File(Context.getFilesDir(), "images");
File newFile = new File(imagePath, "default_image.jpg");
Uri contentUri = FileProvider.getUriForFile(getContext(), "com.mydomain.fileprovider", newFile);
您可以根据使用情况使用以下两种方式:
Uri uri = Uri.parse("文件位置字符串");
或者
Uri uri = Uri.fromFile(new File("文件位置字符串"));
我已经尝试了这两种方法,都可以正常工作。
虽然有点晚了,但希望能对未来的某个人有所帮助。
要获取文件的内容URI,您可以使用以下方法:
FileProvider.getUriForFile(Context context, String authority, File file)
它将返回内容URI。
只需使用 adb shell 命令行工具,无需编写任何代码即可获取文件ID:
adb shell content query --uri "content://media/external/video/media" | grep FILE_NAME | grep -Eo " _id=([0-9]+)," | grep -Eo "[0-9]+"
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
imageUri = Uri.parse(filepath);
} else{
imageUri = Uri.fromFile(new File(filepath));
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
ImageView.setImageURI(Uri.parse(new File("/sdcard/cats.jpg").toString()));
} else{
ImageView.setImageURI(Uri.fromFile(new File("/sdcard/cats.jpg")));
}
你可以尝试下面的代码片段
public Uri getUri(ContentResolver cr, String path){
Uri mediaUri = MediaStore.Files.getContentUri(VOLUME_NAME);
Cursor ca = cr.query(mediaUri, new String[] { MediaStore.MediaColumns._ID }, MediaStore.MediaColumns.DATA + "=?", new String[] {path}, null);
if (ca != null && ca.moveToFirst()) {
int id = ca.getInt(ca.getColumnIndex(MediaStore.MediaColumns._ID));
ca.close();
return MediaStore.Files.getContentUri(VOLUME_NAME,id);
}
if(ca != null) {
ca.close();
}
return null;
}