Java Android Studio中如何从content类型Uri获取文件绝对路径
Android Content Uri转本地绝对路径工具类
场景说明
需要转换的系统Uri典型示例如下:
content://com.android.providers.downloads.documents/document/msf%3A33346content://com.android.providers.downloads.documents/document/raw%3A%2Fstorage%2Femulated%2F0%2FDownload%2F2021-06-18Format%204.xls
这类Content Uri的格式会随手机机型、系统版本差异发生变化,目标是将其转换为类似storage/emulated/0/[文件路径]格式的标准本地文件路径。
可运行实现代码
import android.annotation.SuppressLint; import android.content.ContentResolver; import android.content.ContentUris; import android.content.Context; import android.database.Cursor; import android.net.Uri; import android.os.Build; import android.os.Environment; import android.provider.DocumentsContract; import android.provider.MediaStore; import android.text.TextUtils; import android.util.Log; import org.apache.commons.io.IOUtils; import java.io.File; import java.io.FileOutputStream; import java.io.InputStream; import java.io.OutputStream; public class FileUtils { /* 获取Uri对应的真实本地文件路径 */ public static String getPath(Context ctx, Uri uri) { String ret; try { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { // Android 4.4及以上系统调用 ret = getUriRealPathAboveKitkat(ctx, uri); } else { // Android 4.4以下系统调用 ret = getRealPath(ctx.getContentResolver(), uri, null); } } catch (Exception e) { e.printStackTrace(); Log.d("DREG", "获取路径异常: " + e); // 直接读取Uri流复制为临时文件返回路径,兜底方案 ret = getFilePathFromURI(ctx, uri); } return ret; } /* 兜底方案:读取Uri流复制到本地临时目录,返回新文件路径 */ private static String getFilePathFromURI(Context context, Uri contentUri) { String fileName = getFileName(contentUri); if (!TextUtils.isEmpty(fileName)) { String TEMP_DIR_PATH = Environment.getExternalStorageDirectory().getPath(); File copyFile = new File(TEMP_DIR_PATH + File.separator + fileName); Log.d("DREG", "复制生成临时文件: " + copyFile); copy(context, contentUri, copyFile); return copyFile.getAbsolutePath(); } return null; } /* 从Uri中提取文件名 */ public static String getFileName(Uri uri) { if (uri == null) return null; String fileName = null; String path = uri.getPath(); int cut = path.lastIndexOf('/'); if (cut != -1) { fileName = path.substring(cut + 1); } return fileName; } /* 将Uri对应的流复制到目标文件 */ public static void copy(Context context, Uri srcUri, File dstFile) { try { InputStream inputStream = context.getContentResolver().openInputStream(srcUri); if (inputStream == null) return; OutputStream outputStream = new FileOutputStream(dstFile); IOUtils.copy(inputStream, outputStream); inputStream.close(); outputStream.close(); } catch (Exception e) { e.printStackTrace(); } } /* Android 4.4及以上系统获取Uri真实路径逻辑 */ @RequiresApi(api = Build.VERSION_CODES.KITKAT) private static String getUriRealPathAboveKitkat(Context ctx, Uri uri) { String ret = ""; if (ctx != null && uri != null) { if (isContentUri(uri)) { if (isGooglePhotoDoc(uri.getAuthority())) { ret = uri.getLastPathSegment(); } else { ret = getRealPath(ctx.getContentResolver(), uri, null); } } else if (isFileUri(uri)) { ret = uri.getPath(); } else if (isDocumentUri(ctx, uri)) { // 获取文档Id String documentId = DocumentsContract.getDocumentId(uri); // 获取Uri的授权方标识 String uriAuthority = uri.getAuthority(); if (isMediaDoc(uriAuthority)) { // 媒体库提供的文档 String idArr[] = documentId.split(":"); if (idArr.length == 2) { String docType = idArr[0]; String realDocId = idArr[1]; Uri mediaContentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; if ("image".equals(docType)) { mediaContentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; } else if ("video".equals(docType)) { mediaContentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI; } else if ("audio".equals(docType)) { mediaContentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; } String whereClause = MediaStore.Images.Media._ID + " = " + realDocId; ret = getRealPath(ctx.getContentResolver(), mediaContentUri, whereClause); } } else if (isDownloadDoc(uriAuthority)) { // 下载库提供的文档 Uri downloadUri = Uri.parse("content://downloads/public_downloads"); Uri downloadUriAppendId = ContentUris.withAppendedId(downloadUri, Long.valueOf(documentId)); ret = getRealPath(ctx.getContentResolver(), downloadUriAppendId, null); } else if (isExternalStoreDoc(uriAuthority)) { // 外部存储提供的文档 String idArr[] = documentId.split(":"); if (idArr.length == 2) { String type = idArr[0]; String realDocId = idArr[1]; if ("primary".equalsIgnoreCase(type)) { ret = Environment.getExternalStorageDirectory() + "/" + realDocId; } } } } } return ret; } /* 检查Uri是否为文档类型Uri */ @RequiresApi(api = Build.VERSION_CODES.KITKAT) private static boolean isDocumentUri(Context ctx, Uri uri) { boolean ret = false; if (ctx != null && uri != null) { ret = DocumentsContract.isDocumentUri(ctx, uri); } return ret; } /* 检查Uri是否为Content类型Uri,示例格式:content://media/external/images/media/1302716 */ private static boolean isContentUri(Uri uri) { boolean ret = false; if (uri != null) { String uriSchema = uri.getScheme(); if ("content".equalsIgnoreCase(uriSchema)) { ret = true; } } return ret; } /* 检查Uri是否为File类型Uri,示例格式:file:///storage/41B7-12F1/DCIM/Camera/IMG_20180211_095139.jpg */ private static boolean isFileUri(Uri uri) { boolean ret = false; if (uri != null) { String uriSchema = uri.getScheme(); if ("file".equalsIgnoreCase(uriSchema)) { ret = true; } } return ret; } /* 检查是否为外部存储提供的文档 */ private static boolean isExternalStoreDoc(String uriAuthority) { return "com.android.externalstorage.documents".equals(uriAuthority); } /* 检查是否为下载管理提供的文档 */ private static boolean isDownloadDoc(String uriAuthority) { return "com.android.providers.downloads.documents".equals(uriAuthority); } /* 检查是否为媒体库提供的文档 */ private static boolean isMediaDoc(String uriAuthority) { return "com.android.providers.media.documents".equals(uriAuthority); } /* 检查是否为谷歌相册提供的文档 */ private static boolean isGooglePhotoDoc(String uriAuthority) { return "com.google.android.apps.photos.content".equals(uriAuthority); } /* 查询ContentResolver获取Uri对应的真实路径 */ @SuppressLint("Recycle") private static String getRealPath(ContentResolver contentResolver, Uri uri, String whereClause) { String ret = ""; Cursor cursor = contentResolver.query(uri, null, whereClause, null, null); if (cursor != null) { boolean moveToFirst = cursor.moveToFirst(); if (moveToFirst) { String columnName = MediaStore.Images.Media.DATA; if (uri == MediaStore.Images.Media.EXTERNAL_CONTENT_URI) { columnName = MediaStore.Images.Media.DATA; } else if (uri == MediaStore.Audio.Media.EXTERNAL_CONTENT_URI) { columnName = MediaStore.Audio.Media.DATA; } else if (uri == MediaStore.Video.Media.EXTERNAL_CONTENT_URI) { columnName = MediaStore.Video.Media.DATA; } int columnIndex = cursor.getColumnIndex(columnName); if (columnIndex > -1) { ret = cursor.getString(columnIndex); } cursor.close(); } } return ret; } }
内容的提问来源于stack exchange,提问作者Jairo Daniel Salas Mosquera
相关产品推荐
相关产品推荐

