documentfile - DocumentFile.createFile() 在某些 Android 10 设备上失败
问题描述
DocumentFile.createFile() 在某些 Android 10 设备上返回 null ( java.lang.IllegalArgumentException )。
其中大部分是华为设备:VOG-L29、MAR-LX1A、...
一些用户报告了这一点,但我不知道为什么。我没有遇到此问题的设备,因此无法对其进行测试。
它在大多数设备上都可以正常工作。
有没有人解决过这个问题?
Uri treeUri = <from ACTION_OPEN_DOCUMENT_TREE result> ( content://com.android.externalstorage.documents/tree/4A21-0000:Photos )
DocumentFile docFile = DocumentFile.fromTreeUri( context, treeUri );
DocumentFile resultFile = docFile.createFile( "image/jpeg", "IMG_20200327_144048.jpg" );
resultFile is null !!!
从用户收到的日志:
onActivityResult: requestCode=1,resultCode=-1,data=Intent { dat=content://com.android.externalstorage.documents/tree/4A21-0000:Photos flg=0xc3 }
DocumentsContract: Failed to create document
DocumentsContract: java.lang.IllegalArgumentException: Requested path /mnt/media_rw/4A21-0000/Photos/IMG_20200327_144048.jpg doesn't appear under [/system/media, /hw_product/hw_oem/VOG-L29/media, /system/product/media]
DocumentsContract: at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:170)
DocumentsContract: at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:140)
DocumentsContract: at android.content.ContentProviderProxy.call(ContentProviderNative.java:658)
DocumentsContract: at android.content.ContentResolver.call(ContentResolver.java:2080)
DocumentsContract: at android.provider.DocumentsContract.createDocument(DocumentsContract.java:1327)
...
解决方案
背景:正如许多华为用户所注意到的,从 EMUI 9 到 EMUI 10 的更新已经破坏了许多依赖于对 SD 卡进行写访问的应用程序。该问题已报告给华为,后者将责任推给了谷歌,似乎没有采取任何进一步的行动。受此问题影响的应用程序 Total Commander 的开发者发现,
在 Android 10 的华为设备上,DocumentsContract.createDocument 成功创建文件,但随后导致异常
并怀疑
显然,华为硬编码了一些应该允许用户创建文件的路径,但犯了一个错误。
假设:您的用户尝试通过您的应用程序将文件保存在他们的 SD 卡上。您在问题中没有提到这一点,但根据日志显示的问题和树 URI,我认为是这种情况。
解决方案:即使createFile()
返回null
,文件已正确创建。您可以使用findFile()
它来获取它:
DocumentFile docFile = DocumentFile.fromTreeUri(context, treeUri);
String filename = "IMG_20200327_144048"
DocumentFile resultFile = docFile.createFile("image/jpeg", filename);
if (resultFile == null) {
resultFile = docFile.findFile(filename + ".jpg");
}
如果那时resultFile
仍然是null
,那么我认为这是另一个问题。
警告:如果此目录中已经有一个名为“IMG_20200327_144048.jpg”的文件,那么createFile()
很可能会创建一个名为“IMG_20200327_144048 (1).jpg”的文件,并且findFile()
按照上述解决方案调用会给你旧文件,而不是新创建的。你可以随心所欲地处理它,但我认为这超出了这个问题的范围。
推荐阅读
- android - 上下文 - 空对象引用
- node.js - 在 bcrypt 中比较两个相同的字符串散列返回未定义
- javascript - AngularJS http post and delete data
- c# - sending checkbox value true if checked else false with form object using jQuery in mvc
- google-places-api - Google Places API 请求的会话令牌参数的正确拼写是什么?
- dns - 为什么 Kubernetes 上没有开箱即用地启用 dns 本地缓存?
- sql - A table with several columns in addition to a date/time column. How to query and avoid duplicate dates stamps?
- javascript - 之间的区别:“export { something }”与“export something”
- caching - Pagination feature in Pivotal GemFire
- c# - UWP Bluetooth LE API is slow