打包前提工作 --这里假设是新创建的工程

创建build.xml local.properties project.properties --如果已经有这三个文件,请忽略此步骤
project.properties --这个文件通常是在创建android工程时已经创建好了!在工程主目录下可以找到。
build.xml--此文件需要创建,其具体创建过程如下:打开命令行,切换到工程目录下,执行命令 android update project -p . -t <target> -n <build name>
比如 d:/androidtest : android update project -p . -t 3 -n <buildTest>
具体参数解释如下:
-p 指项目所在目录,这里的.表示当前目录下;
-t 指工程对应的target,获取方式是:在cmd下输入命令android list targets,对应地返回数值(比如你项目选用的android平台是 4.2.2,那么对应的id是3,如下所示)

    id: 3 or "android-17"

     Name: Android 4.2.2

-n 指的是build文件的name,可以自定义,也可以默认(默认取launcher对应的activity的名字);
完成后,工程目录如下:
-src
-res
-libs
-assets
-AndroidManifest.xml
-project.properties----------<android update project 生成>工程属性,指定target, proguard.config
-build.xml -------------------------<android update project 生成>ant工程文件
-local.properties ------------------ <android update project 生成>指定sdk.dir属性
-proguard-project.txt -------------<android update project 生成>个性化混淆配置文件
-ant.properties---------------------手动添加,可以放置自定义的ant属性

[编辑]打包步骤--这里入正题

打包分以下两种方式:
1. 命令行:
cmd切换到项目目录下,执行命令 ant release(调用sdk/tool/ant目录下 build.xml打包) ,打包过程可看日志,打包成功后,自动将apk包 放到bin/目录下;
2. 用ant模式:
在eclipse模式下,点击项目下的build.xml文件(此build.xml里有如下代码:<import file="${sdk.dir}/tools/ant/build.xml" />,它实际上也是调用了sdk/tool/ant目录下 build.xml打包),右击,选择open with--Ant Editor ,在弹出来的outline视框中,找到 release,然后点击右键,选择Ant build,打包成功后,自动将apk包 放到bin/目录下;


[编辑]签名

打开build.xml文件,通常有 <property file="ant.properties" /> ,这个file文件里面记录的是 签名信息,通常包含四个参数:
key.store
key.alias
key.store.password
key.alias.password
此文件在调用build.xml运行打包命令时,会被调用,生成 签名的apk包;
如果用eclipse运行安装apk,不调用build.xml,不会生成签名的包;
经过签名的apk,解压出来,可以在META-INF下看到两个文件:CERT.RSA CERT.SF;

[编辑]混淆

为了代码保密,增加反向工程的难度,在打包的时候需要对代码进行混淆,ADT支持混淆工具Proguard
参考 http://developer.android.com/intl/zh-CN/tools/help/proguard.html (英文权威版)。
设置 混淆 规则:
在项目录下,project.properties文件里,添加代码
proguard.config=proguard.cfg --.cfg文件需要自己添加混淆规则内容
或者使用注释里面的代码
proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt --这是sdk自带的混淆规则文件

build.xml 运行打包过程中,会读取混淆规则文件,进行混淆处理,打包完成后,会在项目bin/ 目录 下生成proguard文件夹(如果用eclipse打包:点击项目名称,右键 android tools --Export Unsigned ....--生成apk,这种操作方式,产生的proguard文件夹直接在项目主目录下),包含以下内容:
dump.txt --文件中所有类文件间的内部结构
mapping.txt --列出了原始的类,方法和字段名与混淆后代码间的映射【重要!】
seeds.txt --列出了未被混淆的类和成员
usage.txt --列出了从.apk中删除的无用的代码,减小apk大小

build打包过程, 如果设置了混淆,它会调用此规则,生成 混淆后的APK;



[编辑]多渠道打包 --ttids

因为android的app市场众多,聚划算android客户端分发的渠道达到60+,为统计或其他定制的需要,就产生了一个版本的app需要为各个market打包,每个market分配不同的channel id。channel id一般放置在asset文件,或者放在AndroidManifest的meta-data标签中,命名为 ttid.dat;<br>

ttid.dat --每个投放到市场的apk包,都包含此文件,它里面包含了此市场的渠道号,简称为ttid;市场上面下载的apk,它的所有request里面都会包含ttid这个参数,用来记录此渠道的应用的使用情况;<br>

