armosu哪个微商做什么产品比较好好用?

思源一号上的OSU基准测试

思源一号使用 osu_latency 测量点对点通信延迟

作业脚本 osu_latency.slurm 在两个节点上各启动一个MPI进程,测量两个MPI进程之间的通信延迟。

思源一号上使用 osu_mbw_mr 测量点对点通信带宽

作业脚本 osu_bw.slurm 在两个节点上各启动一个MPI进程,测量两个MPI进程之间的通信带宽。

思源一号上使用 osu_bcast 测量广播延迟

需要注意广播延迟和参与测试的节点数量正相关,如果需要对比性能,要保证测试作业所用的节点数一致。

作业脚本 osu_latency.slurm 在两个节点上各启动一个MPI进程,测量两个MPI进程之间的通信延迟。

作业脚本 osu_bw.slurm 在两个节点上各启动一个MPI进程,测量两个MPI进程之间的通信带宽。

需要注意广播延迟和参与测试的节点数量正相关,如果需要对比性能,要保证测试作业所用的节点数一致。

作业脚本 osu_latency.slurm 在两个节点上各启动一个MPI进程,测量两个MPI进程之间的通信延迟。

作业脚本 osu_bw.slurm 在两个节点上各启动一个MPI进程,测量两个MPI进程之间的通信带宽。

需要注意广播延迟和参与测试的节点数量正相关,如果需要对比性能,要保证测试作业所用的节点数一致。

}

这是【Android 修炼手册】系列第 10 篇文章,如果还没有看过前面系列文章,欢迎点击 查看~

看完本文可以达到什么程度

我们现在大部分开发都是基于 Android Studio 进行的,在 AS 中,我们只需要点击 Run 按钮,AS 自动会打包 Apk 安装至设备中并运行。对于我们来说,其中的打包过程就是一个黑盒,我们所知道的就是 Sources -> AS Compiler -> APK。这篇文章我们就分析一下中间的打包过程,以及打包相关的一些问题。

我们先了解一下 APK 内部的结构。

接下来我们看看一个正常的 APK 的结构。

一个 APK 打包完之后,通常有下面几个目录,用来存放不同的文件。

原生资源文件,不会被压缩或者处理

java 代码通过 javac 转化成 class 文件,再通过 dx 文件转化成 dex 文件。如果有多个 dex 文件,其命名会是这样的:

保存了 native 库 .so 文件,其中会根据 cpu 型号划分不同的目录,比如 ARM,x86 等等。

保存了处理后的二进制资源文件。

保存了资源 id 名称以及资源对应的值/路径的映射。

MANIFEST.MF 保存了所有文件对应的摘要,部分内容如下:

CERT.RSA 包含了对 CERT.SF 文件的签名以及签名用到的证书。

这个文件大家都很熟悉了,全局配置文件,不过这里是编译处理过的二进制的文件。

我们在上面看了一个完整 APK 的结构,APK 打包的过程其实就是生成上述文件的过程。这里放一张网上流传比较广的流程图。

2.2 如何手动使用命令行打包

平时的开发都是使用 gradle 构建,下面我们不依赖 gradle,直接用官方提供的各个阶段的打包工具,手动用命令行打一个 APK,可以更好更详细的了解其中的过程。
这里直接用 工程做示例。

开始之前,我们先创建一个 tmp 目录用来存放中间产物。创建 tmp/final 存放最终产物。

使用 aapt2 对单个资源处理,会生成 xxx.flat 文件,是 aapt2 的中间产物,可以用于后面的资源增量编译。我们这里通过 --dir 直接指定了资源的目录,产物 res 是一个压缩包,里面包含了所有资源处理后的 xxx.flat。

这里我们再把 res 这个压缩包解压一下。执行下面的命令。

这一步结束以后,目录是这个样子的。

执行命令后,会生成 res.apk,里面就是 resource.arsc,处理后的 AndroidManifest.xml 以及 处理后的二进制资源。我们这里也把他解压出来,后面最终打包的时候使用。执行命令如下。

这一步结束以后,目录状态如下。

│ │ ├── xxx 资源目录

这一步我们需要处理 java 文件,生成 class 文件。要用到上一步生成的 R.java 文件。执行下面的命令。

这一步结束以后,目录状态如下。

│ │ ├── xxx 资源目录

