原文链接
原作者:红地毯前吃泡面
android10以后,只需要考虑沙盒里的文件uri和共享文件(匿名uri)、通过文件选择器获取到的uri的转换;其他类型,要么转换不成File,要么拿不到,也就不用再考虑了
事实上android10之后,是无法拿到外部文件的绝对路径的,唯一能做的,只是把共享文件复制到沙盒目录下,然后再进行文件操作
沙盒里的文件(file开头),可以直接转成File使用,共享文件(content开头)如果要操作,需要先复制到沙盒目录下
kotlin写法
@RequiresApi(Build.VERSION_CODES.Q)
private fun uriToFileQ(context: Context, uri: Uri): File? =
if (uri.scheme == ContentResolver.SCHEME_FILE)
File(requireNotNull(uri.path))
else if (uri.scheme == ContentResolver.SCHEME_CONTENT) {
//把文件保存到沙盒
val contentResolver = context.contentResolver
val displayName = "${System.currentTimeMillis()}${Random.nextInt(0, 9999)}.${
MimeTypeMap.getSingleton()
.getExtensionFromMimeType(contentResolver.getType(uri))}"
val ios = contentResolver.openInputStream(uri)
if (ios != null) {
File("${context.cacheDir.absolutePath}/$displayName")
.apply {
val fos = FileOutputStream(this)
FileUtils.copy(ios, fos)
fos.close()
ios.close()
}
} else null
} else null
java写法
@RequiresApi(api = Build.VERSION_CODES.Q)
public static File uriToFileApiQ(Uri uri, Context context) {
File file = null;
if(uri == null) return file;
//android10以上转换
if (uri.getScheme().equals(ContentResolver.SCHEME_FILE)) {
file = new File(uri.getPath());
} else if (uri.getScheme().equals(ContentResolver.SCHEME_CONTENT)) {
//把文件复制到沙盒目录
ContentResolver contentResolver = context.getContentResolver();
String displayName = System.currentTimeMillis()+ Math.round((Math.random() + 1) * 1000)
+"."+ MimeTypeMap.getSingleton().getExtensionFromMimeType(contentResolver.getType(uri));
// 注释掉的方法可以获取到原文件的文件名,但是比较耗时
// Cursor cursor = contentResolver.query(uri, null, null, null, null);
// if (cursor.moveToFirst()) {
// String displayName = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));}
try {
InputStream is = contentResolver.openInputStream(uri);
File cache = new File(context.getCacheDir().getAbsolutePath(), displayName);
FileOutputStream fos = new FileOutputStream(cache);
FileUtils.copy(is, fos);
file = cache;
fos.close();
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return file;
}