Android apk打包流程★

本文详细介绍了Android APK的打包过程,包括aapt打包资源文件生成R.java,aidl处理接口,javac编译源码,DX转换为dex,ApkBuilder打包资源和dex,KeyStore签名以及ZipAlign对齐处理。每一步骤都详细阐述了其工具、操作和作用,对于理解APK的生成至关重要。

1.apk打包

Android开发中打包apk主要有两种方式:

①使用Android Studio集成直接生成apk;
②使用ant工具在命令行方式下打包apk。

不管哪种方式,打包apk的本质过程都是一样的。

Android的apk包文件包括两部分:代码和资源。所以打包也分为资源打包和代码打包两个方面。

apk打包的流程图:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5a2f6Iqz6Iqz,size_20,color_FFFFFF,t_70,g_se,x_16

①aapt打包资源文件,生成R.java文件

②aidl处理aidl文件,生成相应的Java文件

③javac编译源代码+R+aidl,生成class文件

④DX将所有的class文件转换成dex文件

⑤ApkBuilder将资源文件、dex文件打包成apk

⑥KeyStore对apk文件进行签名

⑦ZipAlig对签名后的apk文件进行对齐处理

 

2.打包流程

①通过aapt工具打包资源文件,生成R.java文件

资源文件主要包括AndroidManifest.xml、布局文件、各种xml资源等。这些资源文件都会被编译,生成相应的R.java文件。(注意:assets和res/raw两个目录里的文件不会在这一步打包,它们都会在打包apk的时候直接打包到apk中,携带在应用里面供应用访问,而且不会被编译成二进制)

打包资源的工具是aapt,全称是Android Asset Packaging Tool。aapt有一个可执行的aapt.exe在Android SDK的build-tools下,选择要编译的SDK版本,如23.0.1,在该目录下命令行里运行指令:

aapt.exe package -f -m -J E:\MyApp\bin (产物R.java输出的目录)  

-S MyApp\app\src\main\res (资源文件夹路径)

-I D:\Tools\AndroidSDK\platforms\android-23\android.jar (本地android.jar路径)

-M E:\MyApp\app\src\main\AndroidManifest.xml (项目AndroidManifest.xml)

aapt 参数的含义:

-f 如果编译出来的文件已经存在,强制覆盖。

-m 使生成的包的目录放在-J参数指定的目录。

-J 指定生成的R.java的输出目录

-S res文件夹路径

-A assert文件夹的路径

-M AndroidManifest.xml的路径

-I 某个版本平台的android.jar的路径

-F 具体指定apk文件的输出

②通过aidl工具处理aidl文件,生成相应的Java文件

这一过程使用的工具是aidl(Android Interface Definition Language),即Android接口描述语言。

AIDL的可执行文件也在Android SDK 的build-tools下,aidl.exe。aidl工具解析接口定义文件然后生成相应的Java代码接口供程序调用。

aidl.exe -IE:\MyApp\app\src (项目路径)

  -oE:\MyApp\bin (.java文件输出)

 E:\MyApp\app\src\main\aidl\com\mytemplateapp\IMyAidlInterface.aidl (需要编译的AIDL文件)

如果在项目没有使用到aidl文件,则可以跳过这一步。

③通过javac工具编译项目源代码,生成class文件

把R.java跟AIDL的java文件编译出来以后,就可以跟其他java源文件一起编译成class文件了。

项目中所有的Java代码,包括R.java和.aidl文件,都会被Java编译器(javac)编译成.class文件,生成的class文件位于工程中的bin/classes目录下。

javac -encoding UTF-8

-bootclasspath D:\Tools\AndroidSDK\platforms\android-23\android.jar

-d E:\MyApp\bin (产物输出路径)

E:\MyApp\app\src\main\java\com\mytemplateapp\*.java                                              

E:\MyApp\bin\com\mytemplateapp\R.java

E:\MyApp\bin\com\mytemplateapp\IMyAidlInterface.java

④通过DX工具将编译好的class文件转换成dex文件

dx工具生成可供Android系统Dalvik虚拟机执行的classes.dex文件,该工具位于android-sdk/platform-tools 目录下。

任何第三方的libraries和.class文件都会被转换成.dex文件。

该过程主要完成将Java字节码转成Dalvik字节码、压缩常量池、消除冗余信息等工作。

dx.bat --dex --output=E:\MyApp\bin\classes.dex E:\MyApp\bin

此处选择class文件的路径需要注意,class文件绝对路径在“E:MyAppbin commytemplateapp”,但是在命令行输入时应该输入到“E:MyAppbin ”,这样编译时className才会跟path对应上。(commytemplateapp 是包名)

⑤通过ApkBuilder工具将资源文件、dex文件打包生成APK文件

所有没有编译的资源(如images等)、编译过的资源和.dex文件都会被apkbuilder工具打包到最终的.apk文件中。

打包的工具apkbuilder位于android-sdk/tools目录下。apkbuilder为一个脚本文件,实际调用的是android-sdk/tools/lib/sdklib.jar文件中的com.android.sdklib.build.ApkbuilderMain类。

⑥使用KeyStore对APK文件进行签名

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

用SDK自带的一个debug key进行签名:

jarsigner -verbose -keystore C:\Users\Administrator\.android\debug.keystore

-storepass android

-keypass android

E:\MyApp\bin\test_unsigned.apk

androiddebugkey

⑦通过ZipAlig工具对签名后的APK文件进行对齐处理

