Build and Release an Android App - tenji/ks GitHub Wiki

Android 应用编译、打包和发布

一、APK 是什么?

APK 是 Android Package 的缩写,即 Android 安装包。.apk 文件其实就是一个压缩包,把文件的后缀改成 .zip,就可以正常解压,查看内部的相关文件信息了。

二、APK 包含哪些东西?

  1. assets 资源(不是每个项目都有);
  2. lib 包(不是每个项目都有),lib 文件夹里面存放的是 so 动态链接库,so 动态链接库是不需要 apk 打包一些压缩处理的;
  3. META-INF,签名文件夹;
  4. res 资源,里面是二进制的 xml 资源和其他非代码类的资源文件;
  5. AndroidManifest.xml,二进制的;
  6. classes.dex,.dex 文件,就是我们写的 java 代码经过处理得到的;
  7. resources.arsc,记录了所有的应用程序资源目录的信息,将其想象成是一个资源索引表,这个资源索引表在给定资源 ID 和设备配置信息的情况下,能够在应用程序的资源目录中快速地找到最匹配的资源。

三、APK 打包流程

3.1 aapt 打包阶段

使用 aapt 工具来打包 res 资源文件,生成 R.javaresources.arscres 文件。

其中:

  1. 除了 assets 和 res/raw 资源被原装不动地打包进 APK 包中,其它的资源文件都会被编译或者特殊处理(压缩,过滤等);
  2. 除了 assets 资源外,其他资源都会被赋予一个资源 ID,res/raw 也会有资源 ID;
  3. 打包工具负责编译和打包资源,编译完成之后,会生成一个 resources.arsc 文件和一个 R.java,前者保存的是一个资源索引表,后者定义了各个资源 ID 常量。

R 文件存的全部是资源 ID,而 resources.arsc 则存储的是所有资源文件的信息表,包括不同设备下的资源准确定位。

3.2 aidl 处理阶段

aidl 工具解析 aidl 接口定义文件,生成对应的 Java 文件,供下一步程序调用。对于没有使用到 aidl 的 android 工程,可以跳过此步骤。

3.3 Java Compile 阶段

这里调用了 javac 工具编译工程的 src 目录下所有的 java 源文件(R.java、Java 接口文件、Java 源文件),生成的 class 文件位于工程的 bin\classess 目录下。

实际开发过程中,也有可能会使用 android NDK 来编译 native 代码(android SDK 开发),因此,如果可能的话,这一步还需要使用 android NDK 编译 C/C++ 代码。

3.4 dex 转换阶段

通过 dx 工具将 .class 文件和第三方库中的 .class 文件处理生成 classes.dex。dx 工具主要的工作是将 java 字节码转换为 dalvik 字节码、压缩常量池、消除冗余信息等。

3.5 apkbuilder 打包阶段

通过系统构建 apk 脚本,将 classes.dex、resources.arsc、res 文件夹(res/raw 资源被原装不动地打包进 APK 之外,其它的资源都会被编译或者处理)、Other Resources(assets文件夹)、AndroidManifest.xml 打包成 apk 文件。

res/raw 和 assets 的相同点:

两者目录下的文件在打包后会原封不动的保存在 apk 包中,不会被编译成二进制。

res/raw和assets的不同点:

  1. res/raw 中的文件会被映射到 R.java 文件中,访问的时候直接使用资源 ID 即 R.id.filename;assets 文件夹下的文件不会被映射到 R.java 中,访问的时候需要 AssetManager 类;
  2. res/raw 不可以有目录结构,而 assets 则可以有目录结构,也就是 assets 目录下可以再建立文件夹。

3.6 JarSigner 签名阶段

通过 jarsigner 工具对 apk 文件进行签名。

android 的应用程序需要签名才能在 android 设备上安装,签名 apk 文件有两种情况:

  1. 在平时开发的时候,在编译调试程序时会自己使用一个 debug.keystore 对 apk 进行签名,该文件位于 C:\Users\{用户}\.android\ 目录下;
  2. 正式发布时对应用程序打包进行签名,这种情况下需要提供一个符合 android 开发文档中要求的签名文件。

