常见的Android文件格式 - APK
APK的生成流程
APK 的生成是 代码编译、资源处理、打包签名 的流水线式过程
Java/Kotlin 代码 资源文件
↓ ↓
编译为字节码 资源编译(AAPT2)
↓ ↓
.class → DEX 生成 resources.arsc
↘ ↓ ↙
APK 打包(zip 格式)
↓
签名(Jarsigner/APK Signer)
↓
最终 APK/ZIP 对齐优化(zipalign)
Java/Kotlin代码编译
- 输入:.java/.kt文件、依赖库(AAR/JAR)
- 工具:javac(Java)、kotlinc(Kotlin)
- 输出: .class字节码文件
- 关键过程:
- Java -> .class(JVM字节码)
- Kotlin -> .class(通过Kotlin编译器)
DEX转换
- 工具:D8或R8(取代旧版DX)
- 输入: 所有.class文件
- 输出: 单个/多个class.dex文件
- 作用: 将JVM字节码转为Android设备可执行的DEX格式
d8 --output ./out/ app.jar library.jar
资源处理阶段
资源编译与打包
-
工具:AAPT2
-
输入: /res/*(图片、XML布局) , AndroidManifest.xml.
-
输出:
- resources.arsc(二进制资源索引表),res/转换为二进制格式(如 layout.xml -> layout.bin)
-
作用:
- 资源ID分配
- 优化资源加载速度
# 示例:AAPT2 编译资源
aapt2 compile -o out/ res/layout/activity_main.xml
aapt2 link -o base.apk --manifest AndroidManifest.xml -I android.jar
APK打包阶段
- 工具:zip格式打包(通过Gradle或apkbuilder)
- 输入: DEX、资源文件、原生库(.so)、AndroidManifest.xml
- 输出: 未签名的APK(包含所有组件)
- 文件结构
APK ├── AndroidManifest.xml # 二进制格式 ├── classes.dex # 可执行代码 ├── res/ # 二进制资源 ├── resources.arsc # 资源索引 └── lib/ # .so 原生库(可选)
APK签名阶段
- 目的:确保APK的完整性和开发者身份认证
- 工具:
- jarsigner(传统工具)
- apksigner(官方推荐,支持v2/v3签名方案)
- 流程:
- 生成Keystore(密钥库)
keytool -genkey -v -keystore my.keystore -alias mykey -keyalg RSA -validity 1000
- 对APK签名
apksigner sign --ks my.keystore --ks-key-alias mykey app-unsigned.apk
- 生成Keystore(密钥库)
ZIP对齐优化
- 工具:zipalign
- 作用:调整APK中文件的对齐方式,以优化内存访问效率
- 命令:
zipalign -v 4 input.apk output-aligned.apk
APK安装流程
- 用户触发安装APK->系统启动PackageInstaller界面。
- 复制APK到临时目录(如/data/app/vmdlxxx.tmp)。
- 解析APK信息(包名、权限等)-> 验证签名和兼容性。
- 分配应用专属目录(如/data/app/<包名>-XXXX/) -> 复制APK到该目录。
- DEX优化(由dexopt转换为OAT文件)。
- 更新系统数据库(packages.xml) -> 注册应用信息。
- 广播通知安装完成->应用状态生效。
详解内部运作机制
触发安装:前端交互
-
用户场景:用户打开APK文件,系统调用PackageInstaller应用。
- PackageManagerService(PMS)
- 功能:管理应用安装、卸载、权限授予。
- 启动时机:系统启动时由 SystemServer 初始化。
- 核心方法
public void installPackageAsUser(String apkPath, int flags, int userId);
- PackageManagerService(PMS)
-
系统行文:
- Intent.ACTION_VIEW → 交由 PackageInstallerActivity 处理。
- 权限检查:校验安装来源(如 Settings.Secure.INSTALL_NON_MARKET_APPS)
复制到临时目录
- 临时存储路径:/data/app/vmdlXXXXXX.tmp(由系统生成唯一文件名)
- 关键服务:PackageManagerService(PMS)的 installPackageAsUser 方法
APK解析与验证
- 解析内容:
- 提取 AndroidManifest.xml(转为二进制后解析)
- 读取包名、版本号、权限列表(uses-permission)、SDK 要求等
- 签名验证:
- 检查签名证书的合法性(防止篡改)
- 对比现有签名(更新应用时需一致)
应用目录分配
- 目标路径:/data/app/<包名>-XXXX/(存储 APK 和私有数据)。
- 示例:/data/app/com.example.app-1a2b3c/
- lib 目录:.so 文件解压到子目录 /lib/abi/(如 armeabi-v7a)
- 文件权限:设置 -rw-r--r--(用户私有,其他应用不可读)
DEX 优化(关键步骤)
- 流程:
- 原始 DEX 转换为 OAT 格式(ART 虚拟机优化)
- 输出至 /data/dalvik-cache/arm64/
- 工具链:
- dex2oat(编译器,将 DEX 转为机器码)
- 优化级别:speed(完全编译)或 quicken(快速优化)
数据库更新
- 关键文件:
- /data/system/packages.xml:存储包名、UID、权限、签名等信息。
- /data/system/packages.list:记录包名与数据目录的映射。
- 权限授权:将 uses-permission 声明的权限写入 PMS 内存映射。
广播通知安装结果
- 发送广播:Intent.ACTION_PACKAGE_ADDED → 通知系统和其他应用。
- 回调处理:系统服务更新状态(如 Launcher 刷新应用列表)