FileOperator
FileOperator copied to clipboard
🔥 【置顶】获取路径为空的问题(Path return null problem)
✨基本上每一个issue
都会提到的问题👉Android Q及以上版本获取路径为空
🌴测试环境 API 30 , Android 11.0
https://user-images.githubusercontent.com/15343661/132307433-c4cde301-d9b5-4bc9-b460-fcb70db4dbcb.mp4
🍎 可以看到, 同一文件会有两种不同的 Uri :
- 从侧边栏
手机图标
进入时获取到文件的Uri
为content://com.android.externalstorage.documents/...
,此时路径不为空; - 从侧边栏
Download
进入时Uri
为content://com.android.providers.downloads/...
, 此时路径为空。
🌴建议使用Uri
替换Path
, 如上传文件操作可以使用ContentResolver.openInputStream/openFile/...
等API操作, 唯一缺点是不能显示文件路径, 但不会影响功能使用。
这个问题现在解决了吗
这个问题现在解决了吗
这个是Android 新版本的特性, 目前没有好的替代方式
android11系统,下载目录根据uri获取path,我目前用了以下方式获取 // DownloadsProvider else if (isDownloadsDocument(uri)) {
// TODO 下载目录中选择或者新建文件夹,在文件夹中存储文件
final String id = DocumentsContract.getDocumentId(uri);
if (id != null && id.startsWith("raw:")) {
return id.substring(4);
}
// TODO 下载根目录存储文件
String displayName = DocumentFile.fromSingleUri(context, uri).getName();
return Environment.getExternalStorageDirectory().toString()
+ File.separator + "Download" + File.separator + displayName;
}
不知道这种获取有什么弊端没
android11系统,下载目录根据uri获取path,我目前用了以下方式获取 // DownloadsProvider else if (isDownloadsDocument(uri)) {
// TODO 下载目录中选择或者新建文件夹,在文件夹中存储文件 final String id = DocumentsContract.getDocumentId(uri); if (id != null && id.startsWith("raw:")) { return id.substring(4); } // TODO 下载根目录存储文件 String displayName = DocumentFile.fromSingleUri(context, uri).getName(); return Environment.getExternalStorageDirectory().toString() + File.separator + "Download" + File.separator + displayName; }
不知道这种获取有什么弊端没
试了下, 拼接路径不靠谱啊... 路径不是固定的Environment.getExternalStorageDirectory().toString()+ File.separator + "Download" + File.separator + displayName
Download 路径下可以使用这种,但是android11 用以下这种方式获取更靠谱: final String id = DocumentsContract.getDocumentId(uri); if (id != null && id.startsWith("raw:")) { return id.substring(4); } String displayName = DocumentFile.fromSingleUri(context, uri).getName(); return Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + File.separator + displayName;
图片压缩的时候,传入 Uri ,会有部分图片返回的 Uri 为空,这个问题要怎么解决
图片压缩的时候,传入 Uri ,会有部分图片返回的 Uri 为空,这个问题要怎么解决
- 先检测下传入的图片Uri是否正确, 参考方法
fun checkUri(uri: Uri?): Boolean {...}
- 如果传入的Uri没问题, 可以试试屏蔽掉
setRenameListener
- [推荐]如果只是单图片处理, 建议压缩图片别缓存, 比如做图片上传可以使用
ByteArrayOutputStream
参考方法👉 fun compressPure(uri: Uri?, maxSize: Long = 300L): Bitmap? {...}
https://github.com/javakam/FileOperator/blob/master/library_compressor/src/main/java/ando/file/compressor/ImageCompressEngine.kt
可以看下这篇文章 Android通过uri获取文件路径 把URI对应的拷到沙盒里面去
可以看下这篇文章 Android通过uri获取文件路径 把URI对应的拷到沙盒里面去
他的解决方式是把读取不到路径的文件
复制到可以读取路径的目录
中, 这种方式大概在 v1.3.7 版本时也是有的。可以参照 #21 中的解释:
和上面原理相同的还有另外一种方式: https://github.com/coltoscosmin/FileUtils/blob/master/FileUtils.java 也可以解决路径为空的问题:
之所以后面删掉这种方式是因为它对于处理小文件和少量文件时还可以, 一旦文件过大或数量多的话就会严重占用手机存储, 所以建议尽量用uri操作文件而不是直接使用path。 当然万不得已的情况下不失为一种解决方式。
可以看下这篇文章 Android通过uri获取文件路径 把URI对应的拷到沙盒里面去
他的解决方式是把
读取不到路径的文件
复制到可以读取路径的目录
中, 这种方式大概在 v1.3.7 版本时也是有的。可以参照 #21 中的解释:
和上面原理相同的还有另外一种方式: coltoscosmin/FileUtils@
master
/FileUtils.java 也可以解决路径为空的问题:
之所以后面删掉这种方式是因为它对于处理小文件和少量文件时还可以, 一旦文件过大或数量多的话就会严重占用手机存储, 所以建议尽量用uri操作文件而不是直接使用path。 当然万不得已的情况下不失为一种解决方式。
我现在的场景就是必须得获取到真实路径,单从不能出问题的角度来看,这个方法不失为暂时的解决之策。还有就是那个 FileSelector的构建能不能改改啊,以及示范例子给多点,点进去看源码才知道,还要处理回调。。。