Question

Can anyone share with sample/simple obfuscation ANT task for Android? Provided that I do have complete APK and I need just pass *class hru Proguard and then prepare *.dex to build APK

Was it helpful?

Solution

I have found solution:

  1. Get Proguard - copy proguard.jar into known directory (say MyProject/proguard)
  2. Prepare proguard.cfg -describing what and how optimize/obfuscate. This process thoroughly described in Proguard's manual
  3. Prepare following ANT's build.xml (or smth like this one) - great thanx to this guy

UPDATE complete build.xml

<?xml version="1.0" encoding="UTF-8"?> 
<project name="MyProject" default="zipalign" basedir=".">
    <property name="target" value="android-8"/>
    <!--property file="default.properties" /-->
    <property name="encoding" value="UTF-8"/>

    <!-- dirs -->
    <property name="sdk.dir" location="Location of Android SDK"/>
    <property name="proguard.dir" value="proguard" />
    <property name="src.dir" value="src"/>
    <property name="gen.dir" value="gen"/>
    <property name="res.dir" value="res"/>
    <property name="assets.dir" value="assets"/>
    <property name="libs.dir" value="libs"/>
    <property name="out.classes.unoptimized.dir" value="out"/>
    <property name="out.classes.optimized.dir" value="out/optimized"/>

    <!-- files -->
    <property name="manifest.file" value="AndroidManifest.xml"/>
    <property name="signed.apk" value="${ant.project.name}-signed.apk"/>
    <property name="unsigned.apk" value="${ant.project.name}-unsigned.apk"/>
    <property name="final.apk" value="${ant.project.name}.apk"/>
    <property name="android.jar" value="${sdk.dir}/tools/platforms/${target}/android.jar"/>
    <property name="unoptimized" value="unoptimized.jar" />
    <property name="optimized" value="optimized.jar" />
    <property name="proguard.config" value="${proguard.dir}/proguard.cfg"/>

    <!-- tools -->
    <property name="dx.jar" value="${sdk.dir}/platform-tools/lib/dx.jar"/>
    <property name="aapt" value="${sdk.dir}/platforms/${target}/tools/aapt.exe"/>
    <property name="zipalign" value="${sdk.dir}/tools/zipalign.exe"/>
    <property name="jarsign" value="jarsigner.exe location is here"/>
    <property name="keystore" value="Your key store is here"/>
    <property name="keyalias" value="Your key alias is here"/>


    <path id="android.antlibs">
        <pathelement path="${sdk.dir}/tools/lib/anttasks.jar" />
        <pathelement path="${sdk.dir}/tools/lib/sdklib.jar" />
        <pathelement path="${sdk.dir}/tools/lib/androidprefs.jar" />
        <pathelement path="${sdk.dir}/tools/lib/apkbuilder.jar" />
        <pathelement path="${sdk.dir}/tools/lib/jarutils.jar" />
    </path>

    <taskdef name="setup"
        classname="com.android.ant.SetupTask"
        classpathref="android.antlibs" />
    <setup import="false"/>

    <!--taskdef name="aaptexec"
            classname="com.android.ant.AaptExecLoopTask"
            classpathref="android.antlibs" /-->

    <target name="clean" description="Removes output files created by other targets.">
        <echo>Cleaning...</echo>
        <delete dir="${out.classes.unoptimized.dir}" verbose="true" />
        <delete dir="${out.classes.optimized.dir}" verbose="true" />
    </target>

    <target name="dirs">
        <echo>Creating output directories if needed...</echo>
        <mkdir dir="${out.classes.unoptimized.dir}" />
        <mkdir dir="${out.classes.optimized.dir}" />
    </target>

    <!-- Compiles this project's .java files into .class files. -->
    <target name="compile" depends="dirs"
            description="Compiles project's .java files into .class files">
        <echo>Compiling sources...</echo>
        <javac encoding="${encoding}" target="1.6" debug="true" extdirs=""
                destdir="${out.classes.unoptimized.dir}"
                bootclasspathref="android.target.classpath"
                includeantruntime="true">
            <src path="${src.dir}" />
            <src path="${gen.dir}" />
            <classpath>
                <fileset dir="${libs.dir}" includes="*.jar" />
            </classpath>
        </javac>
    </target>

    <target name="preobfuscate" depends="compile">
        <echo>Preparing to obfuscation...</echo>
    <jar destfile="${unoptimized}"
       basedir="${out.classes.unoptimized.dir}"
       includes="**/**"
       excludes="optimized/**"
       />
    </target>

    <!--  Obfuscation with ProGuard   -->
    <target name="optimize" unless="nooptimize" depends="preobfuscate">
        <echo>Proguard obfuscation...</echo>
        <java jar="${proguard.dir}/proguard.jar" fork="true" failonerror="true">
            <jvmarg value="-Dmaximum.inlined.code.length=16" />
            <arg value="@${proguard.dir}/proguard.cfg" />
            <arg value="-injars ${unoptimized}" />
            <arg value="-outjars ${optimized}" />
            <arg value="-libraryjars ${android.jar}" />
        </java>
        <unzip src="${optimized}" dest="${out.classes.optimized.dir}" />
        <!-- Delete optimized jar (now unzipped into bin directory)  -->
        <delete file="${optimized}"/>
        <delete file="${unoptimized}"/>
    </target>

    <target name="dex" description="Converting JVM bytecodes into Dalvik bytecodes" depends="optimize">
        <echo>Converting bytecodes to Dalvik VM bytecodes...</echo>
        <java jar="${dx.jar}" fork="true">
            <arg line="--dex --verbose --output=${out.classes.optimized.dir}/classes.dex ${out.classes.optimized.dir}"/>
        </java>
    </target>

    <target name="aapt" depends="dex" description="compile resources">
        <echo>Packing resources...</echo>
        <exec executable="${aapt}" logerror="true" osfamily="windows">
            <arg line="p
            -f
            -M ${manifest.file}
            -I ${android.jar}
            -S ${res.dir}
            -A ${assets.dir}
            -F ${out.classes.optimized.dir}/${unsigned.apk}
            -m -J ${gen.dir}"/>
        </exec>
    </target>

    <target name="sign" depends="aapt" description="sign apk">
        <input message="Please enter keystore password (store:${keystore}):"
                       addproperty="keystore.password" />
        <echo>Signing apk...</echo>
        <exec executable="${jarsign}" logerror="true" osfamily="windows">
            <arg line="-verbose
            -keystore ${keystore}
            -storepass ${keystore.password}
            -signedjar ${out.classes.optimized.dir}/${signed.apk}
            ${out.classes.optimized.dir}/${unsigned.apk} ${keyalias}"/>
        </exec>
    </target>

    <target name="zipalign" depends="sign" description="zip align">
        <echo>Aligning apk...</echo>
        <exec executable="${zipalign}" logerror="true" osfamily="windows">
            <arg line="-f
            -v
            4
            ${out.classes.optimized.dir}/${signed.apk}
            ${final.apk}"/>
        </exec>
    </target>