这一步是把上一步生成的 class 文件编译为 dex 文件,需要用到 d8 或者 dx,这里用 d8。执行下面的命令。

命令执行完以后,会生成 classes.dex,这就是最终 apk 里需要的 dex 文件,我们把它拷贝到 final/ 目录下。执行如下命令。

这一步结束以后,目录状态如下。

│ │ ├── xxx 资源目录

执行完上述的命令,打包 APK 需要的材料就都准备好了,因为 APK 本身就是 zip 格式,这里我们直接用 zip 命令打包上述产物,生成 final.apk。执行下面的命令。

上一步打包好的 APK 还不能直接安装,因为没有签名,我们这里用 debug.keystore 给 final.apk 签名。执行下面的命令。

这样,最后的 final.apk 就是我们手动生成的 apk 了。可以安装尝试一下了~

正常开发中,我们大部分都是直接点击 AS 中的 Run 去编译一个 APK。

上面介绍了 Android APK 的打包流程,也通过手动打 APK 体验了整个流程。

在实际的生产开发过程中,我们往往会把 APK 发往各个应用市场,很多时候要根据市场渠道进行一些统计,所以就需要对不同的市场渠道进行区分。关于多渠道打包的问题,有不少解决方式。

最容易想到的就是使用 Gradle 的 Flavor,使用 Flavor 的特性,生成不同的渠道标识。不过这种方式每生成一个渠道包都需要执行一遍构建过程,非常耗时。

另外一种方式就是使用 apktool 反编译 APK,修改其中的资源,添加渠道的标识,并进行重新打包签名,这种方式省去了构建过程,反编译,打包,签名这几个步骤也比较耗时。按照美团博客的数据,打包 900 个渠道包将近三个小时。

所以需要再寻找其他的方法。在此之前,我们先看下 Android APK 签名的方式。了解了签名方式,才能更好的去了解方法实现。

在了解 APK 签名之前,我们先看一下 Zip 的文件格式,因为 APK 本质上是一个 Zip 文件,而多渠道打包就涉及到 Zip 的文件格式。

APK 的本质是一个 Zip 文件,我们可以用 file 命令看一下。是 V2.0 版本的 Zip 格式文件。

一个 Zip 文件的格式基本如下:

主要可以分为三个大区域:

记录了文件的压缩信息,主要内容如下:

文件在磁盘上的起始位置

官方文档中没有对 Digital signature 有太具体的介绍,但是有提到 核心目录是可以压缩和加密的,盲猜是用来加密核心目录的。

3.1.3 核心目录结束标志

目录结束标志是在整个文件的结尾,用于标记压缩目录数据的结束。每个 Zip 文件有且只有一个结束标志记录。

核心目录起始位置的磁盘编号
磁盘上记录的核心目录数量
核心目录起始位置的偏移

上面基本上就是一个通用的 Zip 包结构了。
下面就看看 Android 的签名机制。

MANIFEST.MF 保存了所有文件对应的摘要,部分内容如下:

CERT.RSA 包含了对 CERT.SF 文件的签名以及签名用到的证书。

在 APK 签名时,主要流程如下:

在 APK 校验时,主要流程如下:

我们在上面讲了 Zip 文件的结构,通过上面校验过程,我们可以发现,在 APK 校验过程中,只是校验了数据区的内容,剩余的两个部分没有做处理。

所以如果修改剩余两个部分,签名校验过程中是不会发现的,要写入信息,EOCD 的注释字段是很好的选择。所以将渠道信息写入 EOCD 的注释字段,就可以达到打入渠道信息的目的。这就是腾讯 VasDolly 做的事情。

除此之外,我们可以发现,APK 签名校验过程中,并没有对 META-INF 文件夹下的文件进行签名和校验,所以可以在 META-INF 文件夹下新增一个空文件,这样也可以携带渠道信息。这就是美团做的事情。

本来使用上述方案,一切都是很美好的,然而在 Android 7.0 的时候,引入新的签名方式,APK Signature Scheme v2,导致 V1 上的多渠道签名方案失效。我们先看看 V2 签名的原理。

按照来看,V2 签名是在 数据区和核心目录区之间,新增了一个 APK Signing Block 区块,用来记录签名信息。

签名块的长度,和第一个字段一样

在校验签名时,会按照下面的逻辑进行。

