8月不支持 64 位,App 将没法上架 Google Play!须要怎么作?

一. 序

事情是这样的,前几天收到 Google Play 的通知邮件,这才想起来有几款在 Google Play 上架的 App,尚未支持 64 位 CPU 架构。html

早在今年一月份,Google 就发布通知,在今年 8 月 1 日开始,上架的 App,除了提供 32 位的版本以外,还须要提供 64 位的版本。android

这眼看着离强制升级窗口,只剩下最后两个月的时间,不少第三放来源的 so 支持库,若是没有提供 64 位的版本,还须要同步催促合做方更新。git

那今天就来聊聊 Android APK 升级 64 位 CPU 架构的细节,看看你的应用是否须要支持 64 位 CPU 架构,若是要支持,须要作什么?github

二. Android CPU 架构细节

2.1 这是强制规范

早在 2015 年 Google 发布 Android 5.0 版本时,就加入了 64 位处理器的支持,当时就提出了以 19 年 8 月为最后的更新支持期限,并在今年又重申了这个强制要求。shell

只要你的 App 存在国际版,须要上架 Google Play,这个规定都必须准守。bash

2.2 那些 APK 须要支持 64 位?

那假如你有一个国际化的 App 须要维护,在今年 8 月 1 日以后,更新 Google Play 时,就必须提供 64 位的版本。架构

那这里说的 64 位版本支持,究竟是什么?app

若是你的应用,彻底是使用 Java 或者 Kotlin 编写代码,不包含任何原生(Native)的支持,那么就表示这个应用已经支持 64 位。ide

可是应用内使用了任何原生(Native)的支持(so 库),就须要针对这些 so 文件,针对不一样的 CPU 架构提供不一样的版本的 so 支持。性能

须要注意的是,有些时候,在咱们自身的代码中,确实没有用到原生的支持,可是在 App 中使用的一些第三方库中却包含了。

此时最稳妥的方式,就是针对最终打包生成的 APK 文件进行分析,来判断是否须要提供 64 位架构的支持。

那 CPU 架构是什么?什么又是 ABIs?

在 Android 中,虽然 ARM 的 CPU 架构是主流,可是目前至少支持几类 CPU 架构,ARM 下的 ARMv5/ARMv7/ARMv8,x86 下的 x86/x86_64,以及很不常见的 MIPS 类架构。这里的每一种 CPU 类型对应了一种 ABI(Application Binary Interface),例如 armeabi-v7a 中的 "armeabi" 指的就是 ARM 这种类型的 ABI,后面的 “v7a” 指的是 ARMv7。

一般咱们能够简单的理解:

这三个概念是相通的,一般在技术讨论中,说的是一个东西。

2.3 为何是强制的?

谷歌之因此会有强制更新的要求,很大一方面缘由是由于做为开发者,更新补全 ABIs 的动力并不足。

主要缘由来自如下几个方面:

1. APK 体积增大

针对不一样 CPU 架构提供对应的 so 库,固然是效率最高的作法。可是这种作法,最直接的影响,就是 APK 文件的增大,有些时候补全这些 so 支持,会致使整个 APK 体积有几 MB 到几十 MB 的增幅。

APK 体积优化,不少公司都将其算作是一个 KPI 指标,加入一个新特性,致使 APK 体积的增大,在不少时候都是不容许的,为此换技术方案都是常有的事。

从增加的角度来看,越小的 APK,用户下载的意愿就更大,转化率就越高。

可是随着如今流量愈来愈便宜,近期 iOS 已经将 蜂窝数据下载限制从 150MB 放宽至 200MB,针对安装包的体积优化标准,也能够适当的放宽了。

2. 自己有必定的兼容性

应用市场中,不少 APP 其实都只有 armeabi 或者 armeabi-v7a 的支持,而市面上的设备,支持的并非只有这两种 CPU 架构。

可是这并无影响在这些设备上运行这些 App,这就是 CPU 架构的兼容性。

不一样架构,并不意味着之间必定是不兼容的,在不一样版本下,其实提供了两种 ABI 支持,分别是

  • 主要 ABI:与系统自己使用的原生代码同样,最优方案。
  • 辅助 ABI:支持的另外一个 ABI 方案,兼容方案。