3.7 zipalign 对齐阶段

release 模式下通过 zipalign 工具对签名后的 apk 进行对齐处理。

Zipalign 是一个 android 平台上整理 APK 文件的工具,它对 apk 中未压缩的数据进行 4 字节对齐,对齐后就可以使用 mmap 函数读取文件,每个资源的开始位置上都是上一个资源之后的4字节,访问下一个资源就不用遍历了,有点类似于资源数组化,加快访问速度。

四、Android Studio 打包生成 APK

待更新...

五、APK 安装流程

Android 应用安装有如下四种方式:

  1. 系统应用安装 - 开机时完成,没有安装界面;
  2. 网络下载应用安装 — 通过 market 应用完成,没有安装界面;
  3. ADB 工具安装 - 没有安装界面;
  4. 第三方应用安装 — 通过 SD 卡里的 APK 文件安装,有安装界面,由 packageinstaller.apk(程序安装器)应用处理安装及卸载过程的界面。

应用安装涉及到如下几个目录:

  • system/app:系统自带的应用程序,获得 adb root 权限才能删除;
  • data/app:用户程序安装的目录。安装时把apk文件复制到此目录;
  • data/data:存放应用程序的数据;
  • data/dalvik-cache:将 apk 中的 dex 文件安装到 dalvik-cache 目录下

在应用管理器中执行 .apk 安装需要经过以下几步:

5.1 拷贝文件到指定的目录

在 Android 系统中,apk 安装文件是会被保存起来的,默认情况下,用户安装的 apk 首先会被拷贝到 /data/app 目录下,/data/app 目录是用户有权限访问的目录,在安装 apk 的时候会自动选择该目录存放用户安装的文件,而系统出场的 apk 文件则被放到了 /system 分区下,包括 /system/app,/system/vendor/app,以及 /system/priv-app 等等,该分区只有 ROOT 权限的用户才能访问,这也就是为什么在没有 Root 手机之前,我们没法删除系统出场的 app 的原因了。

5.2 解压缩 apk,保存文件,创建应用的数据目录

为了加快 app 的启动速度,apk 在安装的时候,会首先将 app 的可执行文件 dex 拷贝到 /data/dalvik-cache 目录,缓存起来。然后,在 /data/data/ 目录下创建应用程序的数据目录(以应用的包名命名),存放在应用的相关数据,如数据库、xml 文件、cache、二进制的 so 动态库等。

5.3 解析 apk 的 AndroidManifest.xml 文件

Android 系统中,也有一个类似注册表的东西,用来记录当前所有安装的应用的基本信息,每次系统安装或者卸载了任何 apk 文件,都会更新这个文件。这个文件位于如下目录:/data/system/packages.xml

系统在安装这个 apk 的过程中,会解析 apk 的 AndroidManifest.xml 文件,提取出这个 apk 的重要信息写入到 packages.xml 文件中,这些信息包括:权限、应用包名、APK 的安装位置、版本、userID 等等。由此,我们就知道了为什么一些应用市场和软件管理类的 app 能够很清楚地知道当前手机所安装的所有 app,以及这些 app 的详细信息了。

以上过程都是由 PackageManagerService 完成的,PackageManagerService 处理各种应用的安装,卸载,管理等工作,开机时由 systemServer 启动此服务。

5.4 显示快捷方式

如果这些应用程序在 PackageManagerService 服务注册好了,如果我们想要在 Android 桌面上看到这些应用程序,还需要有一个 Home 应用程序,负责从 PackageManagerService 服务中把这些安装好的应用程序取出来,并以友好的方式在桌面上展现出来,例如以快捷图标的形式。在 Android 系统中,负责把系统中已经安装的应用程序在桌面中展现出来的 Home 应用就是 Launcher 了。

参考链接