在 Android 9.0 中引入了新的签名方式 V3。为了解决签名签名过期的问题。V3 签名在 V2 的 APK Signing Block 中新增了一个签名块,保存了 supported SDK 版本以及密钥流转结构。由于对 V2 结构没有进行大的更改,所以不会对多渠道打包方案造成影响。关于 V3 签名更具体的信息,可以查看。

上面说的 APK 结构和打包,都是完整包含了所有资源,包括适配不同的分辨率,适配不同的 API 等等,但其实在每一个用户设备上,只会用到其中的一种,其余的资源只会占用包大小。所以 Google 也提供了一些其他方法,可以根据不同分辨率,不同 ABI 等等来打包,从而减少包大小。

在 Android L 之后,Android 支持了 Multiple APKs,简单来说就是可以通过不同分辨率,不同 CPU 架构,不同 API level 把同一个应用打包成对应不同设备的多个 APK,然后在不同的设备上安装不同的 APK,来减少体积。

里提供的了详细的解释,我们这里看一下,通过配置不同分辨率,生成的 APK 是什么样的。

含义很清楚了,就不多解释了。然后我们编译,可以看到,生成的 APK 不是一个,而是四个。

其中 simpleapk-universal-debug.apk 是包含了所有资源的完整 APK。其他三个 apk 分别是根据不同分辨率生成的。其中只包含了对应分辨率需要的资源。从而减少了包大小。我们可以对比一下两个 APK 就看出区别了。

Android L 以后提供了 Split APKs 的多 APK 构建机制,可以将一个 APK 基于 CPU 架构,屏幕密度等纬度拆分成多个 APK,当下载应用时,会依据当前的设备配置选择对应的 APK 安装。

Base APK 包含了通用的资源,而 Split APK 就是用户设备特有的资源。用户安装时会安装 Base APK 以及其设备对应的 Split APK,从而减少了其他无用资源的包大小。

和传统安装方式对比如下。

.aab 本质也是一个 zip 文件,我们解压看看。包里的内容如下。

我们可以通过 Google 提供的 将 .aab 文件生成 APK。执行下面的命令。

当然现在 App Bundle 的使用,完全依赖于 Google Play,所以国内还是无法使用的。不过对其原理的了解,我们也能知道 Google 是如何区减少包大小的。






这是【Android 修炼手册】系列第 10 篇文章,如果还没有看过前面系列文章,欢迎点击 查看~

看完本文可以达到什么程度

我们现在大部分开发都是基于 Android Studio 进行的,在 AS 中,我们只需要点击 Run 按钮,AS 自动会打包 Apk 安装至设备中并运行。对于我们来说,其中的打包过程就是一个黑盒,我们所知道的就是 Sources -> AS Compiler -> APK。这篇文章我们就分析一下中间的打包过程,以及打包相关的一些问题。

我们先了解一下 APK 内部的结构。

接下来我们看看一个正常的 APK 的结构。

一个 APK 打包完之后,通常有下面几个目录,用来存放不同的文件。

原生资源文件,不会被压缩或者处理

java 代码通过 javac 转化成 class 文件,再通过 dx 文件转化成 dex 文件。如果有多个 dex 文件,其命名会是这样的:

保存了 native 库 .so 文件,其中会根据 cpu 型号划分不同的目录,比如 ARM,x86 等等。

保存了处理后的二进制资源文件。

保存了资源 id 名称以及资源对应的值/路径的映射。

MANIFEST.MF 保存了所有文件对应的摘要,部分内容如下:

CERT.RSA 包含了对 CERT.SF 文件的签名以及签名用到的证书。

这个文件大家都很熟悉了,全局配置文件,不过这里是编译处理过的二进制的文件。

我们在上面看了一个完整 APK 的结构,APK 打包的过程其实就是生成上述文件的过程。这里放一张网上流传比较广的流程图。

2.2 如何手动使用命令行打包

平时的开发都是使用 gradle 构建,下面我们不依赖 gradle,直接用官方提供的各个阶段的打包工具,手动用命令行打一个 APK,可以更好更详细的了解其中的过程。
这里直接用 工程做示例。

开始之前,我们先创建一个 tmp 目录用来存放中间产物。创建 tmp/final 存放最终产物。

使用 aapt2 对单个资源处理,会生成 xxx.flat 文件,是 aapt2 的中间产物,可以用于后面的资源增量编译。我们这里通过 --dir 直接指定了资源的目录,产物 res 是一个压缩包,里面包含了所有资源处理后的 xxx.flat。