这种兼容策略就不在这里展开说了,最简单的就是 64 位的 arm64-v8a 在支持自己的 CPU 架构以外,还兼容支持 armeabi-v7a、armeabi;x86_64 同时也兼容支持 X86 和 armeabi。

你看,虽然添加 64 位的支持,能够有效的使用硬件的优点,提高性能,但大部分时候,采用兼容方案,是一种更简单的方式。

3. 没有对应架构的 so 文件

这个缘由就比较尴尬了,咱们 App 中使用到的原生代码,其实有两种。

一种是咱们本身编写的,源码在手,想提供对应的支持,修改配置从新编译一下就解决了。

另外一种来自第三方提供的,这种时候咱们没有源码,没法作到从新编译,只能和第三方沟通,看能不能提供一个对应 CPU 架构的 so 库。这种状况就很是的不可控了。

例如比较常见的一个 WebView 的替换方案,腾讯 X5 内核,自己就不提供 X86 的库。

官方给的建议是使用 armeabi 或者 armeabi-v7a。

在前文有提到,ABIs 自己是有一些兼容规则的,可是这种兼容规则,是有条件的。

举个例子:64 位的 arm64-v8a 是能够向下兼容的,可是这有个前提,那就是若是你的项目中,有 armeabi-v7a 和 arm64-v8a 两个目录,就须要保证这两个目录下支持的 so 库文件保持一致。

在左边的状况下,若是 arm64-v8a 的手机用到 b.so 时,就会去 arm64-v8a 目录下找,固然是找不到 b.so 文件的,就会直接抛异常,而不会再去 armeabi-v7a 目录下继续寻找。

若是须要提供多套 ABIs 的支持,就须要保证全部 ABI 目录下,对应的 so 文件保持一致。

而在一些特殊的状况下,咱们没法提供对应平台的 so 库,例如腾讯 X5 内核这种状况,就须要作个取舍了。

在没有 Google Play 的强制策略下,同时又由于各方考虑,大多数时候咱们可能会舍弃其余 ABIs 的支持。可是如今既然强制执行了,腾讯 X5 内核就可能升级以提供 64 位的 so 库,毕竟一边是没法上架,另一遍是一个 WebView 的内核,谁都知道怎么取舍。

3、支持 64 位架构

3.1 是否包含 64 位库?

介绍了 Android 下 CPU 架构的一些细节,接下来就要开始正题了,如何升级并支持 64 位架构。

从前文中应该了解到,支持对应的 ABIs,反映在项目中,就是存在对应 ABIs 架构的目录,而且目录中有完备的 so 库支持。

Google 并不要求咱们支持全部的 64 位架构,可是对于已经支持的每种原生 32 位架构,就必须包含对应的 64 位架构。

例如:

  • 对于 ARM 架构,有 armeabi-v7a(32位) 就必须 arm64-v8a(64位)。
  • 对于 x86 架构,有 x86(32位) 就必须有 x86_64(64位)

这就要求咱们有对应的目录,而且目录中包含对应的 so 文件。APK 中提供了完备的 ABIs 支持,运行的以后,会选取对应的最优支持进行加载和使用。

须要注意的是,有时候咱们将 32 位的 so 复制到 64 位中,运行不会出现异常,可是这依然存在隐患。最好的办法是根据不一样的架构,编译对应的 so 文件,原则上,咱们的目标是确保应用能够在仅支持 64 位架构的环境中正常运行。

3.2 判断是否支持 64 位架构

前面也提到,咱们的项目中,可能会引入一些第三方库,致使在不明确的状况下,引入了一些预期以外的 ABIs 库。

一般咱们的作法是在 Gradle 中增长 abiFilters 过滤,来确保不会在打包输出的 APK 中存在预期以外的 ABIs 目录和 so 库。

ndk {
	//设置支持的SO库架构
	abiFilters 'armeabi-v7a' 
}
复制代码

那么咱们拿最终打包输出的 APK 文件去分析,是最稳妥的办法。

分析的方法有两种:

1. AS 的 APK 分析器

在 Android Studio 中,从菜单依次选择 Build → Analyze APK...

