Android ANT脚本打包及混淆文件

http://p.ymt360.com/w/app/wiki/tech/build_apk/

简介

Android支持使用ANT打包。
通过ANT脚本,可以对文件进行编译、打包、安装、联合SVN自动拉取等。
并且支持多种方式打包,如debug、release、批量打包等场景。
eclipse项目是通过调用SDK提供的ANT脚本build.xml文件进行打包的。

附件是AndroidSDK附带的打包脚本,超详细,可以参考学习下。build.xml
(建议使用JDK1.6环境,在之前ANT使用过程中被1.7环境坑过)

使用建议

Android studio 使用gradle 进行编译打包,
gradle是google推荐的打包方式,如果以后开发环境切换到Android studio 建议使用gradle

如果是在eclipse开发环境可以使用ANT或者gradle

YMT APP开发时 Android studio是测试版本阶段,gradle学习资料较少,基于目前的目录结构,采用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

配合我们项目介绍在YMT项目中使用ANT的流程

1.clean清除temp文件
2.初始化各种temp目录
3.用aapt命令 打包项目的资源文件 生成R.java文件
4.生成buildconfig类 主要用于在项目中调用 BuildConfig.Debug判断是否DebugAPK的代码
5.用aidl命令生成相应java文件
6.用javac命令编译java源文件生成class文件
7.将class文件生成jar文件
8.对打包后的结果进行混淆
9.用dx.bat将class文件转换成classes.dex文件
10.用apkbuilder.bat打包资源和classes.dex文件,生成unsigned.apk
11.用jarsinger命令对apk认证,生成signed.apk
12.zipalign,对混淆的签名包做优化

脚本分析

我们详细介绍每一个步骤所使用到的命令:

打包过程不在代码基础上进行操作,全部在副本里面进行操作。

1.清除temp文件,删除之前复制代码(包括依赖库代码)到的temp文件夹

<target name="clean" >

        <echo>
			Start clean...

        </echo>

        <mkdir dir="${apk}" />

        <delete dir="${temp}" />

        <delete dir="${ymtBaseApp-temp}" />

        <delete dir="${pulltofresh-project-temp}" />

        <delete dir="${datetimepicker-library-temp}" />

        <delete dir="${c3kDemo-lib-temp}" />

        <echo>
			Finished clean...

        </echo>

        <echo>
        </echo>
    </target>
  1. 创建temp文件夹,复制依赖库文件,项目文件到temp文件夹中(src,gen,lib等)
<target name="init" >

        <echo>
			Start init...

        </echo>

        <echo>
			If not exist, then create the directories...

        </echo>

        <mkdir dir="${apk}" />

        <mkdir dir="${temp}" />

        <mkdir dir="${ymtBaseApp-temp}" />

        <mkdir dir="${pulltofresh-project-temp}" />

        <mkdir dir="${datetimepicker-library-temp}" />

        <mkdir dir="${c3kDemo-lib-temp}" />

        <mkdir dir="${classes}" />

        <mkdir dir="${classes-obfs}" />

        <mkdir dir="${gen}" />

        <mkdir dir="${lib}" />

        <echo>
			Copy files to temp directory...

        </echo>

        <copy
            filtering="true"
            todir="${temp}" >

            <fileset dir="${project_path}" >

                <exclude name="**/.svn/*" />

                <exclude name="**/temp/" />

                <exclude name="**/temp2/" />

                <exclude name="**/bin/" />

                <exclude name="**/gen/" />
            </fileset>
        </copy>

        <echo>
			Copy files of xxx android library project to temp2 directory...

        </echo>

        <copy
            filtering="true"
            todir="${ymtBaseApp-temp}" >

            <fileset dir="${ymtBaseApp}" >

                <exclude name="**/.svn/*" />

                <exclude name="**/bin/" />

                <exclude name="**/gen/" />
            </fileset>
        </copy>

        <copy
            filtering="true"
            todir="${pulltofresh-project-temp}" >

            <fileset dir="${pulltofresh-project}" >

                <exclude name="**/.svn/*" />

                <exclude name="**/bin/" />

                <exclude name="**/gen/" />
            </fileset>
        </copy>

        <copy
            filtering="true"
            todir="${c3kDemo-lib-temp}" >

            <fileset dir="${c3kDemo-lib}" >

                <exclude name="**/.svn/*" />

                <exclude name="**/bin/" />

                <exclude name="**/gen/" />
            </fileset>
        </copy>

        <copy
            filtering="true"
            todir="${datetimepicker-library-temp}" >

            <fileset dir="${datetimepicker-lib}" >

                <exclude name="**/.svn/*" />

                <exclude name="**/bin/" />

                <exclude name="**/gen/" />
            </fileset>
        </copy>

        <!-- copy All lib to lib folder -->
        <copy
            filtering="true"
            todir="${lib}" >

            <fileset dir="${ymtBaseApp}/libs" />

            <fileset dir="${c3kDemo-lib}/libs" />

            <fileset dir="${datetimepicker-lib}/libs" />

        </copy>

        <echo>
				Finish init...

        </echo>
    </target>
  1. aapt(Android Asset Packaging Tool)命令,根据资源文件生成R.java文件

