不是我不想支持 Android 10 的分区存储啊 Orz

2021-06-11 16:27:47 +08:00
 xloger

我司 App 最近终于打算上架 Google Play 了,因此在做一些准备工作。Google Play 的上架要求是 targetSdkVersion 最低 29,也就是要适配分区存储 /存储隔离。 当然,还有一种临时的方案就是在 application 设置 android:requestLegacyExternalStorage="true"。不过这显然也不是啥长久之计,我决定还是直接支持为好。

说一下 App 情况:我们本身行为是很干净的,只有在 DCIM 下创建了一个我们的文件夹,用于用户导出的视频。然后再有一个内置的图片 /视频 /音频选择器,供用户导入,预览内容。

我看了一通 Android 自己的 Android 10 兼容文档,和一些相关的适配文章,<del>很快就适配好了</del>。

大致思路是,我们没法直接操作非我们私有目录文件的 File 了,我们能得到的是 Uri,然后需要读就调 contentResolver.openAssetFileDescriptor 之类的方法,操作 FileDescriptor 即可。 看着是不是很简单!我也觉得!

然后我就愉快地开始测试了=。=

然后发现,项目用到的一个第三方框架,一款获取视频某个关键帧画面的框架 FFmpegMediaMetadataRetriever,在用 FileDescriptor 解析一部分视频时,会发生 Native Crash 。我想着人家是开源项目嘛,我自己琢磨下咋修呗,然后研究了半天,也试了不同的场景,甚至还找到了当年该作者关于这个问题的提问贴,但看了一圈感觉写得没问题啊...

最后放弃了,给作者提了个 Issue 。

我把用到该框架的功能封装了一下改用 Android 自己的 MediaMetadataRetriever 实现了,姑且算是规避了这个问题。

然后,过了两天,我又发现,我如果反复加载视频(对应的用户操作就是在项目列表页反复进入编辑页退出),以前的操作是直接调系统的一个接口 MediaExtractor.setDataSource(filePath),没有问题。但是兼容 Android 10 传 uri 后,操作就是先 contentResolver.openAssetFileDescriptor(uri, "r"),再 MediaExtractor.setDataSource(fileDescriptor),然后当操作次数多了后,openAssetFileDescriptor 就有概率阻塞住,需要过很久才会响应。

我依旧对其进行了很久的分析,自然是有 close 的,而且它的几个不同的 setDataSource 函数本质上也是互相调用的,折腾了一圈,最终结论就是似乎不是我的锅...

而且这个只在一部分手机上会出现。比如我自己的小米 11 就正常。 暂时无解。

再然后,今天早上,测试小姐姐又跟我说,在一台测试机上导图片又会 Crash 啦。我看了一下,大致原因是我们的 Gif 支持是用的一个第三方框架 android-gif-drawable,它在 Android 11 上(也可能是一部分 Android 11 手机)如果传入一张非 Gif 图,会产生 Native Crash 。

我们可以选择先判断 exif 信息之类的,只对 gif 调用。或者再给作者提个 Issue...

所幸我报着试一试的态度更新了库的依赖,解决了问题。而这个版本也是近几个月才更新修复的。

_(:з)∠)_我已经写得身心俱疲了...不知道哪里会不会又有新的兼容性问题,好烦啊......

3362 次点击
所在节点    程序员
23 条回复
xloger
2021-09-13 11:19:24 +08:00
@rosu #20 我之前也是看官方文档的,所以也有类似你的误解。Android 11 的确不支持 requestLegacyExternalStorage 啊,但是这没影响。
对于 Android 10,我们申请了 requestLegacyExternalStorage,所以一切能正常使用。
对于 Android 11,requestLegacyExternalStorage 失效了,但是恢复了 File API 的支持,一样能正常使用。

我负责的 App 自身行为是很规范的,信息存储在私有目录,唯一的问题在于有个内置多媒体选择器,这部分获取了相关权限后照旧用 File 操作就好了,不需要变动。
rosu
2021-09-13 12:02:43 +08:00
@xloger File API 指的是 「 File 相关的 API 」 对吗?那我理解错了。我一开始以为是外部存储相关的东西呢...😂

我纠结的地方在于:

1. Android 10 必须启用 `requestLegacyExternalStorage`,才能使用 `WRITE_EXTERNAL_STORAGE` 权限
2. Android 11 (事实上)却又直接支持 `WRITE_EXTERNAL_STORAGE` 权限,但文档里又写了不支持...所以我就有点懵
xloger
2021-09-13 15:28:35 +08:00
@rosu #22 File API 指的是 「 File 相关的 API 」 ,是的。

Android 11 对 WRITE_EXTERNAL_STORAGE 的支持我忘了,我是规范地获取读取了多媒体权限,然后只有一个写入视频的权限,所以这个对我没影响。如果你操作的是 SD 卡里系统相关的几个目录,那能操作是正常的,如果不是,那我也不太清楚了。(这些文档看完我就忘记得差不多了,它自己反复横跳搞不清...)

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/782941

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX