android程序载eclipse自动化生成apk的过程

学人智库 时间:2018-01-17 我要投稿
【meiwen.anslib.com - 学人智库】

  从事安卓开发的人都知道,在我们写好java代码之后eclipse直接就帮我们把代码生成为APK格式的文件。apk格式就是在安卓上可以直接安装的一种格式。那么自动化的去生成个性化apk的时候,我们就需要编写脚本或代码来自动生成一个apk,在生成apk之前必须了解下android编译apk的过程;

  现在很多人想对Android工程的编译和打包进行自动化,比如建立每日构建系统、自动生成发布文件等等。这些都需要我们对Android工程的编译和打包有一个深入的理解,至少要知道它的每一步都做了什么,需要什么环境和工具,输入和输出是什么。那么我们就来挖掘一下Android的编译过程中的细节。

  首先,我们假定你的系统(什么系统都行,不限于Linux还是Windows系统,当然,我在这里默认使用Linux系统来举例子,但在 Windows中几乎没有什么差别)已经安装了JDK和Android SDK。再假定你的Android SDK的路径是ANDROID_SDK_HOME,你想要编译的Android OS版本是ANDROID_OS_VERSION(比如android-1.6、android-8、android-10等)。

  我们重点关心的是(1)这个过程的输入是什么?(2)这个过程的输出是什么?(3)这个过程使用了什么工具?至于使用什么参数,可以自己去看对应命令的帮助文件,或者在网上搜索,这不是本文的重点。

  步骤中提到的工具如下表:

