【朝花夕拾】Android性能篇之(四)Apk打包

简介: 随着IDE功能的不断加强,APK的打包几乎被一手包办,使得很多Android程序员并不了解其过程。而深入了解APK的打包流程,有助于更好地理解APK的结构及Android机制,也能很好地感受到Anroid虚拟机在优化道路上孜孜不倦的追求。

前言

        APK,即Android Package,是将android程序和资源整合在一起,形成的一个.apk文件。相信所有的Android程序员是在IDE的帮助下,完成打包轻而易举,但对打包流程真正清楚的可能并不多。本章的内容比较简单,也是非常基础的内容,但是对理解android应用的结构却有很大的帮助。笔者写这篇文章的目的,一方面是为了弥补这方面的盲点,回顾和梳理apk打包方面的理论知识点;第二方面,是为了给后续写Android虚拟机知识做铺垫,进而去研究android的性能优化,这也是把这篇文章放到Android性能优化系列文章当中的原因;第三方面,也是为了方便读者理解Android虚拟机的相关内容。

       对于在IDE,如Android Studio上操作打包的过程,本文不做演示,对于更深入的源码分析,也不在本文讨论之列,出于前面说到的原因,本文只简单阐述其打包流程,本文主要内容如下:

         

 

一、apk构建流程图

     以下截图为Google官方提供的详细的apk构建过程图,其中包含了各个环节所用到的工具和中间相关的文件。

                

                         apk构建过程(绿色部分为对应环节工具,蓝色部分为相关文件)

 

二、构建过程中所用工具

        如下截图展示了apk构建过程中所使用的部分工具,这些工具大部分都在sdk/build-tools/文件夹下:

                 

                  

                    代码混淆所用工具

                 

                                   打包所用工具所在的jar包