这里我们再把 res 这个压缩包解压一下。执行下面的命令。

这一步结束以后,目录是这个样子的。

执行命令后,会生成 res.apk,里面就是 resource.arsc,处理后的 AndroidManifest.xml 以及 处理后的二进制资源。我们这里也把他解压出来,后面最终打包的时候使用。执行命令如下。

这一步结束以后,目录状态如下。

│ │ ├── xxx 资源目录

这一步我们需要处理 java 文件,生成 class 文件。要用到上一步生成的 R.java 文件。执行下面的命令。

这一步结束以后,目录状态如下。

│ │ ├── xxx 资源目录

这一步是把上一步生成的 class 文件编译为 dex 文件,需要用到 d8 或者 dx,这里用 d8。执行下面的命令。

命令执行完以后,会生成 classes.dex,这就是最终 apk 里需要的 dex 文件,我们把它拷贝到 final/ 目录下。执行如下命令。

这一步结束以后,目录状态如下。

│ │ ├── xxx 资源目录

执行完上述的命令,打包 APK 需要的材料就都准备好了,因为 APK 本身就是 zip 格式,这里我们直接用 zip 命令打包上述产物,生成 final.apk。执行下面的命令。

上一步打包好的 APK 还不能直接安装,因为没有签名,我们这里用 debug.keystore 给 final.apk 签名。执行下面的命令。

这样,最后的 final.apk 就是我们手动生成的 apk 了。可以安装尝试一下了~

正常开发中,我们大部分都是直接点击 AS 中的 Run 去编译一个 APK。

上面介绍了 Android APK 的打包流程,也通过手动打 APK 体验了整个流程。

在实际的生产开发过程中,我们往往会把 APK 发往各个应用市场,很多时候要根据市场渠道进行一些统计,所以就需要对不同的市场渠道进行区分。关于多渠道打包的问题,有不少解决方式。

最容易想到的就是使用 Gradle 的 Flavor,使用 Flavor 的特性,生成不同的渠道标识。不过这种方式每生成一个渠道包都需要执行一遍构建过程,非常耗时。

另外一种方式就是使用 apktool 反编译 APK,修改其中的资源,添加渠道的标识,并进行重新打包签名,这种方式省去了构建过程,反编译,打包,签名这几个步骤也比较耗时。按照美团博客的数据,打包 900 个渠道包将近三个小时。

所以需要再寻找其他的方法。在此之前,我们先看下 Android APK 签名的方式。了解了签名方式,才能更好的去了解方法实现。

在了解 APK 签名之前,我们先看一下 Zip 的文件格式,因为 APK 本质上是一个 Zip 文件,而多渠道打包就涉及到 Zip 的文件格式。

APK 的本质是一个 Zip 文件,我们可以用 file 命令看一下。是 V2.0 版本的 Zip 格式文件。

一个 Zip 文件的格式基本如下:

主要可以分为三个大区域:

记录了文件的压缩信息,主要内容如下:

文件在磁盘上的起始位置

官方文档中没有对 Digital signature 有太具体的介绍,但是有提到 核心目录是可以压缩和加密的,盲猜是用来加密核心目录的。

3.1.3 核心目录结束标志

目录结束标志是在整个文件的结尾,用于标记压缩目录数据的结束。每个 Zip 文件有且只有一个结束标志记录。

核心目录起始位置的磁盘编号
磁盘上记录的核心目录数量
核心目录起始位置的偏移

上面基本上就是一个通用的 Zip 包结构了。
下面就看看 Android 的签名机制。

MANIFEST.MF 保存了所有文件对应的摘要,部分内容如下:

CERT.RSA 包含了对 CERT.SF 文件的签名以及签名用到的证书。

在 APK 签名时,主要流程如下:

在 APK 校验时,主要流程如下:

我们在上面讲了 Zip 文件的结构,通过上面校验过程,我们可以发现,在 APK 校验过程中,只是校验了数据区的内容,剩余的两个部分没有做处理。

所以如果修改剩余两个部分,签名校验过程中是不会发现的,要写入信息,EOCD 的注释字段是很好的选择。所以将渠道信息写入 EOCD 的注释字段,就可以达到打入渠道信息的目的。这就是腾讯 VasDolly 做的事情。