名称功能介绍在操作系统中的路径aaptAndroid资源打包工具${ANDROID_SDK_HOME}/platform-tools/apptaidlAndroid接口描述语言转化为.java文件的工具${ANDROID_SDK_HOME}/platform-tools/aidljavacJava Compiler${JDK_HOME}/javac或/usr/bin/javacdex转化.class文件为Davik VM能识别的.dex文件${ANDROID_SDK_HOME}/platform-tools/dxapkbuilder生成apk包${ANDROID_SDK_HOME}/tools/opkbuilderjarsigner.jar文件的签名工具${JDK_HOME}/jarsigner或/usr/bin/jarsignerzipalign字节码对齐工具${ANDROID_SDK_HOME}/tools/zipalign

  第一步:打包资源文件,生成R.java文件

  【输入】Resource文件(就是工程中res中的文件)、Assets文件(相当于另外一种资源,这种资源Android系统并不像对res中的文件那样优化它)、AndroidManifest.xml文件(包名就是从这里读取的,因为生成R.java文件需要包名)、Android基础类库(Android.jar文件)

  【输出】打包好的资源(一般在Android工程的bin目录可以看到一个叫resources.ap_的文件就是它了)、R.java文件(在gen目录中,大家应该很熟悉了)

  【工具】aapt工具,它的路径在${ANDROID_SDK_HOME}/platform-tools/aapt(如果你使用的是Windows系统,按惯例路径应该这样写:%ANDROID_SDK_HOME%platform-toolsaapt.exe,下同)。

  第二步:处理AIDL文件,生成对应的.java文件(当然,有很多工程没有用到AIDL,那这个过程就可以省了)

  【输入】源码文件、aidl文件、framework.aidl文件

  【输出】对应的.java文件

  【工具】aidl工具

  第三步:编译Java文件,生成对应的.class文件

  【输入】源码文件(包括R.java和AIDL生成的.java文件)、库文件(.jar文件)

  【输出】.class文件

  【工具】javac工具

  第四步:把.class文件转化成Davik VM支持的.dex文件

  【输入】 .class文件(包括Aidl生成.class文件,R生成的.class文件,源文件生成的.class文件),库文件(.jar文件)

  【输出】.dex文件

  【工具】javac工具

  第五步:打包生成未签名的.apk文件

  【输入】打包后的资源文件、打包后类文件(.dex文件)、libs文件(包括.so文件,当然很多工程都没有这样的文件,如果你不使用C/C++开发的话)

  【输出】未签名的.apk文件

  【工具】apkbuilder工具

  第六步:对未签名.apk文件进行签名

  【输入】未签名的.apk文件

  【输出】签名的.apk文件

  【工具】jarsigner

  第七步:对签名后的.apk文件进行对齐处理(不进行对齐处理是不能发布到Google Market的)

  【输入】签名后的.apk文件

  【输出】对齐后的.apk文件

  【工具】zipalign工具

  知道了这些细节之后,我们就可以实现很多我们想实现东西了,比如:自动化,我们可以使用某种脚本,像Windows下的批处理,linux下的Bash,Java下的Ant,Python、Perl这样的脚本语言,甚至直接用Java、.net这们的强类型语言也是可以的。如果你真正弄懂了上面的步骤,了解了编译打包过程的本质,你完全可以以你想要的任何方式实现它的自动化,这才是真正的“举一反三,以不变应万变”。再比如,对Android SDK的精简,大家知道,现在Android SDK动辙几百兆,我们完全可以应用上面的知识,只保留必要的工具,把SDK精简到10M以下。当然,还可以做很多事情,前提是你真正弄懂了它。

  备注:android sdk版本不同,安装之后在tools下可能会少dx.bat,apkbuilder.bat文件,通过升级SDK或者单独下载放在对应的目录,也可正常使用;

  一、手动编译APK的流程如下:

  1.生成资源文件:使用Android SDK提供的aapt.exe生成R.java类文件

  2.编译本地库:使用Android SDK提供的aidl.exe把.aidl转成.java文件(如果没有aidl,则跳过这一步)

  3.编译java代码:使用JDK提供的javac.exe编译.java类文件生成class文件

  4.生成dex文件:使用Android SDK提供的dx.bat命令行脚本生成classes.dex文件

  5.打包资源文件:使用Android SDK提供的aapt.exe生成资源包文件(包括res、assets、androidmanifest.xml等)

  6.生成apk文件:使用Android SDK提供的apkbuilder.bat生成未签名的apk安装文件

  7.对apk文件进行签名:使用jdk的jarsigner.exe对未签名的包进行apk签名

  二、详细步骤

  1)、准备工作

  A、安装好JDK,配置环境变量;

  B、将android-sdk-windowsplatform-tools和 android-sdk-windows ools 添加到CLASSPATH 环境变量中;

  C、打开CMD命令行界面,将当前目录切换到工程所在目录;

  D、准备一个目录,以下例子是以在eclipse中创建的Android test project项目,名称Test;

  2)生成资源文件,使用aapt生成R.java类文件,aapt所在路径android-sdk-windowsplatform-toolsaapt.exe:

  E:UsersAdministratorworkspaceTest>aapt package -f -m -J gen -S res -M AndroidManifest.xml -I E:android-sdk_r23.0.2-windowsandroid-sdk-windowsplatformsandroid-18android.jar

  说明:

  -f -m -J gen 代表按覆盖的形式在gen目录下生成带包路径的R.java;

  -f force overwrite of existing files;

  -m make package directories under location specified by -J

  -J specify where to output R.java resource constant definitions

  -J后面跟的是生成目录;-S后面跟的是资源目录;-M后面跟的是AndroidManifest.xml;-I后面跟的是使用的AndroidAPI的jar;

  3)javac.exe编译.java类文件生成class文件,javac所在路径C:Program FilesJavajdk1.6.0_43injavac.exe

  E:UsersAdministratorworkspaceTest>javac -encoding utf-8 -target 1.6 -d bin -bootclasspath E:android-sdk_r23.0.2-windowsandroid-sdk-windowsplatformsandroid-18android.jar genandroidsupportv7appcompat est*.java srcandroidsupportv7appcompat est*.java

  说明:-target:jdk版本;-d:指定生成的class类文件存放的位置;-bootclasspath:覆盖引导类文件的位置;-encoding:后面跟字符编码,避免出现乱码;

  4)使用dx.bat命令行脚本生成classes.dex文件,dx.bat所在路径android-sdk-windows oolsdx.bat

  E:UsersAdministratorworkspaceTest>dx.bat --dex --output=E:UsersAdministratorworkspaceTestinclasses.dex E:UsersAdministratorworkspaceTestinclasses

  说明:--output:生成的dex文件存放路径;最后带上class文件所在目录,不需要加包目录

  5)使用aapt.exe生成资源包文件,aapt.exe所在路径android-sdk_r23.0.2-windowsandroid-sdk-windowsplatform-toolsaapt.exe

  E:UsersAdministratorworkspaceTest>aapt.exe package -f -M AndroidManifest.xml -S res -A assets -I E:android-sdk_r23.0.2-windowsandroid-sdk-windowsplatformsandroid-18android.jar -F bin esourcesLater

  说明:-S:资源目录;-M:AndroidManifest.xml文件;-I:导入用的jar文件;-F:后面跟生成的资源文件存放位置,生成的资源文件名是自己新建的

  6)使用apkbuilder.bat生成未签名的apk安装文件,apkbuilder.bat所在路径android-sdk_r23.0.2-windowsandroid-sdk-windows oolsapkbuilder.bat。

  (使用该命令时:会提示该工具已过时,Google不推荐使用。而推荐使用的是:com.android.ant.ApkBuilderTask,但apk仍能成功生成)

  E:UsersAdministratorworkspaceTest>apkbuilder E:UsersAdministratorworkspaceTestinHelloWorld.apk -u -z E:UsersAdministratorworkspaceTestin esourcesLater -f E:UsersAdministratorworkspaceTestinclasses.dex -rf E:UsersAdministratorworkspaceTestsrc

  THIS TOOL IS DEPRECATED. See --help for more information.

  说明:-z:资源打包文件;-f:类打包文件;-rf:源代码目录;

  (备注:此步骤没有成功给apk签名)

  7)使用jarsigner.exe对未签名的包进行apk签名,jarsigner.exe所在路径C:Program FilesJavajdk1.6.0_43injarsigner.exe

  E:UsersAdministratorworkspaceTest>jarsigner -verbose -keystore E:Userszhengshu_apk -signedjar E:UsersAdministratorworkspaceTestinHelloWorld.apk E:UsersAdministratorworkspaceTestinHelloWorld.apk.mydeystore

  说明:-keystore:keystore文件;-signedjar:签名后的文件;后面还有未签名文件和key的alias

  用法:jarsigner [选项] jar 文件别名

  jarsigner -verify [选项] jar 文件

  [-keystore ] 密钥库位置

  [-storepass <口令>] 用于密钥库完整性的口令

  [-storetype <类型>] 密钥库类型

  [-keypass <口令>] 专用密钥的口令(如果不同)

  [-sigfile <文件>] .SF/.DSA 文件的名称

  [-signedjar <文件>] 已签名的 JAR 文件的名称

  [-digestalg <算法>] 摘要算法的名称

  [-sigalg <算法>] 签名算法的名称

  [-verify] 验证已签名的 JAR 文件

  [-verbose] 签名/验证时输出详细信息

  [-certs] 输出详细信息和验证时显示证书

  [-tsa ] 时间戳机构的位置

  [-tsacert <别名>] 时间戳机构的公共密钥证书

  [-altsigner <类>] 替代的签名机制的类名

  [-altsignerpath <路径列表>] 替代的签名机制的位置

  [-internalsf] 在签名块内包含 .SF 文件

  [-sectionsonly] 不计算整个清单的散列

  [-protected] 密钥库已保护验证路径

  [-providerName <名称>] 提供者名称

  [-providerClass <类> 加密服务提供者的名称

  [-providerArg <参数>]] ... 主类文件和构造函数参数

  E:UsersAdministratorworkspaceTest

  生成和运行apk文件相关的组件:

  apk文件的编译流程图如下:

  下面逐一说明:

  项目的源文件结构如下:

  [html] view plaincopyE:Example

  │ AndroidManifest.xml

  │

  ├─assets

  ├─res

  │ ├─drawable-hdpi

  │ │ icon.png

  │ │

  │ ├─drawable-ldpi

  │ │ icon.png

  │ │

  │ ├─drawable-mdpi

  │ │ icon.png

  │ │

  │ ├─layout

  │ │ main.xml

  │ │

  │ └─values

  │ strings.xml

  │

  └─src

  └─net

  └─claudxiao

  └─example

  Example.java

  1、从res生成R.java

  mkdir gen

  aapt package -f -m -J gen -S res -I “E:Program FilesAndroidandroid-sdk-windowsplatformsandroid-7android.jar” -M AndroidManifest.xml

  其中,-f将覆盖已有结果,-m -J gen指定输出路径,-S指定资源文件目录,-I指定要包含的包,-M指定AndroidMenifest.xml文件。

  2、将.java编译为.class

  mkdir bin

  javac -encoding GB18030 -target 1.6 -bootclasspath “E:Program FilesAndroidandroid-sdk-windowsplatformsandroid-7android.jar” -d bin src etclaudxiaoexampleExample.java gen etclaudxiaoExampleR.java

  其中,-target指定类文件的虚拟机版本,-bootclasspath覆盖引导类文件的位置,-d指定输出路径。

  3、将.class编译为classes.dex

  dx.bat dex output=E:Exampleinclasses.dex E:Examplein

  注意这里必须用绝对路径。

  4、将资源文件打包

  aapt package -f -M AndroidManifest.xml -S res -A assets -I “E:Program FilesAndroidandroid-sdk-windowsplatformsandroid-7android.jar” -F bin esources.ap_

  -F指定输出的apk文件。

  5、打包成未签名apk文件

  apkbuilder.bat E:ExampleinExample_unsigned.apk -u -z E:Examplein esources.ap_ -f E:Exampleinclasses.dex -rf E:Examplesrc

  这个命令的常用格式为:

  apkbuilder ${output.apk.file} -u -z ${packagedresource.file} -f ${dex.file} -rf ${source.dir} -rj ${libraries.dir}

  参数必须使用绝对路径。

  此外,运行后提示这一工具即将被废弃,但我没有找到新的替代工具是什么。

  6、生成一个签名

  keytool -genkey -alias android.keystore -keyalg RSA -validity 20000 -keystore android.keystore

  当前目录下生成了一个android.keystore文件

  7、对apk文件签名

  jarsigner -keystore E:Exampleandroid.keystore -storepass claudxiao -keypass claudxiao -signedjar E:ExampleinExample.apk E:ExampleinExample_unsigned.apk android.keystore

  这个命令的常用格式为:

  jarsigner -keystore ${keystore} -storepass ${keystore.password} -keypass ${keypass} -signedjar ${signed.apkfile} ${unsigned.apkfile} ${keyalias}

  至此,binExample.apk就是一个可以安装的apk文件了。作为对比,现在的目录结构如下:

  [html] view plaincopyE:Example

  │ android.keystore

  │ AndroidManifest.xml

  │

  ├─assets

  ├─bin

  │ │ classes.dex

  │ │ Example.apk

  │ │ Example_unsigned.apk

  │ │ resources.ap_

  │ │

  │ └─net

  │ └─claudxiao

  │ └─example

  │ Example.class

  │ R$attr.class

  │ R$drawable.class

  │ R$layout.class

  │ R$string.class

  │ R.class

  │

  ├─gen

  │ └─net

  │ └─claudxiao

  │ └─example

  │ R.java

  │

  ├─res

  │ ├─drawable-hdpi

  │ │ icon.png

  │ │

  │ ├─drawable-ldpi

  │ │ icon.png

  │ │

  │ ├─drawable-mdpi

  │ │ icon.png

  │ │

  │ ├─layout

  │ │ main.xml

  │ │

  │ └─values

  │ strings.xml

  │

  └─src

  └─net

  └─claudxiao

  └─example

  Example.java

  8. 对齐

  如果apk是Release模式,则必须使用zipalign工具进行对齐,对齐可减少内存使用。

[android程序载eclipse自动化生成apk的过程]