三、apk打包流程详解

       依据如上的流程图和工具图,下面咱们按照流程顺序对其进行讲解。

  1、aapt打包资源

  • 工具:aapt(Android Asset Package Tool Android资源打包工具)
  • 工具路径:sdkpath/build-tools/版本号/aapt.exe和aapt2.exe
  • 输入:Android资源文件、AndroidManifest.xml
  • 输出: R.java类、二进制的resource.arsc,res文件夹(包括二进制的xml、没被改变的图片和res/raw文件)、二进制的AndroidManifest.xml文件、没有改变的assets文件夹。

        Android的资源文件包含了两类:1)assets类资源。该类资源放在工程目录的assets根目录下,存放一些原始文件,这些文件不会被编译为二进制文件,而是被原封不动地打包在apk文件中,同样也不能通过资源ID来查找,不保存在R文件中。2)res类资源,10种目录。这类资源保存在工程目录中的res目录下,包含了animator(属性动画资源)、anim(补间动画资源)、color(对象颜色状态选择资源)、drawable(xml或Bitmap文件的图像资源)、layout(布局文件资源)、menu(程序菜单资源)、mipmap(图标资源,推荐阅读:drawable与mipmap的区别)、raw(不被编译成二进制文件的资源,注意和assets资源的区别,推荐阅读:assets和raw的区别)、values(6种不同的值:数组arrays.xml、颜色值colors.xml、尺寸dimens.xml、字符串strings.xml和样式值styles.xml)、xml(描述应用程序配置信息的资源)。

       如下截图展示了R.java的内容,其中包含了各种静态内部类,分别对应了某种资源的类型。

       

                            R.java结构图

      以R.string类为例,其中展示了字符串名称对应的id值,就是对应在res/values文件夹下,string字符串资源。

      

                                                                    R.string结构图

        推荐阅读:apk打包安装过程

  2、aidl生成跨进程通信的java文件

  • 工具:aidl(Android Interface Definition Language安卓接口定义语言)
  • 工具路径:sdkpath/build-tools/版本号/aidl.exe
  • 输入:aidl后缀的文件,位于工程项目src/main/aidl目录下
  • 输出:可用于进程间通信的C/S端java代码,位于build/generated/source/aidl

          

                                       工程项目中的aidl原始文件

          

                                       aidl工具处理后生成的java文件

  3、Java编译源码

  • 工具:javac.exe
  • 工具路径:jdk/bin/javac.exe
  • 输入:java source文件夹、aapt中生成的R.java文件、aidl生成的java文件、BuildConfig.java文件
  • 输出:对于gradle编译,生成的class文件保存在build/intermediates/classes里

         

                               BuildConfig.java和R.java文件

         

                                              输出的class文件

  4、proguard代码混淆

        完成javac编译之后,一般还会对其进行代码的混淆,其实就是类似于加密的功能,作用就是增加反编译的难度,同时也将一些代码的命名进行了缩短,减少代码占用的空间。推荐阅读:Android代码混淆零基础入门

  • 工具:ProGuard
  • 工具路径:sdk/tools/proguard/bin/proguard.bat
  • 输入:被编译过的class文件、混淆配置文件proguard-rules.pro
  • 输出:被混淆过的.class文件、混淆前后映射文件

         

  5、将所有.class文件转化为classes.dex文件

  • 工具:dx.bat
  • 工具路径:sdkpath/build-tools/版本号/dx.bat
  • 输入:编译后生成的所有.class文件、第三方库和.class文件
  • 输出:可以在Android虚拟机上使用的.dex文件

       调用dx.bat将所有的class文件转化为classes.dex文件,将二进制码转化为Android虚拟机(Android4.4以前虚拟机是Dalvik,4.4上是Dalvik和ART可以切换、Android5.0及以后是ART)上的字节码、生成常量池、消除冗余数据等。由于Android虚拟机是一种针对嵌入式设备而特殊设计的java虚拟机,所有dex文件与标准的class文件在结构设计上有着很大的区别,当javac将java程序编译成class后,dx工具将所有的class文件整合到一个dex文件中,这样做使得各个类能够共享数据,在一定程度上降低了容易,同时也使文结构更加紧凑,实验表明,dex文件时传统jar文件的50%左右。class文件结构和dex文件结构比对如下(该部分还会在后文讲Android虚拟机时提到):

           

                     .class文件和.dex文件结构对比图

  6、apkbuilder打包生成apk

  • 工具:ApkBuilder类
  • 工具路径:sdkpath/tools/lib/sdklib_xxx.jar
  • 输入:上一步生成的classes.dex文件,aapt时生成的resources.arsc、被编译后的res文件夹、AndroidManifest.xml,Other Resouces(assets文件夹)
  • 输出:.apk文件(Android Package)

  7、对apk进行签名

  • 工具:apksigner.bat
  • 工具路径:sdkpath/build-tools/版本号/apksigner.bat
  • 输入:上一步中生成的.apk文件、签名文件(Debug or Release Keystore)
  • 输出:签名后的.apk文件

      签名是一个apk身份的证明,Android系统在安装apk的时候,首先会检验apk的签名,如果发现签名文件不存在或者校验签名失败,就会拒绝安装。对一个apk文件签名后,apk文件根目录下回增加META-INF目录,该目录下有三个文件:

        

               META-IINF文件夹结构

      Android系统就是根据这三个文件的内容对apk文件进行签名验证的:

      MANIFEST.MF中包含对apk中除了/META-INF文件夹外所有文件的签名值。

      

                                                 MANIFEST.MF内容截图

      CERT.SF是对MANIFEST.MF文件整体签名以及其中各个条目的签名。一般地,如果是使用工具签名,还多包括一项,就是对MANIFEST.MF头部信息签名。

      

                                                               CERT.SF内容截图

      CERT.RSA包含用私钥对CERT.SF的签名以及包含公钥信息的数字证书。用一般的文本打开后,会显示乱码。

      

                          CETR.RSA内容截图

      推荐阅读:Android签名有什么用?

                      Android签名过程详解

  8、zipalign优化

      如果是在release mode下,还会对apk进行align,即对签名后的apk进行对齐处理,这种方式是对apk进行整理和优化。

  • 工具:zipalign
  • 工具路径:sdkpath/build-tools/版本号/zipalign.exe
  • 输入:上一步中签名后的apk文件
  • 输出:优化后的apk文件

 

四、APK文件结构

      一个apk解压后,其典型的结构如下所示,分别在apk打包流程中appt资源打包、javac编译、签名阶段所产生:

      

