Android打包流程

Android 打包流程

参考:

  1. App 的编译和打包流程
  2. Android 打包流程

1. apk内部结构

在这里插入图片描述

  • res 未编译的资源文件

  • resources.arsc是aapt(Android assets packaging tools)生成的资源索引表。这个文件记录了所有的应用程序资源目录的信息,包括每一个资源名称、类型、值、ID以及所配置的维度信息。这个资源索引 标在给定资源ID和设备配置信息的情况下,能够在应用程序的资源目录中快速地找到最匹配的资源。

  • AndroidManifest.xml是编译之后的AndroidManifest文件

  • libs为app需要的so文件

  • classes.dex Android 平台上的可执行文件,Android虚拟机Dalvik支持的字节码文件格式。

  • asserts 额外简历的资源文件夹。res和 assets 的不同在于 res 目录下的文件会在 R 文件中生成对应的资源 ID,而 assets 不会自动生成对应的 ID,而是通过 AssetManager 类的接口来获取。

  • META-INF :用于保存 App 的签名和校验信息,以保证程序的完整性。当生成 APK 包时,系统会对包中的所有内容做一次校验,然后将结果保存在这里。而手机在安装这一 App 时还会对内容再做一次校验,并和 META-INF 中的值进行比较,以避免 APK 被恶意篡改。其中包含如下 三个文件,如下所示

    1. MANIFEST.MF:其中每一个资源文件都有一个对应的 SHA-256-Digest(SHA1) 签名,MANIFEST.MF 文件的 SHA256(SHA1) 经过 base64 编码的结果即为 CERT.SF 中的 SHA256(SHA1)-Digest-Manifest 值。
    2. CERT.SF:除了开头处定义的 SHA256(SHA1)-Digest-Manifest 值,后面几项的值是对 MANIFEST.MF 文件中的每项再次 SHA256(SHA1) 经过 base64 编码后的值。
    3. CERT.RSA:其中包含了公钥、加密算法等信息。首先,对前一步生成的 CERT.SF 使用了 SHA256(SHA1)生成了数字摘要并使用了 RSA 加密,接着,利用了开发者私钥进行签名。然后,在安装时使用公钥解密。最后,将其与未加密的摘要信息(MANIFEST.MF文件)进行对比,如果相符,则表明内容没有被修改。

    详细可参考apk签名原理

2. apk打包流程

在这里插入图片描述

1. 打包资源文件,生成R.java文件(aapt)

打包资源工具是aapt(Android Asset Packaging Tool),在这个过程中,项目中的AndroidManifest.xml文件和布局文件xml都会编译,然后生成相应的R.java,另外AndroidManifest.xml会被aapt编译成二进制。
处理资源文件主要包括两步:

  1. 编译:将资源文件编译为二进制格式(把所有的Android资源文件进行解析,生成扩展名为.flat的二进制文件。比如是png图片,那么就会被压缩处理,采用.png.flat的扩展名)。
  2. 链接:合并所欲已编译的文件并打包到一个软件包中(首先,这一步会生成辅助文件,比如R.java,R文件大家应该都比较熟悉,就是一个资源索引文件,我们平时引用也都是通过R.的方式引用资源id)

最后,会将R文件和之前的二进制文件进行打包,打包到一个APK压缩包(没有dex文件、没有签名)。

2. 处理aidl文件,生成相应的java文件(aidl)

这一过程中使用到的工具是aidl(Android Interface Definition Language),即Android接口描述语言。
aidl工具解析接口定义文件然后生成相应的java代码接口供程序调用,如果在项目中没有使用aidl文件,则可以跳过这一步。

3. 编译项目源代码,生成class文件(javac)

项目中所有的java代码,包括R.java和aidl文件,都会被java编译器(javac)编译成class文件,生成的class文件位于工程中的bin/classes目录下。
注解代码也是在这阶段生成的。当注解的生命周期被设置为CLASS的时候,就代表该朱姐会再编译class文件的时候生效,并且存在与java源文件和class字节码文件。
javac的基础命令:

javac -d destdir(class文件存放目录) srcFile(java文件)
4. 转换所有的class文件,生成clesses.dex文件(dex)

dx工具生成可供Android系统Dalvik虚拟机执行的classes.dex文件。
任何第三方的libraries和class文件都会被转换成dex文件。
dx工具的主要工作是将java字节码转成Dalvik字节码、压缩常量池、消除冗余信息等。

5. 打包成APK文件(apkbuilder)

所有没有编译的资源,如images、assets目录下资源(该类文件是一些原始文件,App打包时并不会对其进行编译,而是直接打包到apk中,对于 这一类资源文件的访问,应用层代码需要通过文件名对其进行访问)。
编译过的资源和dex文件都会被apkbuilder工具打包到最终的apk文件中。
打包的工具apkbuilder位于android-sdk/tools目录下。

6. 对apk文件进行签名(jarsigner)