除此之外,我们可以发现,APK 签名校验过程中,并没有对 META-INF 文件夹下的文件进行签名和校验,所以可以在 META-INF 文件夹下新增一个空文件,这样也可以携带渠道信息。这就是美团做的事情。

本来使用上述方案,一切都是很美好的,然而在 Android 7.0 的时候,引入新的签名方式,APK Signature Scheme v2,导致 V1 上的多渠道签名方案失效。我们先看看 V2 签名的原理。

按照来看,V2 签名是在 数据区和核心目录区之间,新增了一个 APK Signing Block 区块,用来记录签名信息。

签名块的长度,和第一个字段一样

在校验签名时,会按照下面的逻辑进行。

在 Android 9.0 中引入了新的签名方式 V3。为了解决签名签名过期的问题。V3 签名在 V2 的 APK Signing Block 中新增了一个签名块,保存了 supported SDK 版本以及密钥流转结构。由于对 V2 结构没有进行大的更改,所以不会对多渠道打包方案造成影响。关于 V3 签名更具体的信息,可以查看。

上面说的 APK 结构和打包,都是完整包含了所有资源,包括适配不同的分辨率,适配不同的 API 等等,但其实在每一个用户设备上,只会用到其中的一种,其余的资源只会占用包大小。所以 Google 也提供了一些其他方法,可以根据不同分辨率,不同 ABI 等等来打包,从而减少包大小。

在 Android L 之后,Android 支持了 Multiple APKs,简单来说就是可以通过不同分辨率,不同 CPU 架构,不同 API level 把同一个应用打包成对应不同设备的多个 APK,然后在不同的设备上安装不同的 APK,来减少体积。

里提供的了详细的解释,我们这里看一下,通过配置不同分辨率,生成的 APK 是什么样的。

含义很清楚了,就不多解释了。然后我们编译,可以看到,生成的 APK 不是一个,而是四个。

其中 simpleapk-universal-debug.apk 是包含了所有资源的完整 APK。其他三个 apk 分别是根据不同分辨率生成的。其中只包含了对应分辨率需要的资源。从而减少了包大小。我们可以对比一下两个 APK 就看出区别了。

Android L 以后提供了 Split APKs 的多 APK 构建机制,可以将一个 APK 基于 CPU 架构,屏幕密度等纬度拆分成多个 APK,当下载应用时,会依据当前的设备配置选择对应的 APK 安装。

Base APK 包含了通用的资源,而 Split APK 就是用户设备特有的资源。用户安装时会安装 Base APK 以及其设备对应的 Split APK,从而减少了其他无用资源的包大小。

和传统安装方式对比如下。

.aab 本质也是一个 zip 文件,我们解压看看。包里的内容如下。

我们可以通过 Google 提供的 将 .aab 文件生成 APK。执行下面的命令。

当然现在 App Bundle 的使用,完全依赖于 Google Play,所以国内还是无法使用的。不过对其原理的了解,我们也能知道 Google 是如何区减少包大小的。






这是【Android 修炼手册】系列第 10 篇文章,如果还没有看过前面系列文章,欢迎点击 查看~

看完本文可以达到什么程度

我们现在大部分开发都是基于 Android Studio 进行的,在 AS 中,我们只需要点击 Run 按钮,AS 自动会打包 Apk 安装至设备中并运行。对于我们来说,其中的打包过程就是一个黑盒,我们所知道的就是 Sources -> AS Compiler -> APK。这篇文章我们就分析一下中间的打包过程,以及打包相关的一些问题。

我们先了解一下 APK 内部的结构。

接下来我们看看一个正常的 APK 的结构。

一个 APK 打包完之后,通常有下面几个目录,用来存放不同的文件。

原生资源文件,不会被压缩或者处理

java 代码通过 javac 转化成 class 文件,再通过 dx 文件转化成 dex 文件。如果有多个 dex 文件,其命名会是这样的:

保存了 native 库 .so 文件,其中会根据 cpu 型号划分不同的目录,比如 ARM,x86 等等。

保存了处理后的二进制资源文件。

保存了资源 id 名称以及资源对应的值/路径的映射。

MANIFEST.MF 保存了所有文件对应的摘要,部分内容如下:

CERT.RSA 包含了对 CERT.SF 文件的签名以及签名用到的证书。

这个文件大家都很熟悉了,全局配置文件,不过这里是编译处理过的二进制的文件。