参数说明:
-f 强制覆盖已存在的文件。
-m 在-J指定的位置下自动生成相应的包的目录。
-J 指定R.java文件生成的目录。
-S 指定资源目录。
-M 指定清单文件。
-I 引入类库。
注意,我们当前所在的位置是ant项目根目录,所以必要时需要输入很多关于命令的路径,以下示例也是一样。

<!-- 打包项目的资源文件 -->

    <target name="generate" >

        <echo>
			Package res and assets...

        </echo>

        <exec
            executable="${aapt}"
            failonerror="true" >

            <arg value="package" />

            <arg value="-f" />

            <arg value="-m" />

            <arg value="-J" />

            <arg value="${gen}" />

            <arg value="-M" />

            <arg value="${temp}/AndroidManifest.xml" />

            <arg value="-S" />

            <arg value="${res}" />

            <arg value="-S" />

            <arg value="${ymtBaseApp-temp}/res" />

            <arg value="-S" />

            <arg value="${pulltofresh-project-temp}/res" />

            <arg value="-S" />

            <arg value="${datetimepicker-library-temp}/res" />

            <arg value="-S" />

            <arg value="${c3kDemo-lib-temp}/res" />

            <arg value="--extra-packages" />

            <arg value="com.ymt360.app:com.handmark.pulltorefresh.library:com.fourmob.datetimepicker:com.example.client" />

            <arg value="-A" />

            <arg value="${assets}" />

            <arg value="-I" />

            <arg value="${androidjar}" />

            <arg value="-F" />

            <arg value="${temp}/${file_name}.ap_" />

            <arg value="--auto-add-overlay" />
        </exec>
    </target>

4.生成buildconfig类和依赖库的buildconfig类 很重要,关系到测试代码是否能在正式版本关闭。
引入ant-tasks.jar 目的是为使用buildconfig命令

if (BuildConfig.DEBUG) {
      do something;
}
<target name="buildconfig" >

        <echo level="info" >
			Handling BuildConfig class...

        </echo>

        <!-- jar file from where the tasks are loaded -->

        <path id="android.antlibs" >

            <pathelement path="${android_home}/tools/lib/ant-tasks.jar" />
        </path>

        <!-- Custom tasks -->

        <taskdef
            classpathref="android.antlibs"
            resource="anttasks.properties" />

        <buildconfig
            buildType="${build.is.packaging.debug}"
            genFolder="${gen}"
            package="${project.app.package}"
            previousBuildType="${build.last.is.packaging.debug}" />

        <buildconfig
            buildType="${build.is.packaging.debug}"
            genFolder="${c3kDemo-lib-temp}/gen"
            package="com.example.client"
            previousBuildType="${build.last.is.packaging.debug}" />
    </target>
  1. aidl(Android Interface Definition Language)命令,根据.aidl定义文件生成java文件
<target name="aidl" >

        <echo>
Start compile aidl files to java classes...

        </echo>

        <apply
            executable="${aidl}"
            failonerror="true" >

            <arg value="-p${android_framework}" />

            <arg value="-I${src}" />

            <arg value="-o${gen}" />

            <fileset dir="${src}" >

                <include name="**/*.aidl" />
            </fileset>
        </apply>
    </target>
  1. 编译项目和依赖包的.java文件 JDK版本使用的是1.6版本

javac命令