一旦apk文件生成,必须被签名才能被安装在设备上。
在开发过程中,主要用到的就是两种签名的keystore。一种是用于调试的debug.keystore,它主要用与调试,在Android studio中直接run后跑在手机上的就是使用debug.keystore。另一种就是用于发布正式版本的keystore。

7. 对签名后的apk文件进行对齐处理(zipalign)

如果发布的apk是正式版的话,就必须对apk进行对齐处理,用到的工具是zipalign。
zipalign主要工作是将apk包进行对齐处理。使apk包中的所有资源文件,起始偏移4字节的整数倍,这样通过mmap内存映射访问apk时的速度更快。
mmap

3. gradle task

上面涉及到的Android打包流程是以gradle task链的形式串联起来的。

下面看一下常见的task

> Task :app:preBuild UP-TO-DATE
> Task :app:preDebugBuild UP-TO-DATE
> Task :app:compileDebugAidl NO-SOURCE
> Task :app:compileDebugRenderscript NO-SOURCE
> Task :app:generateDebugBuildConfig UP-TO-DATE
> Task :app:javaPreCompileDebug UP-TO-DATE
> Task :app:checkDebugAarMetadata UP-TO-DATE
> Task :app:generateDebugResValues UP-TO-DATE
> Task :app:generateDebugResources UP-TO-DATE
> Task :app:mergeDebugResources UP-TO-DATE
> Task :app:createDebugCompatibleScreenManifests UP-TO-DATE
> Task :app:extractDeepLinksDebug UP-TO-DATE
> Task :app:processDebugMainManifest UP-TO-DATE
> Task :app:processDebugManifest UP-TO-DATE
> Task :app:processDebugManifestForPackage UP-TO-DATE
> Task :app:processDebugResources UP-TO-DATE
> Task :app:compileDebugJavaWithJavac UP-TO-DATE
> Task :app:mergeDebugShaders UP-TO-DATE
> Task :app:compileDebugShaders NO-SOURCE
> Task :app:generateDebugAssets UP-TO-DATE
> Task :app:mergeDebugAssets UP-TO-DATE
> Task :app:compressDebugAssets UP-TO-DATE
> Task :app:processDebugJavaRes NO-SOURCE
> Task :app:mergeDebugJavaResource UP-TO-DATE
> Task :app:checkDebugDuplicateClasses UP-TO-DATE
> Task :app:desugarDebugFileDependencies UP-TO-DATE
> Task :app:mergeExtDexDebug UP-TO-DATE
> Task :app:mergeLibDexDebug UP-TO-DATE
> Task :app:dexBuilderDebug UP-TO-DATE
> Task :app:mergeProjectDexDebug UP-TO-DATE
> Task :app:mergeDebugJniLibFolders UP-TO-DATE
> Task :app:mergeDebugNativeLibs UP-TO-DATE
> Task :app:stripDebugDebugSymbols NO-SOURCE
> Task :app:validateSigningDebug UP-TO-DATE
> Task :app:packageDebug UP-TO-DATE

> Task :app:installDebug
//aidl 转换aidl文件为java文件
> Task :app:compileDebugAidl

//生成BuildConfig文件
> Task :app:generateDebugBuildConfig

//获取gradle中配置的资源文件
> Task :app:generateDebugResValues

// merge资源文件
> Task :app:mergeDebugResources

// merge assets文件
> Task :app:mergeDebugAssets
> Task :app:compressDebugAssets

// merge所有的manifest文件
> Task :app:processDebugManifest

//AAPT 生成R文件
> Task :app:processDebugResources

//编译kotlin文件
> Task :app:compileDebugKotlin

//javac 编译java文件
> Task :app:compileDebugJavaWithJavac

//转换class文件为dex文件
> Task :app:dexBuilderDebug

//打包成apk并签名
> Task :app:packageDebug


生成BuildConfig文件,资源文件
在引入Gradle编译工具之后,Apk的打包流程就多了这么一步,生成BuildConfig文件和资源文件。也就是会根据build.gradle里面配置的内容生成相应的java代码或者res代码,简单举个例子:

 //build.gradle
    buildTypes {
        debug{
            buildConfigField("boolean", "ISDEBUG", "true")
            resValue "string", "TestName", "love1"
        }
        release {
            buildConfigField("boolean", "ISDEBUG", "false")
            resValue "string", "TestName", "love2"
        }
    }

    //BuildConfig.java
    public final class BuildConfig {
    // Field from build type: debug
    public static final boolean ISDEBUG = true;
 }

 R.string.TestName

merge资源文件
这一步就是合并res资源文件,assets文件,manifest文件。
因为在项目中会依赖不同的库、组件,也会有多渠道的需求,所以merge这一步操作就是将不同地方的资源文件进行整合,多个manifest文件需要整理成一个完整的文件,所以如果有属性冲突这一步就会报错。资源文件也会整理分类到不同的分辨率目录中。

附件(详细版打包流程图):
在这里插入图片描述

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值