ste*_*ter 376 android uri absolute-path mediastore
我onActivityResult
从mediastore图像选择返回,我可以使用以下内容获取图像的URI:
Uri selectedImage = data.getData();
Run Code Online (Sandbox Code Playgroud)
将其转换为字符串可以得到:
content://media/external/images/media/47
Run Code Online (Sandbox Code Playgroud)
或者路径给出:
/external/images/media/47
Run Code Online (Sandbox Code Playgroud)
但是我似乎无法找到将其转换为绝对路径的方法,因为我想将图像加载到位图而不必将其复制到某处.我知道这可以使用URI和内容解析器完成,但这似乎在重新启动手机时中断,我想MediaStore
在重新启动之间不会保持其编号相同.
Miš*_*eić 603
在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();
}
}
}
Run Code Online (Sandbox Code Playgroud)
Seb*_*ano 125
只是第一个答案的简单更新: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;
}
Run Code Online (Sandbox Code Playgroud)
Jit*_*iya 106
对于奥利奥
Uri uri = data.getData();
File file = new File(uri.getPath());//create path from uri
final String[] split = file.getPath().split(":");//split the path.
filePath = split[1];//assign it to a string(your choice).
Run Code Online (Sandbox Code Playgroud)
对于Oreo下面的所有版本,我已经制作了这个从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())) {
if (isGooglePhotosUri(uri)) {
return uri.getLastPathSegment();
}
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) {
e.printStackTrace();
}
} 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());
}
public static boolean isGooglePhotosUri(Uri uri) {
return "com.google.android.apps.photos.content".equals(uri.getAuthority());
}
Run Code Online (Sandbox Code Playgroud)
mig*_*mig 95
不要试图在文件系统中找到一个uri,这在数据库中查找起来很慢.
您可以通过向工厂提供输入流来获取uri的位图,就像您将文件提供给工厂一样:
InputStream is = getContentResolver().openInputStream(uri);
Bitmap bitmap = BitmapFactory.decodeStream(is);
is.close();
Run Code Online (Sandbox Code Playgroud)
Nik*_*huk 38
这是我从URI获取文件名的例子,例如file:// ...和content:// .... 它不仅适用于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;
}
Run Code Online (Sandbox Code Playgroud)
Jon*_*n O 15
很好的现有答案,其中一些我曾经拿出自己的答案:
我必须从URI获取路径并从路径获取URI,并且谷歌很难分辨出具有相同问题的任何人(例如,从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;
}
Run Code Online (Sandbox Code Playgroud)
后者(我为视频做,但也可以通过将MediaStore.Audio(等)替换为MediaStore.Video来用于音频或文件或其他类型的存储内容):
/**
* 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;
}
Run Code Online (Sandbox Code Playgroud)
基本上,DATA
柱MediaStore
(或任何它要查询的子部分)存储的文件路径,让你无论是使用你知道要查找什么DATA
字段,或者使用字段来查找你想要的任何东西.
然后我进一步使用Scheme
上面的内容来弄清楚如何处理我的数据:
private boolean getSelectedVideo(Intent imageReturnedIntent, boolean fromData) {
Uri selectedVideoUri;
//Selected image returned from another activity
// A parameter I pass myself to know whether or not I'm being "shared via" or
// whether I'm working internally to my app (fromData = working internally)
if(fromData){
selectedVideoUri = imageReturnedIntent.getData();
} else {
//Selected image returned from SEND intent
// which I register to receive in my manifest
// (so people can "share via" my app)
selectedVideoUri = (Uri)getIntent().getExtras().get(Intent.EXTRA_STREAM);
}
Log.d(TAG,"SelectedVideoUri = " + selectedVideoUri);
String filePath;
String scheme = selectedVideoUri.getScheme();
ContentResolver contentResolver = getContentResolver();
long videoId;
// If we are sent file://something or content://org.openintents.filemanager/mimetype/something...
if(scheme.equals("file") || (scheme.equals("content") && selectedVideoUri.getEncodedAuthority().equals("org.openintents.filemanager"))){
// Get the path
filePath = selectedVideoUri.getPath();
// Trim the path if necessary
// openintents filemanager returns content://org.openintents.filemanager/mimetype//mnt/sdcard/xxxx.mp4
if(filePath.startsWith("/mimetype/")){
String trimmedFilePath = filePath.substring("/mimetype/".length());
filePath = trimmedFilePath.substring(trimmedFilePath.indexOf("/"));
}
// Get the video ID from the path
videoId = getVideoIdFromFilePath(filePath, contentResolver);
} else if(scheme.equals("content")){
// If we are given another content:// URI, look it up in the media provider
videoId = Long.valueOf(selectedVideoUri.getLastPathSegment());
filePath = getFilePathFromContentUri(selectedVideoUri, contentResolver);
} else {
Log.d(TAG,"Failed to load URI " + selectedVideoUri.toString());
return false;
}
return true;
}
Run Code Online (Sandbox Code Playgroud)
YYa*_*mil 10
在所有情况下,这些答案都不适用于我.我不得不直接访问Google的文档https://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;
}
Run Code Online (Sandbox Code Playgroud)
您可以使用此位图在图像视图中显示它.
API 19 及更高版本,来自 Uri 的图像文件路径完美运行。我还检查了这个最新的PIE API 28。
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;
}
Run Code Online (Sandbox Code Playgroud)
现在事情变得复杂了,尤其是在 API 级别 29 Android Q 之后。 这就是你应该如何从内容 Uri 中获取文件名
public static String getNameFromContentUri(Context context, Uri contentUri){
Cursor returnCursor = context.getContentResolver().query(contentUri, null, null, null, null);
int nameColumnIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
returnCursor.moveToFirst();
String fileName = returnCursor.getString(nameColumnIndex);
return fileName;}
Run Code Online (Sandbox Code Playgroud)
这就是您获取所有 android 版本的 Content Uri 完整路径的方法
爪哇
public static String getFullPathFromContentUri(final Context context, final Uri uri) {
final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
// DocumentProvider
if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
// ExternalStorageProvider
if ("com.android.externalstorage.documents".equals(uri.getAuthority())) {
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];
}//non-primary e.g sd card
else {
if (Build.VERSION.SDK_INT > 20) {
//getExternalMediaDirs() added in API 21
File extenal[] = context.getExternalMediaDirs();
for (File f : extenal) {
filePath = f.getAbsolutePath();
if (filePath.contains(type)) {
int endIndex = filePath.indexOf("Android");
filePath = filePath.substring(0, endIndex) + split[1];
}
}
}else{
filePath = "/storage/" + type + "/" + split[1];
}
return filePath;
}
}
// DownloadsProvider
else if ("com.android.providers.downloads.documents".equals(uri.getAuthority())) {
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 ("com.android.providers.media.documents".equals(uri.getAuthority())) {
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;
}
final String selection = "_id=?";
final String[] selectionArgs = new String[]{
split[1]
};
Cursor cursor = null;
final String column = "_data";
final String[] projection = {
column
};
try {
cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
null);
if (cursor != null && cursor.moveToFirst()) {
final int column_index = cursor.getColumnIndexOrThrow(column);
return cursor.getString(column_index);
}
} finally {
if (cursor != null)
cursor.close();
}
return null;
}
}
// 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;
}
private static String getDataColumn(Context context, Uri uri, String selection,
String[] selectionArgs) {
Cursor cursor = null;
final String column = "_data";
final String[] projection = {
column
};
try {
cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
null);
if (cursor != null && cursor.moveToFirst()) {
final int column_index = cursor.getColumnIndexOrThrow(column);
return cursor.getString(column_index);
}
} finally {
if (cursor != null)
cursor.close();
}
return null;
}
Run Code Online (Sandbox Code Playgroud)
科特林
companion object {
@JvmStatic
@SuppressLint("NewApi")
fun getPath(context: Context, uri: Uri): String? {
val isKitKat: Boolean = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT
// DocumentProvider
if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
// ExternalStorageProvider
if (isExternalStorageDocument(uri)) {
val docId = DocumentsContract.getDocumentId(uri)
val split = docId.split(":").toTypedArray()
val type = split[0]
return if ("primary".equals(type, ignoreCase = true)) {
Environment.getExternalStorageDirectory().toString() + "/" + split[1]
} else { // non-primary volumes e.g sd card
var filePath = "non"
//getExternalMediaDirs() added in API 21
val extenal = context.externalMediaDirs
for (f in extenal) {
filePath = f.absolutePath
if (filePath.contains(type)) {
val endIndex = filePath.indexOf("Android")
filePath = filePath.substring(0, endIndex) + split[1]
}
}
filePath
}
} else if (isDownloadsDocument(uri)) {
val id = DocumentsContract.getDocumentId(uri)
val contentUri = ContentUris.withAppendedId(
Uri.parse("content://downloads/public_downloads"), java.lang.Long.valueOf(id))
return getDataColumn(context, contentUri, null, null)
} else if (isMediaDocument(uri)) {
val docId = DocumentsContract.getDocumentId(uri)
val split = docId.split(":").toTypedArray()
val type = split[0]
var contentUri: Uri? = null
if ("image" == type) {
contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
} else if ("video" == type) {
contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI
} else if ("audio" == type) {
contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
}
val selection = "_id=?"
val selectionArgs = arrayOf(
split[1]
)
return getDataColumn(context, contentUri, selection, selectionArgs)
}
} else if ("content".equals(uri.scheme, ignoreCase = true)) {
return getDataColumn(context, uri, null, null)
} else if ("file".equals(uri.scheme, ignoreCase = true)) {
return uri.path
}
return null
}
private fun getDataColumn(context: Context, uri: Uri?, selection: String?,
selectionArgs: Array<String>?): String? {
var cursor: Cursor? = null
val column = "_data"
val projection = arrayOf(
column
)
try {
cursor = context.contentResolver.query(uri!!, projection, selection, selectionArgs,
null)
if (cursor != null && cursor.moveToFirst()) {
val column_index = cursor.getColumnIndexOrThrow(column)
return cursor.getString(column_index)
}
} catch (e: java.lang.Exception) {
} finally {
cursor?.close()
}
return null
}
private fun isExternalStorageDocument(uri: Uri): Boolean {
return "com.android.externalstorage.documents" == uri.authority
}
private fun isDownloadsDocument(uri: Uri): Boolean {
return "com.android.providers.downloads.documents" == uri.authority
}
private fun isMediaDocument(uri: Uri): Boolean {
return "com.android.providers.media.documents" == uri.authority
}
}
Run Code Online (Sandbox Code Playgroud)
}
不过,如果您遇到问题以获得真正的路径,您可以尝试我的答案。上面的答案对我没有帮助。
说明:- 此方法获取 URI,然后检查 Android 设备的 API 级别,然后根据 API 级别生成真实路径。根据API级别不同,生成真实路径方法的代码也不同。
从 URI 获取真实路径的方法
@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;
}
Run Code Online (Sandbox Code Playgroud)
像这样使用这个方法
Log.e(TAG, "getRealPathFromURI: "+getPathFromURI(your_selected_uri) );
Run Code Online (Sandbox Code Playgroud)
输出:-
04-06 12:39:46.993 6138-6138/com.app.qtm E/标签:getRealPathFromURI:/storage/emulated/0/Video/avengers_infinity_war_4k_8k-7680x4320.jpg
过去的Android Q 的任何方式,当 MediaStore.Images.Media.DATA 不再可用时?此字段在 Android Q 中已折旧:
此常量在 API 级别 29 中已弃用。应用程序可能没有直接访问此路径的文件系统权限。应用程序不应尝试直接打开此路径,而应使用 ContentResolver#openFileDescriptor(Uri, String) 来获取访问权限。
https://developer.android.com/reference/android/provider/MediaStore.MediaColumns.html#DATA
--- 编辑
据我所知,对于过去的 Android Q,唯一的方法是在RELATIVE_PATH上进行中继
此媒体项目在其被持久化的存储设备中的相对路径。例如,存储在 /storage/0000-0000/DCIM/Vacation/IMG1024.JPG 的项目的路径为 DCIM/Vacation/。
https://developer.android.com/reference/android/provider/MediaStore.MediaColumns.html#RELATIVE_PATH
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);
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
324642 次 |
最近记录: |