<!-- 编译项目的.java文件 -->

    <target name="compile" >

        <echo>
			Start compile source code...

        </echo>

        <echo>
			The debug param is default to true, for the exception upload feature required it...

        </echo>

        <javac
            bootclasspath="${androidjar}"
            debug="true"
            destdir="${classes}"
            encoding="${encoding}"
            extdirs=""
            target="1.6" >

            <src path="${pulltofresh-project-temp}/src" />

            <src path="${c3kDemo-lib-temp}/src" />

            <src path="${datetimepicker-library-temp}/src" />

            <src path="${ymtBaseApp-temp}/src" />

            <src path="${src}" />

            <src path="${gen}" />

            <src path="${c3kDemo-lib-temp}/gen" />

            <classpath>

                <fileset
                    dir="${lib}"
                    includes="*.jar" />

            </classpath>
        </javac>
    </target>
  1. 将class文件打包为jar
    <target
        name="package"
        if="${notObfuscated}" >

        <echo>
Packing compile results...

        </echo>

        <jar
            basedir="${classes}"
            destfile="temp.jar" />

        <echo>
Copy jar to test directory...

        </echo>

        <copy
            file="temp.jar"
            todir="${autotest}" />
    </target>
  1. 对打包后的结果进行混淆 并输出mapping文件

注意:混淆参数需要根据项目实际情况进行调整

<target
        name="obfuscate"
        if="${obfuscated}" >

        <echo>
Obfuscating package...

        </echo>

        <java
            failonerror="true"
            fork="true"
            jar="${proguard_home}/lib/proguard.jar" >

            <jvmarg value="-Dmaximum.inlined.code.length=32" />

            <arg value="-injars temp.jar" />

            <arg value="-outjars obfuscated.jar" />

            <arg value="-libraryjars ${androidjar}" />

            <!-- 当混淆参数很多时,建议写在独立的proguard.cfg文件中,然后以下面方式来引用 -->

            <arg value="@${basedir}/proguard-project.txt" />

            <arg value="@${ymtBaseApp-temp}/proguard-project.txt" />

            <arg value="@${datetimepicker-library-temp}/proguard-project.txt" />

            <arg value="@${c3kDemo-lib-temp}/proguard-project.txt" />

            <arg value="-dontpreverify" />

            <arg value="-dontoptimize" />

            <arg value="-dontusemixedcaseclassnames" />

            <arg value="-repackageclasses &apos;&apos;" />

            <arg value="-allowaccessmodification" />

            <arg value="-verbose" />
            <!-- 打印混淆过程产生的中间信息,其中mapping用于反向解析异常信息 -->
            <!-- arg value="-dump ${apk}/dump.txt"/ -->
            <!-- arg value="-printusage ${apk}/usage.txt"/ -->

            <arg value="-printmapping ${apk}/mapping.txt" />
            <!-- arg value="-printseeds ${apk}/seeds.txt"/ -->

        </java>

        <delete file="temp.jar" />

        <unzip
            dest="${classes-obfs}"
            src="obfuscated.jar" />

        <delete file="obfuscated.jar" />

        <delete file="${project_path}/proguard/mapping.txt" />

        <copy
            file="${apk}/mapping.txt"
            todir="${project_path}/proguard" />
    </target>

9.用dx.bat将class文件转换成classes.dex文件

<target
        name="dex-obfs"
        if="${obfuscated}" >

        <echo>
Coverting dex-obfs obfuscated class files to dex file...

        </echo>

        <apply
            executable="${dx}"
            failonerror="true"
            parallel="true" >

            <arg value="--dex" />

            <arg value="--output=${dex-obfs}" />

            <arg path="${classes-obfs}" />

            <fileset
                dir="${lib}"
                includes="*.jar" />

            </apply>
    </target>

10.apkbuilder命令,根据classes.dex文件和resources.ap_生成为签证的apk包

A command line tool to package an Android application from various sources.
Usage: apkbuilder <out archive> [-v][-u][-storetype STORE_TYPE] [-z inputzip]
            [-f inputfile] [-rf input-folder] [-rj -input-path]
参数说明:
-u     Creates an unsigned package.
-z     Followed by the path to a zip archive. Adds the content of the application package.
-f      Followed by the path to a file. Adds the file to the application package.
-rf     Followed by the path to a source folder. Adds the java resources found in that folder to the application package, while keeping their path relative to the source folder.
-nf    Followed by the root folder containing native libraries to include in the application package.

新版本的SDK中apkbuilder.bat移除 需要在
sdk\build-tools\android-4.4 目录中添加apkbuilder.bat 附下载 apkbuilder.bat

