赞
踩
要了解APK的打包流程,我们首先来了解下打包完成以后APK包里面包含哪些东西。.apk文件其实就是一个压缩文件,把文件的后缀改成.zip就可以用解压软件解压了:
apk是一个压缩包,里面有lib,META-INF,classes.dex,res,resources.arsc文件夹和文件。下面看看它们各自的作用。
我们发现xml文件都不能直接被识别了这是因为:xml文件都被aapt编译成二进制的xml文件,将文本格式的xml转为二进制格式的xml原因有以下两点:二进制格式的XML文件占用空间更小;二进制格式的XML文件解析速度更快。
Android Studio默认采用gradle组织完成打包过程,对开发者来说简单的执行相关的task即可,这种透明的打包过程也让我们忽略了很多细节。
打包工具详解.
工具名称 | 功能介绍 | 路径 |
---|---|---|
aapt | Android资源打包工具 打包res资源文件,生成R.java、resources.arsc和res文件(二进制 & 非二进制如res/raw和pic保持原样) | {SDK_PATH}/platform-tools/{tools_version}/appt.exe |
aidl | Android接口描述语言转化为.java文件的工具 | {SDK_PATH}/platform-tools/{tools_version}/aidl.exe |
javac | Java Compiler java代码转class文件 | {JDK_HOME}/javac |
dex | 转化.class文件为Davik VM能识别的.dex文件 | {JDK_HOME}/platform-tools/{tools_version}/dx.bat |
apkbuilder | 所有没有编译的资源,如images、assets目录下资源,编译过的资源和.dex文件都会被apkbuilder工具打包到最终的.apk文件中 | {JDK_HOME}/tools/opkbuilder |
jarsigner | .jar文件的签名工具,一旦APK文件生成,它必须被签名才能被安装在设备上。一种是用于调试的debug.keystore 一种就是用于发布正式版本的release.keystore | {JDK_HOME}/jarsigner |
zipalign | 字节码对齐工具,对齐的主要过程是将APK包中所有的资源文件距离文件起始偏移为4字节整数倍,这样通过内存映射访问apk文件时的速度会更快。对齐的作用就是减少运行时内存的使用。 | {JDK_HOME}/tools/zipalign |
打包资源文件的工具是aapt(The Android Asset Packaing Tool),目录 sdk\build-tools\25.0.0\aapt。
在这个过程中,项目中的AndroidManifest.xml文件和布局文件XML都会编译,然后生成相应的R.java,另外AndroidManifest.xml会被aapt编译成二进制。
存放在APP的res目录下的资源,该类资源在APP打包前大多会被编译,变成二进制文件,并会为每个该类文件赋予一个resource id。对于该类资源的访问,应用层代码则是通过resource id进行访问的。
Android应用在编译过程中aapt工具会对资源文件进行编译,并生成一个resource.arsc文件,resource.arsc文件相当于一个文件索引表,记录了很多跟资源相关的信息。
处理aidl文件的工具是aidl(Android Interface Definition Language),即Android接口描述语言,目录 sdk\build-tools\25.0.0\aidl。
aidl工具解析接口定义文件然后生成相应的Java代码接口供程序调用。如果在项目没有使用到aidl文件,则可以跳过这一步。
编译源代码使用工具是 Java编译器(javac)
项目中所有的Java代码,包括R.java和.aidl文件,都会变Java编译器(javac)编译成.class文件,生成的class文件位于工程中的bin/classes目录下。
这过程使用工具 dx(dex)生成可供Android系统Dalvik虚拟机执行的classes.dex文件,工具目录(sdk\build-tools\25.0.0\dx)。
任何第三方的libraries和.class文件都会被转换成.dex文件。dx工具的主要工作是将Java字节码转成 Dalvik字节码、压缩常量池、消除冗余信息等。
打包的工具apkbuilder,目录 android-sdk/tools,apkbuilder为一个脚本文件,实际调用的是(sdk\tools\lib)文件中的com.android.sdklib.build.ApkbuilderMain类。
所有没有编译的资源,如images、assets目录下资源(该类文件是一些原始文件,APP打包时并不会对其进行编译,而是直接打包到APP中,对于这一类资源文件的访问,应用层代码需要通过文件名对其进行访问);
编译过的资源和.dex文件都会被apkbuilder工具打包到最终的.apk文件中。
一旦APK文件生成,它必须被签名才能被安装在设备上。
在开发过程中,主要用到的就是两种签名的keystore。一种是用于调试的debug.keystore,它主要用于调试,在Eclipse或者Android Studio中直接run以后跑在手机上的就是使用的debug.keystore;
另一种就是用于发布正式版本的relese.keystore,需要开发者自己配置。
如果你发布的apk是正式版的话,就必须对APK进行对齐处理,用到的工具是zipalign,目录 sdk\build-tools\25.0.0\zipalign。
对齐的主要过程是将APK包中所有的资源文件距离文件起始偏移为4字节整数倍,这样通过内存映射访问apk文件时的速度会更快。对齐的作用就是减少运行时内存的使用。
综上所述, Android SDK中build-tools目录提供了各种程序, 都是独立可运行的,可以认为Android Studio编译打包过程是对这些工具的封装。
通过上文可以了解到APK打包的脚本都是在SDK文件夹下面的:
编译工具目录,包含了转化为davlik虚拟机的编译工具,比如adb、和aapt、aidl、dx等文件。
Android模拟器模拟器目录。
该文件下存放了Google提供的USB驱动,Intel提供的硬件加速附件工具包。
是每个平台SDK真正的文件,存放不同版本的Android系统。对应android studio build.gradle中的compileSdkVersion
各个版本的通用工具。比如 adb、sqlite3、fastboot等.
包含了各个版本的SDK源码。
存放的是创建Android虚拟机时的镜像文件(已经编译好的镜像文件,模拟器可以直接加载)。
tools:这个文件夹下存放了大量Android开发、调试的工具。包括测试、调试、第三方工具。模拟器、数据管理工具等。
gradle 运行时自动生成的目录(自动编译工具产生的文件),版本由wrapper指定。一般情况不做修改,不需要纳入项目源代码管理中。
Intellij IDEA 运行时候生成的文件目录,一般情况不做修改,不需要纳入项目源代码管理中。
众所周知,Android应用最终是打包成.apk格式(其实就是一个压缩包),然后安装至手机并运行的。APK即Android Package的缩写。
应用程序管理服务PackageManagerService安装应用程序的过程,其实就是解析析应用程序配置文件AndroidManifest.xml的过程,并从里面得到得到应用程序的相关信息,
例如得到应用程序的组件Activity、Service、Broadcast Receiver和Content Provider等信息,有了这些信息后,通过ActivityManagerService这个服务,我们就可以在系统中正常地使用这些应用程序了。
在Android系统中,apk安装文件是会被保存起来的,默认情况下,用户安装的apk首先会被拷贝到 /data/app 目录下。
/data/app目录是用户有权限访问的目录,在安装apk的时候会自动选择该目录存放用户安装的文件,而系统出厂的apk文件则被放到了 /system 分区下,包括 /system/app,/system/vendor/app,以及 /system/priv-app 等等,该分区只有Root权限的用户才能访问,这也就是为什么在没有Root手机之前,我们无法删除系统出厂的app的原因了。
为了加快app的启动速度,apk在安装的时候,会首先将app的可执行文件(dex)拷贝到 /data/dalvik-cache 目录,缓存起来。
然后,在/data/data/目录下创建应用程序的数据目录(以应用的包名命名),存放应用的相关数据,如数据库、xml文件、cache、二进制的so动态库等等。
Android系统中,也有一个类似注册表的东西,用来记录当前所有安装的应用的基本信息,每次系统安装或者卸载了任何apk文件,都会更新这个文件。这个文件位于如下目录:
/data/system/packages.xml
系统在安装apk的过程中,会解析apk的AndroidManifinest.xml文件,提取出这个apk的重要信息写入到packages.xml文件中,这些信息包括:权限、应用包名、APK的安装位置、版本、userID等等。
由此,我们就知道了为啥一些应用市场和软件管理类的app能够很清楚地知道当前手机所安装的所有的app,以及这些app的详细信息了。
另外一件事就是Linux的用户Id和用户组Id,以便他可以获得合适的运行权限。
以上这些都是由PackageServiceManager完成的,下面我们会重点介绍PackageServiceManager。
这些应用程序只是相当于在PackageManagerService服务注册好了,如果我们想要在Android桌面上看到这些应用程序,还需要有一个Home应用程序,负责从PackageManagerService服务中把这些安装好的应用程序取出来,并以友好的方式在桌面上展现出来,例如以快捷图标的形式。在Android系统中,负责把系统中已经安装的应用程序在桌面中展现出来的Home应用程序就是Launcher了
将app的包名、版本号、安装路径等保存在data/system/packages.xml文件中,以备下次安装时再次使用;
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。