在Android 11中,由于隐私和安全的考虑,无法直接从Uri获取真实路径。Android 11引入了Scoped Storage机制,限制了对外部存储的访问权限。但是,我们仍然可以通过以下方法获取Uri对应文件的真实路径:
public String getRealPathFromUri(Context context, Uri uri) {
String filePath = "";
if (uri.getScheme().equals("content")) {
Cursor cursor = context.getContentResolver().query(uri, null, null, null, null);
if (cursor != null) {
if (cursor.moveToFirst()) {
int index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
filePath = cursor.getString(index);
}
cursor.close();
}
} else if (uri.getScheme().equals("file")) {
filePath = uri.getPath();
}
return filePath;
}
public String getRealPathFromUri(Context context, Uri uri) {
String filePath = "";
if (DocumentsContract.isDocumentUri(context, uri)) {
if (isExternalStorageDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
if ("primary".equalsIgnoreCase(type)) {
filePath = Environment.getExternalStorageDirectory() + "/" + split[1];
}
} else if (isDownloadsDocument(uri)) {
final String id = DocumentsContract.getDocumentId(uri);
final Uri contentUri = ContentUris.withAppendedId(
Uri.parse("content://downloads/public_downloads"), Long.parseLong(id));
filePath = getDataColumn(context, contentUri, null, null);
} else if (isMediaDocument(uri)) {
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]};
filePath = getDataColumn(context, contentUri, selection, selectionArgs);
}
} else if ("content".equalsIgnoreCase(uri.getScheme())) {
filePath = getDataColumn(context, uri, null, null);
} else if ("file".equalsIgnoreCase(uri.getScheme())) {
filePath = uri.getPath();
}
return filePath;
}
private 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 index = cursor.getColumnIndexOrThrow(column);
return cursor.getString(index);
}
} finally {
if (cursor != null) {
cursor.close();
}
}
return "";
}
private boolean isExternalStorageDocument(Uri uri) {
return "com.android.externalstorage.documents".equals(uri.getAuthority());
}
private boolean isDownloadsDocument(Uri uri) {
return "com.android.providers.downloads.documents".equals(uri.getAuthority());
}
private boolean isMediaDocument(Uri uri) {
return "com.android.providers.media.documents".equals(uri.getAuthority());
}
这两种方法可以根据Uri的不同类型进行处理,从而获取到文件的真实路径。需要注意的是,由于Android 11的限制,某些Uri可能无法直接获取真实路径,此时可以考虑使用文件流进行操作,而不是依赖于真实路径。
推荐的腾讯云相关产品:腾讯云对象存储(COS),提供了安全可靠、高扩展性的云端存储服务,适用于存储、备份、归档、大数据分析等场景。产品介绍链接地址:https://cloud.tencent.com/product/cos
领取专属 10元无门槛券
手把手带您无忧上云