apkbuilder.bat中需要修改下面3处的环境的地址为自己电脑对应地址
set java_exe=C:\Program Files\Java\jdk1.6.0_23\bin\java.exe
call "C:\Program Files\adt-bundle-windows-x86_64-20131030\sdk\tools\lib\find_java.bat"
set jarpath=C:\Program Files\adt-bundle-windows-x86_64-20131030\sdk\tools\lib\%jarfile%

<target
        name="release-obfs"
        if="${obfuscated}" >

        <echo>
Build unsigned and obfuscated apk file from dex and resouse...

        </echo>

        <exec
            executable="${apkbuilder}"
            failonerror="true" >

            <arg value="${temp}/${file_name}_obfs.apk" />

            <arg value="-u" />

            <arg value="-z" />

            <arg value="${temp}/${file_name}.ap_" />

            <arg value="-f" />

            <arg value="${dex-obfs}" />

            <arg value="-rj" />

            <arg value="${lib}" />

            <arg value="-nf" />

            <arg value="${lib}" />

        </exec>
    </target>

11.jarsigner命令,对上面生成的apk包进行签证

<target
        name="sign-obfs"
        if="${obfuscated}" >

        <echo>
Begin sign obfuscated package...

        </echo>

        <exec
            executable="${signer}"
            failonerror="true" >

            <arg value="-verbose" />

            <arg value="-keystore" />

            <arg value="${keystore}" />

            <arg value="-storepass" />

            <arg value="${store_pass}" />

            <arg value="-keypass" />

            <arg value="${key_pass}" />

            <arg value="-signedjar" />

            <arg value="${temp}/${file_name}_obfs_signed.apk" />

            <arg value="${temp}/${file_name}_obfs.apk" />

            <arg value="${key_name}" />
        </exec>
    </target>

12.zipalign,对混淆的签名包做优化

    <target
        name="zipalign-obfs"
        if="${obfuscated}" >

        <echo>
Start zipalign obfuscated package...

        </echo>

        <exec
            executable="${zipalign}"
            failonerror="true" >

            <arg value="-v" />

            <arg value="4" />

            <arg value="${temp}/${file_name}_obfs_signed.apk" />

            <arg value="${apk}/${nameprefix}_.apk" />
        </exec>

        <echo>
End zipalign...

        </echo>
    </target>

目录结构

build_deploy.xml 入口执行文件
build_option.xml 配置文件(目录配置等,根据不同环境,配置修改)
build_common.xml 步骤执行文件(一般执行步骤不变不需要修改)
proguard-project.txt 混淆配置文件

输出APK目录位置

<property
        name="apk"
        value="${project_path}/../${nameprefix}_apk" />

APK 文件名

<property
     name="nameprefix"
     value="ymt_mass_v4.0.0" />

使用示例

如果需要添加删除依赖包 需要修改如下步骤
1.clean步骤删除对应文件
2.init 步骤创建对应文件
3.generate 步骤添加下图的代码 --extra-packages中用:冒号分开

4.buildconfig中修改对应代码

5.compile步骤中添加对应代码 如果java代码中需要用到R文件 需要指定对应的gen 如<src path="${c3kDemo-lib-temp}/gen" />

6.混淆文件 建议写在独立的proguard.cfg文件中,然后以下面方式来引用

参考资料

参考资料:http://blog.csdn.net/liuhe688/article/details/6679879 等

混淆文件

新建Android项目后会自带一个混淆文件 按照里面的注释打开对应的混淆语句即可对工程进行混淆。
eclipse打包 混淆文件开关位置在project.properties中proguard.config=proguard-project.txt语句 注释则不混淆。如果使用ANT打包 需要在对应的打包脚本中修改。

添加类库
-libraryjars libs/baidumapapi_v2_4_0.jar
忽略警告
-dontwarn org.apache.commons.httpclient.
keep 代码不被混淆
-keep class com.umeng.
{*;}
-keep public class * extends com.umeng.update.UmengDialogButtonListener
-keep public class com.ymt360.app.mass.view.FlowLayout {

public <fields>;
public <methods>;

}

踩过的坑
不要使用中文注释 会导致中文注释紧跟的下面一行被注释掉 不起作用,解决办法用英文注释。

eclipse打包

步骤
1.注意 eclipse打包的时候要关闭自动编译勾选项,否则buildconfig文件会在打包前生成,导致BuildConfig.DEBUG为debug值。

2.如图

over

欢迎完善

时间: 2024-10-07 10:20:48

Android ANT脚本打包及混淆文件的相关文章

android Ant批打包学习(二)---生成有签名且混淆的apk包