如果发布的apk是正式版的话,就必须对APK进行对齐处理,用到的工具是zipalign,它位于android-sdk/tools目录下。

对齐的过程是将APK文件中所有的资源文件距离文件的起始距离都偏移为4字节的整数倍,这样通过内存映射访问apk文件时速度会更快。对齐的作用就是减少运行时内存的使用。

zipalign -f 4 ./testbuild/out/test_unsigned.apk ./testbuild/out/test_signed.apk

到此,apk就打包成功了,可以通过ADB安装到手机上了。

 

3.资源的编译和打包

Android应用程序的设计是代码与资源相分离的,Android的资源文件可以分为两大类:

①assets

assets资源放在主工程assets目录下,它里面保存一些原始的文件,可以以任何方式来进行组织,这些文件最终会原封不动的地被打包进APK文件中。

获取asset资源十分简单:

InputStream is getAssets.open("fileName");

②res

res资源放在主工程的res目录下,这类资源一般都会在编译阶段生成一个资源ID。

res资源包含了开发中使用的各种资源,具体有:animator、anim、color、drawable、layout、menu、raw、values、Xml。这9种类型的资源文件,除了raw类型资源以及Bitmap文件的drawable类型资源之外,其它的资源文件均为文本格式的XML文件,它们在打包的过程中,会被编译成二进制格式的XML文件。这些二进制格式的XML文件分别有一个字符串资源池,用来保存文件中引用到的每一个字符串,包括XL元素标签、属性名称、属性值,以及其它的一切文本值所使用到的字符串。这样原来在文本格式的XML文件中的每一个放置字符串的地方在二进制格式的XML文件中都被替换成一个索引到字符串资源池的整数值,这写整数值统一保存在R.javai类中,R.java会和其他源文件一起编译到APK中去。

前面提到xml编写的Android资源文件都会编译成二进制格式的xm文件,资源的打包都是由AAPT工具来完成的,资源打包主要有以下流程:

①解析AndroidManifest.xml,获得应用程序的包名称,创建资源表。

②添加被引用资源包,被添加的资源会以一种资源ID的方式定义在R.javat中。

③资源打包工具创建一个AaptAssets对象,收集当前需要编译的资源文件,收集到的资源保存在AaptAssets对象对象中。

④将上一步AaptAssets对象保存的资源,添加到资源表ResourceTable中去,用于最终生成资源描述文件resources.arsC。

⑤编译values类资源,这类资源包括数组、颜色、尺寸、字符串等值。

⑥给bag、style、.arrayi这类资源分配资源ID。

⑦编译xml资源文件,编译的流程分为四步:解析xm文件;赋予属性名称资源D;解析属性值:将xm文件从文本格式转换为二进制格式。

⑧生成资源索引表resources.arsc。

 

4.资源ID

每个Android项目里都有有一个R.java文件:

public final class R {

    public static final class anim {

        public static final int abc_fade_in=0x7f010000;

    }

    public static final class attr {

        public static final int actionBarDivider=0x7f020000;

    }

    public static final class String {

        public static final int actionBarDivider=0x7f020000;

    }

}

每个资源项后的整数就是资源D,资源D是一个4字节的无符整数。

最高字节是Package ID表示命名空间,标明资源的来源,Android系统自己定义了两个Package ID,系统资源命名空间:0x01和应用资源命名空间:0x7f。

次字节是Type ID,表示资源的类型,例如:anim、color、string等。

最低两个字节是Entry ID,表示资源在其所属资源类型中所出现的次序。

资源索引上面提到,最终生成的是资源索引表resources.arsc,Android正是利用这个索引表根据资源D进行资源的查找,为不同语言、不同地区、不同设备提供相对应的最佳资源。查找和通过Resources和AssetManger来完成的。

 

resources.arsc索引表从上至下文件格式依次为:

文件头:数据结构用ResTable_header来描述,用来描述整个文件的信息,包括文件头大小,文件大小,资源包Package的数量等信息。

全局字符串池:存放所有的字符串,所以资源复用这些字符串,字符串里存放的是资源文件的路径名和资源值等信息。

资源包:会有多个(例如:系统资源包、应用资源包)。

 

资源包也被划分为以下几个部分:

包头:描述资原包相关信息。

资源类型字符串池:存放资源的类型。

资源名称字符串池:存放资源的名称。

配置列表:存放语音、位置等手机配置信息,用来作为查找资源的标准。

从这里可以看到resources.arsc索引表存在很多常量池,常量池的使用目的也很明显,就是提供资源的复用率,减少resources.arsc索引表的体积,提高索引效率。

 

assets和res/raw的区别在于:

①assets中的文件资源不会映射到R文件中,而res中的文件会映射到R文件中,所以raw文件夹下的资源都有对应的ID;

②assets可能有更深的目录结构,而res/raw里只能有一层目录;

③资源存取方式不同,assets中利用AssetsManager,而res/raw直接利用getResources()。

 

5.注意

①除了assets和res/raw资源被原装不动地打包进APK之外,其它的资源都会被编译或者处理;

②除了assets资源外,其它的资源都会被赋予一个资源ID;

③打包工具负责编译和打包资源,编译完成后会生成一个resources.arsc文件和一个R.java,前者保存的是一个资源索引表,后者定义了各个资源D常量。

④应用程序配置文件AndroidManifest.xml同样会被编译成二进制的XML文件,然后再打包到APK里面去。

⑤应用程序在运行时通过AssetManager来访问资源,或通过资源D来访问,或通过文件名来访问。

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值