我们在上面看了一个完整 APK 的结构,APK 打包的过程其实就是生成上述文件的过程。这里放一张网上流传比较广的流程图。

2.2 如何手动使用命令行打包

平时的开发都是使用 gradle 构建,下面我们不依赖 gradle,直接用官方提供的各个阶段的打包工具,手动用命令行打一个 APK,可以更好更详细的了解其中的过程。
这里直接用 工程做示例。

开始之前,我们先创建一个 tmp 目录用来存放中间产物。创建 tmp/final 存放最终产物。

使用 aapt2 对单个资源处理,会生成 xxx.flat 文件,是 aapt2 的中间产物,可以用于后面的资源增量编译。我们这里通过 --dir 直接指定了资源的目录,产物 res 是一个压缩包,里面包含了所有资源处理后的 xxx.flat。

这里我们再把 res 这个压缩包解压一下。执行下面的命令。

这一步结束以后,目录是这个样子的。

执行命令后,会生成 res.apk,里面就是 resource.arsc,处理后的 AndroidManifest.xml 以及 处理后的二进制资源。我们这里也把他解压出来,后面最终打包的时候使用。执行命令如下。

这一步结束以后,目录状态如下。

│ │ ├── xxx 资源目录

这一步我们需要处理 java 文件,生成 class 文件。要用到上一步生成的 R.java 文件。执行下面的命令。

这一步结束以后,目录状态如下。

│ │ ├── xxx 资源目录

这一步是把上一步生成的 class 文件编译为 dex 文件,需要用到 d8 或者 dx,这里用 d8。执行下面的命令。

命令执行完以后,会生成 classes.dex,这就是最终 apk 里需要的 dex 文件,我们把它拷贝到 final/ 目录下。执行如下命令。

这一步结束以后,目录状态如下。

│ │ ├── xxx 资源目录

执行完上述的命令,打包 APK 需要的材料就都准备好了,因为 APK 本身就是 zip 格式,这里我们直接用 zip 命令打包上述产物,生成 final.apk。执行下面的命令。

上一步打包好的 APK 还不能直接安装,因为没有签名,我们这里用 debug.keystore 给 final.apk 签名。执行下面的命令。

这样,最后的 final.apk 就是我们手动生成的 apk 了。可以安装尝试一下了~

正常开发中,我们大部分都是直接点击 AS 中的 Run 去编译一个 APK。

上面介绍了 Android APK 的打包流程,也通过手动打 APK 体验了整个流程。

在实际的生产开发过程中,我们往往会把 APK 发往各个应用市场,很多时候要根据市场渠道进行一些统计,所以就需要对不同的市场渠道进行区分。关于多渠道打包的问题,有不少解决方式。

最容易想到的就是使用 Gradle 的 Flavor,使用 Flavor 的特性,生成不同的渠道标识。不过这种方式每生成一个渠道包都需要执行一遍构建过程,非常耗时。

另外一种方式就是使用 apktool 反编译 APK,修改其中的资源,添加渠道的标识,并进行重新打包签名,这种方式省去了构建过程,反编译,打包,签名这几个步骤也比较耗时。按照美团博客的数据,打包 900 个渠道包将近三个小时。

所以需要再寻找其他的方法。在此之前,我们先看下 Android APK 签名的方式。了解了签名方式,才能更好的去了解方法实现。

在了解 APK 签名之前,我们先看一下 Zip 的文件格式,因为 APK 本质上是一个 Zip 文件,而多渠道打包就涉及到 Zip 的文件格式。

APK 的本质是一个 Zip 文件,我们可以用 file 命令看一下。是 V2.0 版本的 Zip 格式文件。

一个 Zip 文件的格式基本如下:

主要可以分为三个大区域:

记录了文件的压缩信息,主要内容如下:

文件在磁盘上的起始位置

官方文档中没有对 Digital signature 有太具体的介绍,但是有提到 核心目录是可以压缩和加密的,盲猜是用来加密核心目录的。

3.1.3 核心目录结束标志

目录结束标志是在整个文件的结尾,用于标记压缩目录数据的结束。每个 Zip 文件有且只有一个结束标志记录。

核心目录起始位置的磁盘编号
磁盘上记录的核心目录数量
核心目录起始位置的偏移

上面基本上就是一个通用的 Zip 包结构了。
下面就看看 Android 的签名机制。

MANIFEST.MF 保存了所有文件对应的摘要,部分内容如下:

