忙了三四周,总算把购开心的ios版(appStore搜“购开心”)成功翻译成了android版,UI效果基本保持一致,上一张UI效果图吧,很养眼的:
还不错吧,进入正题吧。
以前一直是让我徒弟混淆和打包的,这个就剩下我一个人了,弄了一次,时间太久了,还太麻烦了,于是,我就研究了下ant打包,下面就简单说下吧:
首先,做任何开发前,肯定是各种环境搭建和配置啊,ant的搭建很简单:
一、安装ant
到官方主页http://ant.apache.org下载新版(目前为Ant-1.9.2)的ant,得到的是一个apache-ant-1.8.1-bin.zip的压缩包。将其解压到你的硬盘上,例如:D:\Android\apache-ant-1.9.2
二、配置环境变量
window中设置ant环境变量:
ANT_HOME D:/Android/apache-ant-1.9.2
path D:/Android/apache-ant-1.9.2/bin
classpath D:/Android/apache-ant-1.9.2/lib
linux中设置ant环境变量:
root用户登陆,用vi编辑器修改root目录下的".bash_profile"属性文件,假设Ant安装在/user/local/ant目录下,要在文件的最后加上
"exportANT_HOME=/user/local/ant"和"export PATH=$PATH:$ANT_HOME/bin"
三、验证ant
为了验证ant是否成功安装,可以进行如下操作:
依次选择:开始->运行->cmd,输入如下命令:ant
如果出现如下内容,说明安装成功:
Buildfile: build.xml does not exist!
Build failed
当然,JAVA_HOME、ANDROID_SDK_HOME等的配置这里就不说了
四、我们就在项目中添加build.xml
code如下:
<?xml version="1.0" encoding="utf-8"?> <project name="HappyShopping" default="release" > <!-- ANT环境变量 --> <property environment="env" /> <!-- 应用名称 --> <property name="appName" value="${ant.project.name}" /> <!-- SDK目录(获取操作系统环境变量ANDROID_SDK_HOME的值) --> <property name="sdk-folder" value="${env.ANDROID_SDK_HOME}" /> <!-- SDK指定平台目录 --> <property name="sdk-platform-folder" value="${sdk-folder}/platforms/android-16" /> <!-- SDK中tools目录 --> <property name="sdk-tools" value="${sdk-folder}/tools" /> <!-- SDK指定平台中tools目录 --> <property name="sdk-platform-tools" value="${sdk-folder}/platform-tools" /> <!-- 使用到的命令(当前系统为windows,如果系统为linux,可将.bat文件替换成相对应的命令) --> <property name="aapt" value="${sdk-platform-tools}/aapt" /> <property name="aidl" value="${sdk-platform-tools}/aidl" /> <property name="dx" value="${sdk-platform-tools}/dx.bat" /> <property name="apkbuilder" value="${sdk-tools}/apkbuilder.bat" /> <property name="jarsigner" value="${env.JAVA_HOME}/bin/jarsigner" /> <!-- 编译需要的jar; 如果项目使用到地图服务则需要maps.jar --> <property name="android-jar" value="${sdk-platform-folder}/android.jar" /> <property name="android-maps-jar" value="${sdk-folder}/add-ons/addon_google_apis_google_inc_8/libs/maps.jar" /> <!-- 编译aidl文件所需的预处理框架文件framework.aidl --> <property name="framework-aidl" value="${sdk-platform-folder}/framework.aidl" /> <!-- 生成R文件的相对目录 --> <property name="outdir-gen" value="gen" /> <!-- 编译后的文件放置目录 --> <property name="outdir-bin" value="bin" /> <!-- 清单文件 --> <property name="manifest-xml" value="AndroidManifest.xml" /> <!-- 源文件目录 --> <property name="resource-dir" value="res" /> <property name="asset-dir" value="assets" /> <!-- java源文件目录 --> <property name="srcdir" value="src" /> <property name="srcdir-ospath" value="${basedir}/${srcdir}" /> <!-- 外部类库所在目录 --> <property name="external-lib" value="libs" /> <property name="external-lib-ospath" value="${basedir}/${external-lib}" /> <!-- 生成class目录 --> <property name="outdir-classes" value="${outdir-bin}" /> <property name="outdir-classes-ospath" value="${basedir}/${outdir-classes}" /> <!-- classes.dex相关变量 --> <property name="dex-file" value="classes.dex" /> <property name="dex-path" value="${outdir-bin}/${dex-file}" /> <property name="dex-ospath" value="${basedir}/${dex-path}" /> <!-- 经过aapt生成的资源包文件 --> <property name="resources-package" value="${outdir-bin}/resources.ap_" /> <property name="resources-package-ospath" value="${basedir}/${resources-package}" /> <!-- 未认证apk包 --> <property name="out-unsigned-package" value="${outdir-bin}/${appName}-unsigned.apk" /> <property name="out-unsigned-package-ospath" value="${basedir}/${out-unsigned-package}" /> <!-- 证书文件 --> <property name="keystore-file" value="${basedir}/naomi" /> <!-- 已认证apk包 --> <property name="out-signed-package" value="${outdir-bin}/${appName}.apk" /> <property name="out-signed-package-ospath" value="${basedir}/${out-signed-package}" /> <!-- 代码混淆配置 --> <property name="proguard-home" value="D:/Android/android-sdk-windows/tools/proguard/lib" /> <target name="init" > <echo> Initializing all output directories... </echo> <delete dir="${outdir-bin}" /> <mkdir dir="${outdir-bin}" /> <mkdir dir="${outdir-classes}" /> </target> <!-- 根据工程中的资源文件生成R.java文件 --> <target name="gen-R" depends="init" > <echo> Generating R.java from the resources... </echo> <exec executable="${aapt}" failonerror="true" > <arg value="package" /> <arg value="-f" /> <arg value="-m" /> <arg value="-J" /> <arg value="${outdir-gen}" /> <arg value="-S" /> <arg value="${resource-dir}" /> <arg value="-M" /> <arg value="${manifest-xml}" /> <arg value="-I" /> <arg value="${android-jar}" /> </exec> </target> <!-- 编译aidl文件 --> <target name="aidl" depends="gen-R" > <echo> Compiling .aidl into java files... </echo> <apply executable="${aidl}" failonerror="true" > <!-- 指定预处理文件 --> <arg value="-p${framework-aidl}" /> <!-- aidl声明的目录 --> <arg value="-I${srcdir}" /> <!-- 目标文件目录 --> <arg value="-o${outdir-gen}" /> <!-- 指定哪些文件需要编译 --> <fileset dir="${srcdir}" > <include name="**/*.aidl" /> </fileset> </apply> </target> <!-- 将工程中的java源文件编译成class文件 --> <target name="compile" depends="aidl" > <echo> Compiling java source code... </echo> <javac bootclasspath="${android-jar}" destdir="${outdir-classes}" encoding="utf-8" srcdir="." target="1.5" > <classpath> <fileset dir="${external-lib}" includes="*.jar" /> <filelist> <file name="${android-maps-jar}" /> </filelist> </classpath> </javac> </target> <!-- 混淆代码 --> <target name="proguard" depends="compile" > <echo> Proguad .... </echo> <jar basedir="${outdir-classes}" destfile="temp.jar" /> <java failonerror="true" fork="true" jar="${proguard-home}/proguard.jar" > <jvmarg value="-Dmaximum.inlined.code.length=32" /> <arg value="-injars temp.jar" /> <arg value="-outjars optimized.jar" /> <arg value="-libraryjars ${android-jar}" /> <arg value="-dontpreverify" /> <arg value="-dontoptimize" /> <arg value="-dontusemixedcaseclassnames" /> <arg value="-repackageclasses ''" /> <arg value="-allowaccessmodification" /> <!-- 混淆配置的引用 --> <arg value="@proguard-project.txt"/> </java> <delete file="temp.jar" /> <delete dir="${outdir-classes}" /> <mkdir dir="${outdir-classes}" /> <unzip dest="${outdir-classes}" src="optimized.jar" /> <delete file="optimized.jar" /> </target> <!-- 将.class文件转化成.dex文件 --> <target name="dex" depends="proguard" > <echo> Converting compiled files and external libraries into a .dex file... </echo> <exec executable="${dx}" failonerror="true" > <arg value="--dex" /> <!-- 输出文件 --> <arg value="--output=${dex-ospath}" /> <!-- 要生成.dex文件的源classes和libraries --> <arg value="${outdir-classes-ospath}" /> <arg value="${external-lib-ospath}" /> </exec> </target> <!-- 将资源文件放进输出目录 --> <target name="package-res-and-assets" > <echo> Packaging resources and assets... </echo> <exec executable="${aapt}" failonerror="true" > <arg value="package" /> <arg value="-f" /> <arg value="-M" /> <arg value="${manifest-xml}" /> <arg value="-S" /> <arg value="${resource-dir}" /> <arg value="-A" /> <arg value="${asset-dir}" /> <arg value="-I" /> <arg value="${android-jar}" /> <arg value="-F" /> <arg value="${resources-package}" /> </exec> </target> <!-- 打包成未签证的apk --> <target name="package" depends="dex, package-res-and-assets" > <echo> Packaging unsigned apk for release... </echo> <exec executable="${apkbuilder}" failonerror="true" > <arg value="${out-unsigned-package-ospath}" /> <arg value="-u" /> <arg value="-z" /> <arg value="${resources-package-ospath}" /> <arg value="-f" /> <arg value="${dex-ospath}" /> <arg value="-rf" /> <arg value="${srcdir-ospath}" /> </exec> <echo> It will need to be signed with jarsigner before being published. </echo> </target> <!-- 对apk进行签证 --> <target name="jarsigner" depends="package" > <echo> Packaging signed apk for release... </echo> <exec executable="${jarsigner}" failonerror="true" > <arg value="-keystore" /> <arg value="${keystore-file}" /> <arg value="-storepass" /> <arg value="123456" /> <arg value="-keypass" /> <arg value="123456" /> <arg value="-signedjar" /> <arg value="${out-signed-package-ospath}" /> <arg value="${out-unsigned-package-ospath}" /> <!-- 不要忘了证书的别名 --> <arg value="blockcheng" /> </exec> </target> <!-- 发布 --> <target name="release" depends="jarsigner" > <!-- 删除未签证apk --> <echo> delete unsigned apk </echo> <delete file="${out-unsigned-package-ospath}" /> <echo> copy apk from ${out-signed-package-ospath} to D:/workspaceAndroid/Release/happyShopping.apk </echo> <copy file="${out-signed-package-ospath}" tofile="D:/workspaceAndroid/Release/happyShopping.apk" /> <echo> clean the workspace bin folder.... </echo> <delete dir="${outdir-classes}"/> <delete file="${dex-ospath}" /> <delete file="${resources-package-ospath}" /> <delete file="${outdir-bin}" /> <echo> </echo> </target> </project>如果不需要混淆代码,去掉上面的 proguard相关的配置就可以了
五、配置proguard属性:
proguard-project.txt
# To enable ProGuard in your project, edit project.properties # to define the proguard.config property as described in that file. # # Add project specific ProGuard rules here. # By default, the flags in this file are appended to flags specified # in ${sdk.dir}/tools/proguard/proguard-android.txt # You can edit the include path and order by changing the ProGuard # include property in project.properties. # # For more details, see # http://developer.android.com/guide/developing/tools/proguard.html # Add any project specific keep options here: # If your project uses WebView with JS, uncomment the following # and specify the fully qualified class name to the JavaScript interface # class: #-keepclassmembers class fqcn.of.javascript.interface.for.webview { # public *; #} -optimizationpasses 5 -dontusemixedcaseclassnames -dontskipnonpubliclibraryclasses -dontskipnonpubliclibraryclassmembers -dontskipnonpubliclibraryclasses -dontpreverify -libraryjars libs/android-support-v4.jar -libraryjars libs/core.jar -verbose -optimizations !code/simplification/arithmetic,!field/*,!class/merging/* -dontwarn android.support.v4.** -keep class android.support.v4.app.** { *; } -keep interface android.support.v4.app.** { *; } -keep class com.actionbarsherlock.** { *; } -keep interface com.actionbarsherlock.** { *; } -keepattributes *Annotation* -keep public class * extends android.app.Activity -keep public class * extends android.support.v4.app.Fragment -keep public class * extends android.support.v4.app.FragmentActivity -keep public class * extends android.app.Application -keep public class * extends android.app.Service -keep public class * extends android.content.BroadcastReceiver -keep public class * extends android.content.ContentProvider -keep public class * extends android.app.backup.BackupAgentHelper -keep public class * extends android.preference.Preference -keep public class * extends blockcheng.BssicAct -keep public class * extends blockcheng.controller.BCFragment -keep public class com.android.vending.licensing.ILicensingService -keepclasseswithmembernames class * { native <methods>; } -keepclasseswithmembers class * { public <init>(android.content.Context, android.util.AttributeSet); } -keepclasseswithmembers class * { public <init>(android.content.Context, android.util.AttributeSet, int); } -keepclassmembers class * extends android.app.Activity { public void *(android.view.View); } -keepclassmembers enum * { public static **[] values(); public static ** valueOf(java.lang.String); } -keepclassmembers class * { public <init>(org.json.JSONObject); } -keep public class blockcheng.R$*{ public static final int *; } -keep public class blockcheng.controller.BlockchengClass.JavaScriptInterface { public <methods>; } -keepnames class blockcheng.controller.BlockchengClass$* { public <fields>; public <methods>; } -keepnames class blockcheng.controller.BlockchengClass$* { public <fields>; public void showContacts(); }
上面的配置中,blockcheng、BC等开头的类,都是被我替换的,不是真实的,具体的类包名和类名,以各人自己的为主。
注意,这个混淆中,开始几行配置很重要,网上很多同学问的ant、proguard相关的错误(什么找不到app.android.v4类等),都是因为缺少这几行导致,但没人回答,这里,我就直接给出了:
-libraryjars libs/android-support-v4.jar -libraryjars libs/core.jar -verbose -optimizations !code/simplification/arithmetic,!field/*,!class/merging/* -dontwarn android.support.v4.** -keep class android.support.v4.app.** { *; } -keep interface android.support.v4.app.** { *; } -keep class com.actionbarsherlock.** { *; } -keep interface com.actionbarsherlock.** { *; } -keepattributes *Annotation* -keep public class * extends android.app.Activity -keep public class * extends android.support.v4.app.Fragment -keep public class * extends android.support.v4.app.FragmentActivity
这个配置主要是针对 android-support.v4和库相关的,请需要的同学注意。
最后的几行配置,是因为我代码中调用了asset中js文件导致的,js相关的操作代码,是不可以混淆的,故需要避开。
六、运行ant命令,构建开始:
命令行输入类似: D:/Android/apache-ant-1.9.2/bin/ant.bat -buildfile D:/workspa
ceAndroid/naomiHappyShopping/build.xml
就可以完成代码混淆和apk输出:
....... release: [echo] [echo] delete unsigned apk [echo] [delete] Deleting: D:\workspaceAndroid\naomiHappyShopping\bin\HappyShoppingAn t-unsigned.apk [echo] [echo] copy apk from D:\workspaceAndroid\naomiHappyShopping /bin/HappyShoppingAnt.apk to D:/workspaceAndroid/Release/happyShopping.apk [echo] [copy] Copying 1 file to D:\workspaceAndroid\Release [echo] [echo] clean the workspace bin folder.... [echo] [delete] Deleting directory D:\workspaceAndroid\naomiHappyShopping\bin [echo] [echo] BUILD SUCCESSFUL Total time: 41 seconds看看时间,是不是比手动方便多了啊,而且反编译一看,代码真的不能再读了。
另外注意:不同人的路径等配置,需要根据各人自己的来,不能直接拷贝引用。