Android 64 位架构适配
前言
随着手机硬件的不断发展,近两年的新式手机已经全部采用了 64 位 CPU,64 位真的比 32 位快吗?实际上 32 位和 64 位的差异主要体现在内存寻址上,32 位最高只支撑 4GB 内存,而 64 位则能够最高支撑 128GB 内存。
目前各个应用市场也对 64 位适配提出了要求。
Google Play:
自 2019 年 8 月 1 日起,在 Google Play 上发布的应用必须支持 64 位架构。
国内:
小米应用商店与 OPPO 应用商店、vivo 应用商店等已经发出通知:
2021 年 12 月底:现有和新发布的应用/游戏,需上传包含 64 位包体的 APK 包(支持双包在架,和 64 位兼容 32 位的两个形式,不再接收仅支持 32 位的 APK 包)。
2022 年 8 月底:硬件支持 64 位的系统,将仅接收含 64 位版本的 APK 包。
2023 年底:硬件将仅支持 64 位 APK,32 位应用无法在终端上运行。
华为应用商店:
2022 年 2 月 1 日起,在华为应用市场新上架/升级的游戏及应用,必须包含 64 位版本,华为应用市场不再接收仅包含 32 位版本的应用。
2022 年 9 月 1 日起,华为应用市场将不再接收包含 32 位版本的应用。
Android ABI
不同的 Android 设备使用不同的 CPU,而不同的 CPU 支持不同的指令集。CPU 与指令集的每种组合都有专属的应用二进制接口 (ABI)。
Android 设备支持的 ABI 类型如下:
这里主要看 arm 架构的,新的架构能够兼容旧的 abi 对应的 so,例如 arm64-v8a 架构的 CPU 能够运行 armeabi-v7a 架构的 so,反过来不行,这就是为什么现在很多 APP 只包含 armeabi-v7a 的包却能够在最新的 CPU 上运行。如果以后的 CPU 不再兼容旧的架构了的话,现在只包含 armeabi 或者 armeabi-v7a 架构的 APP 就不能再运行了。
如果应用同时包含了两种架构,应用运行时会有两个 Zygote (一个 32 位,一个 64 位)进程同时运行。APP 安装的时候根据 lib 目录里面支持的架构和机器自己的 CPU 类型来决定 primaryCpuAbi,在启动的时候会根据安装时候确定的 primaryCpuAbi 的值来决定是从 64 位还是 32 位的 Zygote 进程 fork 出子进程,如果从 64 的 fork,则是以 64 位模式运行。
由于一些软件功能越来越多,安装包的体积、运行时需要消耗的运行内存越来越大,32 位应用的局限性越来越突出。而 64 位系统,可以在单个线程里使用超过 4GB 的运行内存,当处理一些大型软件、或者进行高像素图像、视频处理的时候,就更能够发挥手机硬件的优势。比如一些大型游戏、网络视频直播、高画质影音播放等等。而且 64 位系统相比 32 位系统,会带来至少 20% 效率的提升。
查看自己的应用是否支持 64 位架构
关于如何检索 APK 中不支持 64 位 的 so 文件,官方提供了两种方法,具体可参考
其中比较简单的方法就是通过 Android Studio 提供的 APK 分析工具,查看 lib 文件夹,如果里面只有 armeabi 或者 armeabi-v7a 文件夹,就是只支持 32 位,不支持 64 位。 如果同时还有 arm64-v8a 文件夹,则说明有 64 位原生库,是否与 32 位有相同的功能和质量,还需要进行测试。
可以看到这里没有任何 arm64-v8a 或 x86_64 库,则需要更新构建流程以开始构建并打包 APK 中的这些工件。
应用内的原生库的来源一般有三处:
第三方库
工程内的 so 文件
C/C++ 源码模块
目前很多第三方库已经同时支持 32 和 64 位了,但是有些还不支持,如何找出这部分不支持的库或者文件呢?如果项目中的 .so 文件数量很多,就很难通过肉眼的方式来查找。
我们可以通过 gradle 脚本或者一些现有三方框架,对项目打包过程中 mergeReleaseNativeLibs (mergeDebugNativeLibs 也可以,根据自己情况选择) 这个 Task 来进行 .so 文件的检索,通过判断每个 .so 文件的路径中是否包含 "aremeabi-v7a"、"arm64-v8a"、"x86"、"x86_64" 等名称来判断 .so 的类型。
核心代码:
这里我们使用一个已经封装好的 gradle 插件 ,EasyPrivacy 通过集成和使用后,检测出项目中,尚未进行 arm64-v8a 适配的 .so 文件。
根据项目情况,我们需要对 in armeabiv-v7a, but not in arm64-v8a 的 .so 文件进行适配
通过分析我们可以看到 jetified-gsyVideoPlayer-armv7a-8.0.0:libijkffmpeg.so 、jetified-gsyVideoPlayer-armv7a-8.0.0:libijkplayer.so 、jetified-gsyVideoPlayer-armv7a-8.0.0:libijksdl.so 、 一共 3 个 .so 需要我们去适配。
64 位适配修改
首先我们要将打包配置进行修改:
改为:
这时再进行打包就可以看到 arm64-v8a 的 .so 文件夹了
现在已经支持 64 库,但是是否与 32 位有相同的功能和质量,还需要进行进一步的检查和测试。
然后通过 gsyVideoPlayer 的引用说明,我们可以选择 com.shuyu:gsyVideoPlayer-arm64 的版本进行接入,接入修改后,重新进行检测:
我们发现下方的提示并没有消失:
不用紧张,这里是因为三方库命名的问题,通过上图中的 arm64-v8a size 观察到 size 的值已经由原来的 52 变为了 55,接着我们去对应的 apk 里检查一下,在 arm64-v8a 文件夹下是否有 libijkffmpeg.so 、libijkplayer.so 、libijksdl.so 这三个文件。
可以看到,64 位支持的三方 .so 文件已经成功引入了。
虽然把所有支持的 abi 的 so 都打在一个包里,可以用来适配所有设备,但缺点就是包体积会增大,特别是原生库比较多的情况。 如果是 Google 市场的应用包,可以使用 Android App Bundle 来减小体积。但是国内的应用市场暂不支持,不过国内的部分应用市场提供了分别上传 32 位兼容包和 64 位包的能力,所以可以利用构建多个 APK 的能力来打出支持不同 abi 的包,应用市场根据用户手机 CPU 类型分发对应的包,可以减少用户下载包的大小。
然后执行 assembleRelease 这个 task 进行打包,可以在指定目录下看到产出了不同 abi 的包。
接下来要在 64 位手机、32 位手机上进行分别进行功能测试,如何查看自己的手机 CPU 类型呢,可以通过 adb 命令来查看:
命令行中执行 adb shell getprop ro.product.cpu.abi 如果输出 arm64-v8a 则代表该手机 CPU 类型为 64 位。
如果功能测试无误后,即可根据应用市场上传要求进行 Apk 包上传
小结
64 位适配是目前安卓手机应用的主流趋势,做好适配不仅可以迎合政策,还可以提升应用在新机型上的运行效率,虽然国内市场刚刚开始要求,但避免某天因政策影响,导致自己的应用无法上架,还是早做打算的好~
更多精彩请关注我们的公众号「百瓶技术」,有不定期福利呦!
版权声明: 本文为 InfoQ 作者【百瓶技术】的原创文章。
原文链接:【http://xie.infoq.cn/article/c2b41930652a4991c2161c76a】。文章转载请联系作者。
评论