</project>
  1. This ANT task has to be added to Eclipse's builders (Properties/Builders) tasks after Java builder and before Android package builder.

  2. Press "Build All" (it's better to off Automatic Build check in Eclipse menu)

OTHER TIPS

The Android build process first compiles Java source files (.java) to Java class files (.class), then converts these class files into Dalvik code (classes.dex), and finally packages this Dalvik code in an APK file.

ProGuard reads and writes Java class files, so it has to be inserted into this pipeline between the compilation step and the conversion step. It doesn't read or write Dalvik code itself, so it can't work on the APK file.

The Android SDK documentation on ProGuard discusses how to enable the obfuscation step in the Ant build for android-9. In short, you have to add a line "proguard.config=proguard.cfg" to the file default.properties, and then run "ant release".

Attention: barmaley's reply is from year 2011, and seem to be valid for Android SDK Tools version either 8 or 10.

I tried adapting this solution using Android SDK Tools version 18.1.1, but kept failing on the error:
taskdef class com.android.ant.SetupTask cannot be found

Eventually, what I did was this:

rm build.xml
android update project -p .
  • If you don't have the SDK Tools in your PATH, you'll need to use the full path to the android tool, for example on Windows: C:\Android\sdk\tools

This created a fresh build.xml which is compliant with the current SDK Tools, and seem to automate a lot of the manual work that is described in barmaley's reply.

After that I was able to run ant release, which took care of building and obfuscating the result .apk file out of the box.

In order to automate obfuscation via ant, you'll need to:

  1. Enable Proguard obfuscator (obviously)
  2. Create an ant.properties file and fill it with the appropriate key.store params (see this SO reply for details).

The proGuard obfuscation process needs .class files so you can't launch an Ant before IDE build (.java) or after (.dex packed).

Have a look on this post where it's explained how add the proGuard step in your global Ant build:

http://www.androidengineer.com/2010/07/optimizing-obfuscating-and-shrinking.html

If you really want to use the IDEA build, you can try the following.

  • After the IDEA build unpack the apk with apktool.
  • Convert the .dex files to .class with dex2jar
  • Run proGuard as the previous post show you

Sorry that I don't attach you the links of apktool and dexjar but as I'm newbie I can't post more than one hyperlink.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top