相关文章
|
15天前
|
移动开发 Java Android开发
构建高效Android应用:探究Kotlin与Java的性能差异
【4月更文挑战第3天】在移动开发领域,性能优化一直是开发者关注的焦点。随着Kotlin的兴起,其在Android开发中的地位逐渐上升,但关于其与Java在性能方面的对比,尚无明确共识。本文通过深入分析并结合实际测试数据,探讨了Kotlin与Java在Android平台上的性能表现,揭示了在不同场景下两者的差异及其对应用性能的潜在影响,为开发者在选择编程语言时提供参考依据。
|
19天前
|
缓存 监控 Java
构建高效Android应用:从优化用户体验到提升性能
在竞争激烈的移动应用市场中,为用户提供流畅和高效的体验是至关重要的。本文深入探讨了如何通过多种技术手段来优化Android应用的性能,包括UI响应性、内存管理和多线程处理。同时,我们还将讨论如何利用最新的Android框架和工具来诊断和解决性能瓶颈。通过实例分析和最佳实践,读者将能够理解并实施必要的优化策略,以确保他们的应用在保持响应迅速的同时,还能够有效地利用系统资源。
|
26天前
|
缓存 移动开发 Android开发
提升安卓应用性能的实用策略
在移动开发领域,应用的性能优化是一个持续的挑战。对于安卓开发者而言,确保应用流畅、快速并且电池使用效率高,是吸引和保持用户的关键因素之一。本文将深入探讨针对安卓平台的性能优化技巧,包括内存管理、代码效率、UI渲染以及电池寿命等方面的考量。这些策略旨在帮助开发者构建出更高效、响应更快且用户体验更佳的安卓应用。
|
28天前
|
数据库 Android开发 UED
提升安卓应用性能的十大技巧
【2月更文挑战第30天】在移动设备上,应用程序的性能直接影响用户体验。本文将分享10个优化安卓应用性能的技巧,包括代码优化、内存管理、UI设计和使用性能分析工具等,帮助开发者提高应用的运行速度和响应时间,从而提升用户满意度。
|
28天前
|
Java 编译器 Android开发
构建高效Android应用:探究Kotlin与Java的性能差异
【2月更文挑战第30天】 随着Kotlin成为开发Android应用的首选语言,开发者社区对于其性能表现持续关注。本文通过深入分析与基准测试,探讨Kotlin与Java在Android平台上的性能差异,揭示两种语言在编译效率、运行时性能和内存消耗方面的具体表现,并提供优化建议。我们的目标是为Android开发者提供科学依据,帮助他们在项目实践中做出明智的编程语言选择。
|
1月前
|
监控 测试技术 Android开发
提升安卓应用性能的实用策略
【2月更文挑战第24天】 在竞争激烈的应用市场中,性能优化是提高用户体验和应用成功的关键。本文将探讨针对安卓平台的性能优化技巧,包括内存管理、多线程处理和UI渲染效率的提升。我们的目标是为开发者提供一套实用的工具和方法,以诊断和解决性能瓶颈,确保应用流畅运行。
|
1月前
|
安全 Java Android开发
构建高效Android应用:探究Kotlin与Java的性能差异
【2月更文挑战第24天】在移动开发领域,性能优化一直是开发者关注的焦点。随着Kotlin在Android开发中的普及,了解其与Java在性能方面的差异变得尤为重要。本文通过深入分析和对比两种语言的运行效率、启动时间、内存消耗等关键指标,揭示了Kotlin在实际项目中可能带来的性能影响,并提供了针对性的优化建议。
27 0
|
1月前
|
安全 Java Android开发
构建高效安卓应用:探究Kotlin与Java的性能对比
【2月更文挑战第22天】 在移动开发的世界中,性能优化一直是开发者们追求的关键目标。随着Kotlin在安卓开发中的普及,许多团队面临是否采用Kotlin替代Java的决策。本文将深入探讨Kotlin和Java在安卓平台上的性能差异,通过实证分析和基准测试,揭示两种语言在编译效率、运行时性能以及内存占用方面的表现。我们还将讨论Kotlin的一些高级特性如何为性能优化提供新的可能性。
51 0
|
1月前
|
安全 Java Android开发
构建高效Android应用:探究Kotlin与Java的性能差异
【2月更文挑战第18天】 在Android开发领域,Kotlin和Java一直是热门的编程语言选择。尽管两者在功能上具有相似性,但它们在性能表现上的差异却鲜有深入比较。本文通过一系列基准测试,对比了Kotlin与Java在Android平台上的运行效率,揭示了两种语言在处理速度、内存分配以及电池消耗方面的差异。此外,文章还将探讨如何根据性能测试结果,为开发者提供在实际应用开发中选择合适语言的建议。
|
1月前
|
JavaScript Android开发
【问题篇】打包Vue-cli3创建的vue项目成App的apk文件
【问题篇】打包Vue-cli3创建的vue项目成App的apk文件
24 0