本篇文章预期目标:                 生成有签名apk文件 详细步骤如下: 1  定义文件 两个文件 1.1  名字:local.properties 内容:SDK的路径(例如:sdk.dir=/Users/lincoln/Android/sdk) 1.2 名字:ant.properties 内容: source.dir=src out.dir=bin proguard.config=proguard.cfg   (添加混淆,必须保证proguard.cfg 文件存在) key.s

android Ant批打包学习(一)

1  Apache Ant安装.配置环境变量 1.1 下载地址: http://ant.apache.org/ 1.2 环境变量配置: 把解压缩后的文件夹中/bin的全路径添加到PATH中 2  命令行下创建Android新工程 即:   android create project -k com.ant.test -n antTest -a AntTestActivity -t 7 -p /Users/lincoln/Desktop/antTest 详解: android create pro

[自动运维]ant脚本打包,上传文件到指定服务器,并部署

1.根节点使用,表示根目录为当前目录,默认启动的target为build,项目名称为othersysm, <project basedir="." default="build" name="othersysm"> </project> 2.每一个target为一个执行命令,如果有依赖关系,则写为: <target depends="build-project" name="build&

Android ANT多渠道打包

在没用AndroidStudio的Gradle构建项目之前,多渠道打包一般都是基于ANT构建,所以在此记录一下,以供查阅! 一.文件准备 1.首先要去官网下载ANT代码. ANT官网下载地址 2.下载ANT循环打包JAR包. ANT循环JAR包下载地址 网盘下载地址 3.解压得到其中的ant-contrib-1.0b3.jar文件待用. 做完以上3步,ANT多渠道打包所需要的软件就准备完毕了,接下来就是环境配置了. 二.环境配置 1.先将之前下载的ANT文件解压缩到任意文件路径,如D:\Ant目

Android Ant批量打包

一.配置Ant环境变量 JAVA_HOME=/software/jdk1.6.0_24 ANT_HOME=/software/apache-ant-1.9.2 Android_Home=/software/android-sdk-linux export JAVA_HOME ANT_HOME Android_Home PATH=$JAVA_HOME/bin:$ANT_HOME/bin:$ANDROID_HOME/tools$Android_Home/tools/proguard/bin:$/so

【转载】将python脚本打包成exe文件

exe文件也就是可以直接执行的文件.通常我们编好的带py后缀的脚本文件都是需要在有python的环境下执行, 每次通过Win + R打开运行窗口再输入powershell打开控制台,再千辛万苦地cd c:\python27 (change directory) 转换目录到py文件的目录下.最终还是要用python 1.py之类的方法打开脚本.为了让没有安装python的人也能用 我们编好的脚本.我们就要用到PyInstaller这个东东来编译成exe可执行文件. 参考: http://www.c

gradle打包android (实现外部导入签名文件、多渠道打包、导入ant脚本)

近期一直在做android自己主动打包,之前已经完毕了用纯命令行的形式打包.原生态ant脚本打包.和基于android的SDK的打包.而且实现了多渠道打包,后来同事推荐了gradle,网上的资料说gradle各种好,自己也感兴趣是实现一下.事实上一般来说因为android对eclipse的支持减弱,大部分的人都是用gradle与android studio融合,这样面的样例也会比較多,但笔者所在的项目还是在eclipse的比較多.因为开发者在移植过程中发现报错比較多所以一直没有全然移植(好吧,事

关于项目既要使用ant脚本又要使用maven pom.xml文件的问题

背景:项目使用的是ant脚本打包,但又需要maven去执行sonar代码扫描.所以项目中既有build.xml又有pom.xml build.xml设置的打包后产物文件夹为target,maven运行后也会默认生成target文件夹,这样就会存在覆盖的问题, 因为maven打包默认生成target文件夹, 所以只能修改ant打包存放产物的文件夹,不和maven文件夹重名.

ANT自动打包U3D安卓项目研究笔记

概述 因项目使用Atlassian Stash作为项目源码管理端,且其支持Ant命令自动编译,可使其根据最新的代码自动打包,故产生该研究Ant打包的任务.在此将研究过程及一些相关知识整理记录在此. 本文部分内容可以说就是Android和Ant自动打包的配置,只是在其基础上扩充了Unity3D的部分. 阅读本文需要:知道Android开发环境大概需要哪些东西,知道Unity3D编辑器的基本使用方法. 本文并不是系统学习Ant以及Android自动打包的文章,只是笔者通过网络搜索一系列文章,然后通过