第三篇 提高篇—大胆曹贼,我跟你拼啦!第21回 反编译比较符合我的性格!
来源:互联网 发布:玲珑醉梦网络剧百度云 编辑:程序博客网 时间:2024/06/05 00:18
话说刘关张三人骑着赤兔马,走呀走,走呀走,好不容易走回了卧龙岗。一进门,只见卧龙气喘吁吁地跑出来,“你们可算回来了!”
刘备:“军师何事如此慌张,难道说厕所没手纸了吗?”
孔明:“别扯那没用的,出大事啦!你们还记的曹操不?”
刘备:“废话,我被灭成灰也忘不了他!”
关羽:“大哥,此话不是这么讲的吧……”
孔明:“那曹贼趁你们三人不在之时,通过反编译你们之前做的项目,改一改就放到网上去了,倒成了他的产品了!”
刘备:“那还有没有王法了?难道这种事献帝不管的吗?”
孔明:“献帝只管平时打打酱油喝喝茶,这种事如何能管?”
刘备:“那军师有何妙计?”
孔明:“唉……为今之计,只有认了。”
张飞:“这算哪门子妙计,我找他们拼命去!”
关羽一把拉住张飞,“三弟,先等大哥做决定吧。”
刘备:“孔明,这反编译是什么东西,没有什么防范措施吗?”
孔明:“之前我没跟你们讲反编译,是因为觉得用不到,做出来的产品还没有到达值得别人抄袭的地步。现在你们技术成长了,做出来的东西有价值了,自然会有小人打你们源码的主意。不过这从另一个方面说明你们确实上升了一个台阶。现在看来是时候好好教授你们怎么防范反编译了。”
刘备:“嘿嘿,军师,要不先教教我们怎么反编译吧,纯粹是处于学术上的考虑哈,没什么其他歪念~”
孔明:“我就知道你会这么说。好吧,其实这种反编译这种事情,我也是经常干的……”
1.1. 反编译详解
许多人常常认为反编译是盗取别人的代码。但其实反编译不仅可以开阔自己的视野,汉化外国软件和去除广告,而且可以限制应用程序的权限,增加软件的安全性。例如很多软件,申请了一些可能会导致付费(如:发短信、呼叫号码)或者泄漏隐私(如:读取通讯录)的权限。
本节将介绍如何对Android应用程序进行反编译。通过反编译,不仅可以学习别人的代码,而且会对Android应用程序的构成有更深层次的了解。下面首先介绍一些常见的反编译工具。
1.1.1.反编译工具介绍
jd-gui工具
jd-gui工具是一个用C++开发的Java反编译工具,由PavelKouznetsov开发,支持Windows、Linux和苹果Mac三个平台。jd-gui工具还提供了Eclipse平台下的插件JD-Eclipse。JD-Eclipse实现了Eclipse的高亮着色,多文件标签浏览的功能。jd-gui工具运行界面如图21-1所示:
图21-1 jd-gui运行界面
jad反编译器
jad是非常出色的免费Java字节码反编译器,提供了大量的命令行选项。基本用法:Usage:jad[option(s)],可直接输入类文件名,支持通配符。下面给出一个直接使用命令行批量反编译整个目录的例子:jad-o -r –s java -d src bin/**/*.class。src:反编译的目录;bin:将bin里面所有的“.class”文件反编译到src目录下。下面介绍jad命令行选择的列表:
l -a:用JVM字节格式来注解输出。
l -af:同-a,但是注解的时候用全名称。
l -clear:清除所有的前缀。
l -b:输出多余的括号。
l -d:指定输出文件的文件目录。
l -dead:试图反编译代码的dead 部分。
l -disass:不用字节码的方式反编译。
l -f:无论是类还是方法,输出其整个的名字。
l -ff:在方法之前输出类的成员。
l -i:输出所有变量的缺省最初值。
l -l:将strings分割成指定数目的块字符。
l -lnc:将输出文件用行号来注解。
l -nl:用新一行字符分割strings。
l -nodos:不去检查class文件是否以dos方式写。
l -nocast:不生成辅助文件。
l -nocode:不生成方法的源代码。
l -noconv:不转换Java的定义符。
l -noctor:不允许空的构造器存在。
l -noinner:关掉对内部类的支持。
l -nolvt:忽略局部变量的信息。
l -nonlb:在打开一个括号之前不输出一个新行。
l -o:无需确认直接覆盖输出。
l -p:发送反编译代码到标准输出STDOUT。
dex2jar工具
Android应用会将Java代码编译成class.dex。dex2jar是一个用来将Android的Dalvik Executable(.dex)格式的文件转化成 Java 类文件的工具。jd-gui和jad都是对“.class”文件的反编译,所以它们常常需要配合起来一起使用。首先将apk中的classes.dex转化成jar文件,再用“.class”文件的反编译工具,直接查看jar包的源代码。常用方法是在命令行下定位到dex2jar.bat所在目录,运行“dex2jar.bat classes.dex”命令,生成classes.dex.dex2jar.jar文件,如图21-2所示:
图21-2dex2jar反编译结果
Android apktool工具包
Android apktool是一个第三方的工具包,用来从Android的apk安装程序中提取各种资源,生成程序的源代码、图片、xml配置和语言资源等文件。通过修改图片和资源文件,重新编译打包,签名apk,可以生成本地化/修正版的apk。
AXMLPrinter2工具
直接打开apk压缩包中的xml文件往往看见一堆乱码,AXMLPrinter2可以方便的把apk中已经序列化的xml还原为文本格式。
Gapktool工具
Gapktool是一个强大的apk反编译工具,集成了 jd-gui、jad、dex2jar、apktool,默认使用jad反编译。Gapktool运行界面如图21-3所示:
图21-3 Gapktool反编译
1.1.2.反编译实战
本节通过对一个带有广告的HelloWorld.apk进行反编译、去除广告、重新打包,演示如何进行反编译。首先建立HelloWorld工程,添加广告,HelloWorld工程的结构目录和运行结果如图21-4所示:
图21-4结构目录和运行结果图
然后下载两个工具dex2jar、jd-gui用于反编译Java源代码。首先将apk文件后缀改为zip,解压得到通过dx工具打包的class.dex文件;接着,将class.dex复制到dex2jar.bat所在目录下,在命令行下输入命令:dex2jar.bat classes.dex,生成jar文件,如图21-5所示:
图21-5 dex2jar反编译命令示意图
运行jd-gui,打开上面生成的jar文件,看到源代码如图21-6所示:
图21-6 jd-gui反编译代码
对比HelloWorld.java源代码,可见看出,已经实现了反编译apk的大部分逻辑代码。
public class HelloWorld extendsActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}
下面通过反编译xml文件去除图21-4的广告。首先下载apktool工具:apktool1.4.1.tar.bz2 和 apktool-install-windows-r04-brut1.tar.bz2;接着将下载的两个包解压得到:aapt.exe、apktool.bat和apktool.jar;然后在命令行下定位到apktool.bat目录下,输入命令“apktool d C:\*.apk C:\*文件夹”,命令行解释:apktool d [apk文件路径] [输出文件夹路径],结果如图21-7所示:
图21-7 apktool反编译代码
修改HelloWorld工程的AndroidManifest.xml文件和main.xml文件,将广告权限和广告的代码移除,代码如下所示:
AndroidManifest.xml代码清单23-1-2:
<!—刘备:有困难要帮,没有困难制造困难也要帮!-->
<?xml version="1.0"encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.firstpeople.apk"
android:versionCode="1"
android:versionName="1.0">
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name">
<activity android:name="com.firstpeople.apk.HelloWorld"
android:theme="@android:style/Theme.NoTitleBar"
android:windowSoftInputMode="adjustPan"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<meta-data android:value="56OJyM1ouMGoaSnvCK"android:name="DOMOB_PID"/>
</application>
<!--修改去除广告权限 -->
<uses-permissionandroid:name="android.permission.INTERNET"/>
<uses-permissionandroid:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permissionandroid:name="android.permission.READ_PHONE_STATE"/>
<uses-permissionandroid:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permissionandroid:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-sdk android:minSdkVersion="8" />
</manifest>
main.xml代码清单23-1:
<?xml version="1.0"encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello" />
<!-- 广告位置,去除 -->
<cn.domob.android.ads.DomobAdView
android:id="@+id/domobAdXML"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
在命令行中输入“apktool b c:\***文件夹”命令将修改后的文件重新打包成apk,如下图21-8所示:
图21-8 apktool打包命令
打开目录“C:\HelloWorld”文件夹,可以发现生成了两个文件夹:build和dist。其中,打包生成的新HelloWorld.apk,在dist文件夹下,重新装载apk,发现广告已经移除。
1.2. 防范apk被反编译
有攻就有防!由于软件的商业价值,一些人,会反编译apk的代码,重新编译,发布到应用商店,赚取利益。对于涉及到商业价值的软件,有时做适当的混淆、加密,也是为了保护自身的权利。本节将重点介绍如何防止自己的apk被反编译。
1.2.1. 防止被反编译工具
Jocky混淆编译器
Jocky是一款优秀的Java混淆编译器。一般而言,现有的混淆器都是对编译好的“.class”文件进行混淆,需要编译和混淆两个步骤。而Jocky是直接对源码进行混淆,避免了程序较大时,复杂的配置工作。Jocky混淆编译器是在JDK提供的Java编译器(javac)的基础上完成的,修改其中的代码生成过程,对编译器生成的中间代码进行混淆,最后生成“.class”文件。这样使得编译和混淆只需要一个步骤就可以完成。
不仅可以使用命令行,也可以通过Jocky提供了Eclipse的插件直接在Eclipse中使用Jocky。命令行使用Jocky,只需要获得jocky.jar后,运行“java -jar jocky.jar”命令就可以启动Jocky混淆编译器。Jocky的命令行参数和javac基本相同,但增加了一个新的参数-scramble,它的用法如下:
l -scramble:混淆所有package、private和private符号。
l -scramble all:混淆所有符号。
l -scramble:<level>:混淆相应级别的符号,其中<level>指定混淆级别。
l -scramble:none:不进行混淆。
l -scramble:private:对所有private访问级别的元素进行混淆。
l -scramble:package:对所有private或package private元素进行混淆。
l -scramble:protected:对所有private、package private、protected元素进行混淆。
l -scramble:public:对所有的元素都进行混淆。
l -scramble:all:相当于-scramble:public。
l -scramble:不带级别参数,则相当于-scramble:package。
在Eclipse中安装Jocky,只需要将eclipse/plugins/org.apusic.jocky_1.0.0目录复制至Eclipse的plugins目录下即可。或者在Eclipse/links文件夹中,通过link方式指定Jocky的插件目录。在Eclipse中使用Jocky,只需点中Java工程,点击Jocky,就可以出现Jocky的快捷菜单,如图21-9所示:
图21-9Jocky
proguard混淆源码
为了很好的保护Java源代码,往往会对编译好的“.class”文件进行混淆处理。Google从Android SDK 2.3版本开始,在“android-sdk-windows\tools\”目录下增加了一个proguard文件夹。proguard是一个Java类文件的瘦身器、优化器、混淆器和预校验器。瘦身器用于删除没有使用的类、属性、方法和变量;优化器用于分析和优化方法的字节码;混淆器使用短而无意义的名字重命名类、变量和方法名。这使得工程代码更小、更有效并且更难以实现逆向工程。打开android-sdk-windows\tools\lib\proguard.cfg文件,可以看到如下脚本:
-optimizationpasses 5 //设置混淆的压缩比率 0 ~ 7
-dontusemixedcaseclassnames //颠倒名字
-dontskipnonpubliclibraryclasses//如果应用程序引入的有jar包,并且想混淆jar包里面的class
-dontpreverify
-verbose//混淆后生产映射文件 map 类名,转化后类名的映射
-optimizations!code/simplification/arithmetic,!field/*,!class/merging/*//混淆采用的算法.
-keep public class * extendsandroid.app.Activity//所有activity的子类不要去混淆
-keep public class * extendsandroid.app.Application
-keep public class * extendsandroid.app.Service
-keep public class * extendsandroid.content.BroadcastReceiver
-keep public class * extendsandroid.content.ContentProvider
-keep public class * extendsandroid.app.backup.BackupAgentHelper
-keep public class * extendsandroid.preference.Preference
-keep public classcom.android.vending.licensing.ILicensingService
-keep classes withmembernames class *{
native <methods>;//所有native的方法不能去混淆.
}
-keep classeswithmembers class * {
public <init>(android.content.Context,android.util.AttributeSet);//某些构造方法不能去混淆
}
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet,int);
}
-keepclassmembers class * extendsandroid.app.Activity {
public void *(android.view.View);
}
-keepclassmembers enum * { //枚举类不能去混淆.
public static **[] values();
public static ** valueOf(java.lang.String);
}
-keep class * implementsandroid.os.Parcelable { //aidl文件不能去混淆.
public static final android.os.Parcelable$Creator *;
}
该脚本主要保留了继承自Activity、Application、Service、BroadcastReceiver、ContentProvider、BackupAgentHelper、Preference和ILicensingService的子类不被混淆。因为这些子类,都是可能被外部调用的。另外,它还保留了含有native方法的类、从xml构造的类、枚举类型中的values和valueOf静态方法、继承Parcelable的跨进程数据类。
孔明:在实际的工程项目中,可以直接使用Google自动生成的配置进行混淆工作。也可以根据自己的需求编写一些proguard配置。如果需要修改 proguard混淆脚本可以查看SDK安装目录下的\docs\guide\developing\tools\proguard.html说明。
1.2.2.反编译实战
现在在Eclipse中新建一个项目,一般都会包含proguard.cfg文件。一般大多数情况下,不需要更改这个混淆脚本文件。下面就针对HelloWorld工程进行混淆。
首先在HelloWorld.java里增加一些多余代码,以便观察混淆后的效果。代码如下所示:
public class Test {
String info ="this is a test!";
// 调用的方法
public void infoPrint() {
Log.i("Test", "info");
}
// 多余的方法
public void infoPrint2() {
}
}
public class HelloWorld extendsActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// 测试混淆
Test mTest= new Test();
mTest.infoPrint();
}
}
然后在工程文件project.properties中加入“proguard.config=proguard.cfg”。HelloWorld编译后,导出apk,反编译,可以看到如图21-10中所示代码:
图21-10反编译结果
从图21-10可以看出,有用的类Test名字变成了a,多余的方法infoPrint2()不见了,infoPrint()方法的内容直接写入到Activity里。同时,在工程目录下生成了proguard/dump.txt、proguard/ mapping.txt、proguard/seeds.txt、proguard/ usage.txt四个文件,它们具体的功能如下:
l dump.txt:描述“.apk”包中所有“.class”文件的内部结构。
l mapping.txt:列出了源代码与混淆后的类、方法和属性名字之间的映射。该文件可以把混淆的堆栈跟踪信息反翻译为源代码中的类、方法和成员名字,因此它可以用于分析构建之后得到的bug报告。
l seeds.txt:列出未混淆的类和成员。
l usage.txt:列出从“.apk”中剥离的代码。
孔明:保存好每一个已发布给用户的程序的mapping.txt文件很重要。通过保存发布构建版本的mapping.txt文件,可以确保当用户碰到bug时,能够提交混淆后的堆栈调试跟踪信息,从而修复bug。
1.3. Ant编译打包
Ant是一种基于Java的build工具,它类似于(Unix)C中的make。当项目较大时,每次重新编译、打包、测试等都会变得非常复杂而且重复,因此C语言提供了make脚本来批量完成这些工作。由于Java应用是平台无关的,所以不会用平台相关的make脚本来完成这些批处理任务了。Ant是一个流程脚本引擎,用于自动完成项目的编译、打包、测试。在Android工程里,可以使用Ant来编译工程、打包工程、测试工程、将工程直接安装到手机或模拟器中。
使用Ant对Android工程打包,一般会经过以下几个步骤:
1. 用aapt命令生成R.java文件。
2. 用aidl命令生成相应Java文件。
3. 用javac命令编译Java源文件生成“.class”文件。
4. 用dx.bat将“.class”文件转换成classes.dex文件。
5. 用aapt命令生成资源包文件resources.ap_。
6. 用apkbuilder.bat打包资源和classes.dex文件,生成unsigned.apk。
7. 用jarsinger命令对apk认证,生成signed.apk。
为了更好的理解Ant编译Android工程,必须首先熟悉步骤所使用到各命令。
aapt(Android Asset Packaging Tool)命令
aapt命令可以根据资源文件自动生成R.java文件,该命令主要有如下参数:
l -f:强制覆盖已存在的文件。
l -m:在-J指定的位置下自动生成相应包的目录。
l -J:指定R.java文件生成的目录。
l -S:指定资源目录。
l -M:指定清单文件。
l -I:引入类库。
图21-11就是一个生成R.java文件的示例,命令表示根据res文件资源,在gen文件下生成R文件。
图21-11 aapt命令运行
图21-12演示了如何打包res、assets资源文件生成到指定包resources.ap_下。
图21-12 aapt命令运行资源
aidl(Android Interface Definition Language)命令
aidl是一种Android内部进程通信接口的描述语言,通过它可以定义进程间的通信接口。在Eclipse开发中,编译aidl文件,ADT插件会像资源文件一样把aidl文件编译成Java代码,生成在gen文件夹下。利用aidl命令也可以编辑上述过程,输入命令为“aidl OPINONS INPUT [OUTPUT]”,其中,INPUT表示输入aidl文件路径,OUTPUT表示输出aidl文件对应的Java文件路径。
javac(Java Compiler)命令
javac命令是根据源Java文件生成对应的“.class”文件命令,其主要的参数有:
l -d <目录>:指定存放生成的类文件的位置。
l -bootclasspath <路径>:覆盖引导类文件的位置。
dx命令
在Android中,模拟器运行的是“.dex”文件,dx命令就是将“.class”文件转换成“.dex”文件。如图21-13所示,将bin目录下的“.class”文件转换成classes.dex文件,输出到bin目录下。
图21-13 dx命令运行示意图
apkbuilder命令
apkbuilder命令将classes.dex文件和resources.ap_文件生成apk包。命令形式为:“apkbuilder ${output.apk.file}-u -z ${packagedresource.file} -f ${dex.file} -rf ${source.dir} –rj ${libraries.dir}”,参数解释如下:
l -u:创建一个未签名的apk。
l ${output.apk.file} :表示要输出的apk路径,例如:d:/HelloWorld/bin/my.apk。
l -z ${packagedresource.file}:编译好的资源包路径,例如:d:/HelloWorld/bin/resources.ap_。
l -f ${dex.file}:添加的dex文件的路径,例如:d:/HelloWorld/bin/classes.dex。
l -rf ${source.dir} :源文件的路径,例如:d:/HelloWorld/src。
l -rj ${libraries.dir} :表示引用的库的路径,例如:d:/HelloWorld/libs。
图21-14显示了如何使用apkbuilder命令将classes.dex文件和resources.ap_生成apk包。
图21-14 apkbuilder命令运行
jarsigner命令
jarsigner命令对生成的apk包进行签证,如图21-15显示了如何利用jarsigner命令将无签证的apk包签证。
图21-15 jarsigner命令运行
在签证的过程中,需要使用到证书文件,可以利用keytool命令,创建证书,如图21-16所示:
图21-16 keytool命令运行
也可以在Eclipse里使用ADT提供的图形界面完成证书的创建。选中项目,点击右键:“Android Tools”→“Export Signed Application Package”,在其中的“Keystoreselection”选择“Create new keystore”,然后按照提示填写信息,完成创建。
下面详解介绍如何编写build.xml,用于实现Android工程的自动编译、打包。首先需要定义多个变量属性,用来表示使用到的路径、目录等。如下所示定义了一个build.properties文件,用于定义变量属性:
build.properties代码清单21-3-0:
target=android-8
sdk.dir=G:\\android\\android\\android-sdk
apkbuilder=${sdk.dir}\\tools\\apkbuilder.bat
sdkhomedir=G:\\android\\android\\android-sdk
android-framework=${sdk.dir}
android-jar=${sdkhomedir}\\platforms\\android-8\\android.jar
aapt=${sdkhomedir}\\platform-tools\\aapt
aidl=${sdkhomedir}\\platform-tools\\aidl
dx=${sdkhomedir}\\platform-tools\\dx.bat
adb=${sdkhomedir}\\platform-tools\\adb
apkbuilder=${sdkhomedir}\\tools\\apkbuilder.bat
jarsigner=D:\\jdk1.6.0_18\\bin\\jarsigner
projecthomedir=G:\\workspace\\AntTest
builddir=${projecthomedir}\\build
resource-dir=${projecthomedir}\\res
asset-dir=${projecthomedir}\\assets
srcdir=${projecthomedir}\\src
outdir-gen=${builddir}\\src
outdir-classes=${builddir}\\classes
outdir-dx=${builddir}\\dx
resources-package=${builddir}\\respak
apkdir=${builddir}\\apk
unsignedapkname=unsigntest.apk
apkname=test.apk
然后,在build.xml文件里使用<property file="build.properties"/>引入变量,实现初始化:
<!-- 初始化工作 -->
<target name="init">
<echo>Initializingall output directories...</echo>
<deletedir="${outdir-bin}" />
<mkdirdir="${outdir-bin}" />
<mkdirdir="${outdir-classes}" />
</target>
使用aapt命令生成R.java文件,关键代码如下所示:
<target name="GenRJAVA">
<echo>GeneratingR.java / Manifest.java from the resources...</echo>
<mkdirdir="${outdir-gen}" />
<execexecutable="${aapt}" failonerror="true">
<argvalue="package" />
<argvalue="-m" />
<argvalue="-J" />
<argvalue="${outdir-gen}" />
<argvalue="-M" />
<argvalue="${projecthomedir}/AndroidManifest.xml" />
<argvalue="-S" />
<argvalue="${resource-dir}" />
<argvalue="-I" />
<argvalue="${android-jar}" />
</exec>
</target>
接着,利用aidl命令生成Java源文件:
<targetname="aidl" depends="copy">
<echo>Compilingaidl files into Java classes...</echo>
<applyexecutable="${aidl}" failonerror="true">
<!-- 指定预处理文件 -->
<argvalue="-p${sdk.dir}" />
<!--aidl声明的目录 -->
<argvalue="-I${srcdir}" />
<!-- 指定哪些文件需要编译 -->
<filesetdir="${srcdir}">
<includename="**/*.aidl" />
</fileset>
</apply>
</target>
然后,将源文件编译成“.class”文件,如果使用到了第三方类库,可以在classpath标签下配置:
<targetname="compile" depends="copy, GenRJAVA, aidl">
<mkdirdir="${outdir-classes}" />
<javacencoding="UTF-8" target="1.5"
debug="true" extdirs=""
srcdir="${outdir-gen}"
destdir="${outdir-classes}"
bootclasspath="${android-jar}">
<classpathrefid="project.classpath" />
</javac>
</target>
接着,将“.class”文件转换成classes.dex文件,如果使用到第三方类库,可以在最后用参数的形式配置:
<target name="dex" depends="compile">
<echo>Converting compiled files and externallibraries into ${outdir-dx}/test.dex...</echo>
<mkdirdir="${outdir-dx}" />
<applyexecutable="${dx}" failonerror="true"parallel="true">
<argvalue="--dex" />
<!--输出文件 -->
<argvalue="--output=${outdir-dx}/test.dex" />
<!--要生成.dex文件的源classes和libraries -->
<argpath="${outdir-classes}" />
<filesetdir="${projecthomedir}" includes="*.jar" />
</apply>
</target>
然后,利用aapt命令将资源文件打包:
<targetname="package-res">
<echo>Packagingresources and assets...</echo>
<mkdirdir="${apkdir}" />
<execexecutable="${aapt}" failonerror="true">
<argvalue="package" />
<argvalue="-f" />
<argvalue="-M" />
<argvalue="${projecthomedir}/AndroidManifest.xml" />
<argvalue="-S" />
<argvalue="${resource-dir}" />
<argvalue="-A" />
<argvalue="${asset-dir}" />
<argvalue="-I" />
<argvalue="${android-jar}" />
<argvalue="-F" />
<argvalue="${resources-package}" />
</exec>
</target>
接着,利用apkbuilder命令打包未签证的apk包:
<targetname="packageAPK" depends="dex, package-res">
<echo>Packagingapk for release...</echo>
<execexecutable="${apkbuilder}" failonerror="true">
<argvalue="${apkdir}/${unsignedapkname}" />
<argvalue="-u" />
<argvalue="-z" />
<argvalue="${resources-package}" />
<argvalue="-f" />
<argvalue="${outdir-dx}/test.dex" />
<argvalue="-rf" />
<argvalue="${srcdir}" />
<argvalue="-rj" />
<argvalue="${outdir-gen}" />
</exec>
<echo>It will need to be signed withjarsigner before being published.</echo>
</target>
然后,利用jarsigner命令对apk签证:
<targetname="signAPK" depends="packageAPK">
<echo>Packaging${out-unsigned-package} for release...</echo>
<execexecutable="${jarsigner}" failonerror="true">
<argvalue="-verbose" />
<argvalue="-storepass" />
<argvalue="firstpeople" />
<argvalue="-keypass" />
<argvalue="firstpeople" />
<argvalue="-keystore" />
<argvalue="android.keystore" />
<argvalue="-signedjar" />
<argvalue="${apkdir}/${apkname}" />
<argvalue="${apkdir}/${unsignedapkname}" />
<argvalue="android.keystore" />
</exec>
</target>
最后,利用adb命令发布apk,如下所示:
<targetname="installAPK" depends="signAPK">
<echo>InstallAPK...</echo>
<execexecutable="adb" failonerror="true">
<argvalue="install" />
<argvalue="${apkdir}/${apkname}" />
</exec>
</target>
这样就完成了build.xml文件的编辑。Eclipse包含了Ant的所有功能,可以在Eclipse中直接运行Ant,如图21-17所示:
图21-17 Ant运行
使用Ant打包使得Android项目编译周期变短,编译效率大大提高,同时利用xml脚本,可以高效的控制编译的细节,实现批量编译,批量打包。
1.4. 玄德有话说
刘备:反编译apk,资源文件在Java文件中都是十进制,这咋办?
孔明:可以编写程序根据R.java的映射关系,扫描Java文件替换十进制的字符串。
张飞:现在AndroidSDK 2.3版本之后启用了混淆,反编译还有什么用?
孔明:虽然AndroidSDK 2.3版本之后启用了混淆机制,但反编译对以前的老的版本还是可以的。反编译Android SDK 2.3之后的版本,还是可以看出工程的部分信息,例如布局文件。只要有一些开发功底,反编译后的代码还是可以给我们很多启发的。
关羽:Ant打包的apk怎么签名不正确?
孔明:请检查keystore文件名与别名是否一致。
刘备:Ant打包,adb报错咋办?
孔明:第一,确保E:\Android\android-sdk\platform-tools目录下有adb.exe文件。第二,确保环境变量path中有“\android-sdk\platform-tools”。
- 第三篇 提高篇—大胆曹贼,我跟你拼啦!第21回 反编译比较符合我的性格!
- 我的性格你是懂的
- 我“善变”的性格
- 我的性格
- 我的性格
- 我的性格
- 我的性格测试
- 我的性格分析
- 我的第三篇
- 我的第三篇
- 我的第一篇博文——启航啦!
- 发我的第一篇博客啦!!!
- 跟我一起学习C++虚函数--第三篇
- 让我看看你是什么颜色的性格
- 跟我一起写 Makefile(精华帖合辑)之——提高篇
- 你别跟我婆婆妈妈的
- 关于使用Myeclipse修改Tomcat内存的体会——tomcat 我和你拼了。。。。
- 我的性格(魔兽)
- 二维DP,数塔变形(1176)
- Redis和Memcache对比及选择
- 关机不断电修复DSDT代码
- Raid的一些记录
- ZooKeeper的FastLeaderElection算法源码解析
- 第三篇 提高篇—大胆曹贼,我跟你拼啦!第21回 反编译比较符合我的性格!
- 追求代码质量: 用代码度量进行重构
- android:px,dp(dip),sp的区别
- 阿里巴巴fastjson简用
- 第22回多线程是干什么滴!
- Mongodb Expire Documents after a Specified Number of Seconds
- java 趣味题目解题。
- onresume和onrestart的区别
- PHP获取POST数据的三种方法