Android 11(API 30)调用File.listFiles()无法返回全部文件如何解决?
我分别在API 29(Android 10)和API 30(Android 11)的设备上进行了测试,两台设备的Download文件夹内都存放了5个完全相同的文件。
应用在AndroidManifest.xml中声明了<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />权限,且会在运行时动态申请该权限,同时也配置了android:requestLegacyExternalStorage="true"属性(该属性仅对Android 10生效,Android 11会忽略该配置)。
相关代码如下:
private fun init() { val path = File(Environment.getExternalStorageDirectory(), "Download") val files = path.listFiles() Timber.d("Android API ${Build.VERSION.SDK_INT}, dirFiles ${files?.joinToString(separator = " ") { it.name }}") }
测试日志输出
Android 11(30 SDK)日志
2021-10-06 23:40:52.182 9022-9022/com.example.tests D/MainActivity: Android API 30, dirFiles Elephants Dream.srt Elephants Dream.mkv
Android 10(29 SDK)日志
2021-10-06 23:45:51.835 8293-8293/com.example.tests D/MainActivity: Android API 29, dirFiles Elephants Dream.srt Elephants Dream.ssa Elephants Dream.vtt Elephants Dream.ass Elephants Dream.mkv
从日志可以看出,Android 11系统下调用File.listFiles()方法无法返回全部文件,系统层面会通过媒体过滤器对文件进行筛选,即使用MediaStore游标查询也会得到同样的受限结果。系统仅将srt格式的字幕文件识别为媒体类型,ssa、vtt、ass等其他字幕格式都不被判定为媒体文件,这个逻辑非常不合理,因为上述几种格式都属于标准字幕文件。
权限设置界面对比:
- Android 10存储权限设置界面

- Android 11存储权限设置界面

我开发了一款视频播放器应用,需要支持多种字幕格式,但在Android 11系统下仅能获取到srt格式的字幕文件,请问如何才能获取到所有需要的文件?
更新
目前Android 11下看起来唯一的解决办法是申请Request All files access权限,但该权限很难通过Google Play的审核。
也可以使用SAF(Storage Access Framework,存储访问框架)实现,但该方案在Android 11上存在诸多限制。
内容的提问来源于stack exchange,提问作者user924