CERT.RSA 包含了对 CERT.SF 文件的签名以及签名用到的证书。

在 APK 签名时,主要流程如下:

在 APK 校验时,主要流程如下:

我们在上面讲了 Zip 文件的结构,通过上面校验过程,我们可以发现,在 APK 校验过程中,只是校验了数据区的内容,剩余的两个部分没有做处理。

所以如果修改剩余两个部分,签名校验过程中是不会发现的,要写入信息,EOCD 的注释字段是很好的选择。所以将渠道信息写入 EOCD 的注释字段,就可以达到打入渠道信息的目的。这就是腾讯 VasDolly 做的事情。

除此之外,我们可以发现,APK 签名校验过程中,并没有对 META-INF 文件夹下的文件进行签名和校验,所以可以在 META-INF 文件夹下新增一个空文件,这样也可以携带渠道信息。这就是美团做的事情。

本来使用上述方案,一切都是很美好的,然而在 Android 7.0 的时候,引入新的签名方式,APK Signature Scheme v2,导致 V1 上的多渠道签名方案失效。我们先看看 V2 签名的原理。

按照来看,V2 签名是在 数据区和核心目录区之间,新增了一个 APK Signing Block 区块,用来记录签名信息。

签名块的长度,和第一个字段一样

在校验签名时,会按照下面的逻辑进行。

在 Android 9.0 中引入了新的签名方式 V3。为了解决签名签名过期的问题。V3 签名在 V2 的 APK Signing Block 中新增了一个签名块,保存了 supported SDK 版本以及密钥流转结构。由于对 V2 结构没有进行大的更改,所以不会对多渠道打包方案造成影响。关于 V3 签名更具体的信息,可以查看。

上面说的 APK 结构和打包,都是完整包含了所有资源,包括适配不同的分辨率,适配不同的 API 等等,但其实在每一个用户设备上,只会用到其中的一种,其余的资源只会占用包大小。所以 Google 也提供了一些其他方法,可以根据不同分辨率,不同 ABI 等等来打包,从而减少包大小。

在 Android L 之后,Android 支持了 Multiple APKs,简单来说就是可以通过不同分辨率,不同 CPU 架构,不同 API level 把同一个应用打包成对应不同设备的多个 APK,然后在不同的设备上安装不同的 APK,来减少体积。

里提供的了详细的解释,我们这里看一下,通过配置不同分辨率,生成的 APK 是什么样的。

含义很清楚了,就不多解释了。然后我们编译,可以看到,生成的 APK 不是一个,而是四个。

其中 simpleapk-universal-debug.apk 是包含了所有资源的完整 APK。其他三个 apk 分别是根据不同分辨率生成的。其中只包含了对应分辨率需要的资源。从而减少了包大小。我们可以对比一下两个 APK 就看出区别了。

Android L 以后提供了 Split APKs 的多 APK 构建机制,可以将一个 APK 基于 CPU 架构,屏幕密度等纬度拆分成多个 APK,当下载应用时,会依据当前的设备配置选择对应的 APK 安装。

Base APK 包含了通用的资源,而 Split APK 就是用户设备特有的资源。用户安装时会安装 Base APK 以及其设备对应的 Split APK,从而减少了其他无用资源的包大小。

和传统安装方式对比如下。

.aab 本质也是一个 zip 文件,我们解压看看。包里的内容如下。

我们可以通过 Google 提供的 将 .aab 文件生成 APK。执行下面的命令。

当然现在 App Bundle 的使用,完全依赖于 Google Play,所以国内还是无法使用的。不过对其原理的了解,我们也能知道 Google 是如何区减少包大小的。






}

艾莉主办的偶像赛S2-EP2之偶像猜猜赛的第二轮活动视频!本周为Nanahira专场! 你能从rep一眼认出他们的身份吗? 活动玩法规则:从艾莉提供的5张图中任选一张,在离线模式下打好rep;所有rep将被剪辑成一个完整的带有5首歌的视频,随后玩家观看视频并猜每个编号所对应的玩家真实身份,猜对最多的获胜并可获得艾莉提供的一个月supporter奖励~ 活动皮肤:艾莉原创爱酱皮肤,偶像团专用,并不公开_(:з」∠)_ 活动彩蛋:艾莉提供 ——爱你们的艾莉★

}

我要回帖

更多关于 armelle 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信