1

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)
...
4

1 回答 1

1

背景:正如许多华为用户所注意到的,从 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()按照上述解决方案调用会给你旧文件,而不是新创建的。你可以随心所欲地处理它,但我认为这超出了这个问题的范围。

于 2021-02-23T15:29:15.617 回答