选择须要分析的 APK 文件,查看其 lib 目录,是否存在预期的 ABIs 目录以及完备的 so 文件。

2. 使用 zipinfo 命令进行分析

获得待分析的 APK 文件,就能够经过 zipinfo + grep 命令,输出其内包含的 so 文件。

> zipinfo -1 YOUR_APK_FILE.apk | grep \.so$
    lib/armeabi-v7a/libmain.so
    lib/armeabi-v7a/libmono.so
    lib/armeabi-v7a/libunity.so
    lib/arm64-v8a/libmain.so
    lib/arm64-v8a/libmono.so
    lib/arm64-v8a/libunity.so
复制代码

依然是去看对应目录和 so 文件是否完备。

3.3 在 64 位设备上测试应用

支持 64 位架构是为了让咱们利用 CPU 的特性,以提高性能,可是稳定依然是咱们首先要保证的,因此在升级以后,就须要进行测试。

要测试 App,最简单的方式是使用 adb 命令安装该应用,能够配合 --abi 参数,用以指示要将那些 so 库,安装到设备上,这样咱们在这个设备上安装的 App,就会仅包含咱们制定的库。

# 成功安装 APK :
> adb install --abi armeabi-v7a YOUR_APK_FILE.apk
Success
 # 若是 APK 中不包含 64 位 so 文件:
> adb install --abi arm64-v8a YOUR_APK_FILE.apk
adb: failed to install YOUR_APK_FILE.apk: Failure [INSTALL_FAILED_NO_MATCHING_ABIS: Failed to extract native libraries, res=-113]
 # 若是你的设备(手机)不支持 64 位架构
> adb install --abi arm64-v8a YOUR_APK_FILE.apk
ABI arm64-v8a not supported on this device
复制代码

去年上市的手机,大部分都是 64 位架构的,找一款来测试便可。

3.4 分包处理

若是咱们的应用只须要在国内分发,当前的策略对咱们并不影响,保持原样就行了。可是若是存在国际版,须要上架 Google Play 就必定要重视这次升级。

在 Google Play 上传 APK,是能够根据 CPU 架构上传不一样的 APK 的,也就是咱们能够针对 32 位上传一个 APK,再上传一个 64 位的 APK。

此时就须要用到 Gradle 的打包技巧了,分别输出几个仅包含对应平台的 APK,以此完成 Google Play 的要求,分别上传 32 位的支持 APK 和 64 位的支持 APK,这样可以 APK 文件不至于增大不少。

android {
    ... 
    splits {
        abi {
            enable true
            reset()
            include 'x86', 'x86_64', 'armeabi-v7a', 'arm64-v8a' //select ABIs to build APKs for
            universalApk true //generate an additional APK that contains all the ABIs
        }
    }
    // map for the version code
    project.ext.versionCodes = ['armeabi': 1, 'armeabi-v7a': 2, 'arm64-v8a': 3, 'mips': 5, 'mips64': 6, 'x86': 8, 'x86_64': 9]
 
    android.applicationVariants.all { variant ->
        // assign different version code for each output
        variant.outputs.each { output ->
            output.versionCodeOverride =
                    project.ext.versionCodes.get(output.getFilter(com.android.build.OutputFile.ABI), 0) * 1000000 + android.defaultConfig.versionCode
        }
    }
 }
复制代码

这里利用 Gradle 的 splite 配置,有兴趣能够直接查阅文档,就不展开讲了。

四. 小结时刻

在本文中,咱们借这次 Google Play 的强制支持 64 位架构的事情,讲解了 Android 下 so 库的一些兼容问题。

若是你在 Google Play 上有应用须要更新,别忘了提早准备须要的 so 库,大多数原生支持的第三方库,在此以前其实都已经提供了对应的 64 位架构。咱们只须要在最终日期以前,仔细的进行增长 so 文件,以达到适配的效果。

更新完成以后,别忘了测试,本文就到这里,你有什么更新的看法,欢迎在留言区讨论。

本文对你有帮助吗?留言、转发、点好看是最大的支持,谢谢!

reference:


公众号后台回复成长『成长』,将会获得我准备的学习资料,也能回复『加群』,一块儿学习进步;你还能回复『提问』,向我发起提问。

相关文章
相关标签/搜索