如何打渠道包:<br>

执行build.xml中的ttid 对应的 target时,会去 读取ttid.txt文件(包含所有市场的渠道号),每行一个ttid,foreach任务循环打包,每次循环都会将ttid写入到asset/ttid.dat中,然后执行一次打包过程(具体循环过程可以参考 build.xml内代码);<br>


[编辑]文件详解

[编辑]build.xml

<property file="local.properties" />  <loadproperties srcFile="project.properties" />   --加载文件内容

<import file="${sdk.dir}/tools/ant/build.xml" />  --引用ant的打包文件,必须要有的

最重要的是 <target>标签,用来指定打包任务的类型,一般 需要 自定义,比如

<target name="test">   --任务名称
<xpath input="AndroidManifest.xml" expression="/manifest/@android:versionName" output="versionName" default="unknown" /> --查找versionName的值,并将它保存到变量versionName中
<echo message="name: ${versionName}"> --打印
</echo>
</target>

以上是一次 打包任务,在tasklist中,直接选择test,双击运行即可执行一遍此target;

查看每个项目的build,一般都包含多个build,在tasklist视图中可查看整个build的结构,并可以方便地选择执行哪个task;


[编辑]prguard.cfg

以下是 混淆用到的规则参数列表 ,供参考学习:

参数:

-include {filename} 从给定的文件中读取配置参数
-basedirectory {directoryname} 指定基础目录为以后相对的档案名称
-injars {class_path} 指定要处理的应用程序jar,war,ear和目录
-outjars {class_path} 指定处理完后要输出的jar,war,ear和目录的名称
-libraryjars {classpath} 指定要处理的应用程序jar,war,ear和目录所需要的程序库文件
-dontskipnonpubliclibraryclasses 指定不去忽略非公共的库类。
-dontskipnonpubliclibraryclassmembers 指定不去忽略包可见的库类的成员。

保留选项

-keep {Modifier} {class_specification} 保护指定的类文件和类的成员
-keepclassmembers {modifier} {class_specification} 保护指定类的成员,如果此类受到保护他们会保护的更好
-keepclasseswithmembers {class_specification} 保护指定的类和类的成员,但条件是所有指定的类和类成员是要存在。
-keepnames {class_specification} 保护指定的类和类的成员的名称(如果他们不会压缩步骤中删除)
-keepclassmembernames {class_specification} 保护指定的类的成员的名称(如果他们不会压缩步骤中删除)
-keepclasseswithmembernames {class_specification} 保护指定的类和类的成员的名称,如果所有指定的类成员出席(在压缩步骤之后)
-keepattributes {attribute_name,...} 保护给定的可选属性,例如LineNumberTable, LocalVariableTable, SourceFile, Deprecated, Synthetic, signature and InnerClasses.
-printseeds {filename} 列出类和类的成员-keep选项的清单,标准输出到给定的文件

压缩

-dontshrink 不压缩输入的类文件
-printusage {filename}
-whyareyoukeeping {class_specification}

优化

-dontoptimize 不优化输入的类文件
-assumenosideeffects {class_specification} 优化时假设指定的方法,没有任何副作用
-allowaccessmodification 优化时允许访问并修改有修饰符的类和类的成员

混淆

-dontpreverify //不用预先检查
-verbose //输出详细的过程
-dontobfuscate 不混淆输入的类文件
-printmapping {filename} //指定混淆后,类或方法生成的map,后跟指定的路径及文件名 *.map
-applymapping {filename} 重用映射增加混淆
-obfuscationdictionary {filename} 使用给定文件中的关键字作为要混淆方法的名称
-overloadaggressively 混淆时应用侵入式重载
-useuniqueclassmembernames 确定统一的混淆类的成员名称来增加混淆
-flattenpackagehierarchy {package_name} 重新包装所有重命名的包并放在给定的单一包中
-repackageclass {package_name} 重新包装所有重命名的类文件中放在给定的单一包中
-dontusemixedcaseclassnames 混淆时不会产生形形×××的类名
-renamesourcefileattribute {string} 设置源文件中给定的字符串常量


一般来说,在混淆打包后的测试中,如果发现问题,就将有问题的类设置为keep(让它不参与混淆,以保证质量)



在网上找到一个客户端打包原理图解:

android-客户端打包_apk