Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android obfuscate app using proguard keeps obfuscating library jars - or is it?

Tags:

I'm new to using Proguard so I'm probably making a newbie mistake. I've got an app that after I run the release build (which uses Proguard to obfuscate) it crashes pretty quickly. I believe I've narrowed it down to the fact that it seems like it is obfuscating my reference libraries. In my case my reference libraries are used to define my message classes that I am using to communicate to another device using Google Protobuffers. I am building using, ant release. My proguard config is:

-optimizationpasses 5 -dontusemixedcaseclassnames -dontskipnonpubliclibraryclasses -dontpreverify -verbose -optimizations !code/simplification/arithmetic,!field/*,!class/merging/*  -keep public class * extends android.app.Activity -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 com.android.vending.licensing.ILicensingService  -keepclasseswithmembernames class *   {     native <methods>;  }  -keepclasseswithmembernames class *   {     public <init>(android.content.Context, android.util.AttributeSet);  }  -keepclasseswithmembernames class *   {     public <init>(android.content.Context, android.util.AttributeSet, int);  }  -keepclassmembers enum *   {     public static **[] values();     public static ** valueOf(java.lang.String);  }  -keep class * implements android.os.Parcelable   {     public static final android.os.Parcelable$Creator *;  } 

In my ant build.xml file I have the following defined:

<target name="-obfuscate" unless="do.not.compile">     <if condition="${proguard.enabled}">         <then>             <property name="obfuscate.absolute.dir" location="${out.absolute.dir}/proguard" />             <property name="preobfuscate.jar.file"  value="${obfuscate.absolute.dir}/original.jar" />             <property name="obfuscated.jar.file"    value="${obfuscate.absolute.dir}/obfuscated.jar" />               <!-- input for dex will be proguard's output -->             <property name="out.dex.input.absolute.dir" value="${obfuscated.jar.file}" />              <!-- Add Proguard Tasks -->             <property name="proguard.jar" location="${android.tools.dir}/proguard/lib/proguard.jar" />             <taskdef name="proguard" classname="proguard.ant.ProGuardTask" classpath="${proguard.jar}" />              <!-- Set the android classpath Path object into a single property. It'll be                  all the jar files separated by a platform path-separator.             -->             <property name="android.libraryjars" refid="android.target.classpath"/>              <!-- Build a path object with all the jar files that must be obfuscated.                  This include the project compiled source code and any 3rd party jar                  files.              -->             <path id="project.jars.ref">                 <pathelement location="${preobfuscate.jar.file}" />                 <path refid="jar.libs.ref" />             </path>              <!-- Set the project jar files Path object into a single property. It'll be                  all the jar files separated by a platform path-separator.             -->             <property name="project.jars" refid="project.jars.ref" />              <mkdir  dir="${obfuscate.absolute.dir}" />             <delete file="${preobfuscate.jar.file}" />             <delete file="${obfuscated.jar.file}"   />             <jar basedir="${out.classes.dir}" destfile="${preobfuscate.jar.file}" />             <proguard>                 @${proguard.config}                 -injars ${project.jars}                 -outjars ${obfuscated.jar.file}                 -libraryjars ${android.libraryjars}                 -dump ${obfuscate.absolute.dir}/dump.txt                 -printseeds ${obfuscate.absolute.dir}/seeds.txt                 -printusage ${obfuscate.absolute.dir}/usage.txt                 -printmapping ${obfuscate.absolute.dir}/mapping.txt             </proguard>         </then>     </if> </target>  <!-- Converts this project's .class files into .dex files --> <target name="-dex" depends="compile, -post-compile, -obfuscate"         unless="do.not.compile">     <if condition="${manifest.hasCode}">         <then>             <dex-helper />         </then>         <else>             <echo>hasCode = false. Skipping...</echo>         </else>     </if> </target>  <!-- Puts the project's resources into the output package file      This actually can create multiple resource package in case      Some custom apk with specific configuration have been      declared in default.properties.      --> <target name="-package-resources">     <echo>Packaging resources</echo>     <aapt executable="${aapt}"             command="package"             versioncode="${version.code}"             debug="${build.packaging.debug}"             manifest="AndroidManifest.xml"             assets="${asset.absolute.dir}"             androidjar="${android.jar}"             apkfolder="${out.absolute.dir}"             resourcefilename="${resource.package.file.name}"             resourcefilter="${aapt.resource.filter}">         <res path="${resource.absolute.dir}" />         <!-- <nocompress /> forces no compression on any files in assets or res/raw -->         <!-- <nocompress extension="xml" /> forces no compression on specific file extensions in assets and res/raw -->     </aapt> </target>  <!-- Packages the application and sign it with a debug key. --> <target name="-package-debug-sign" depends="-dex, -package-resources">     <package-helper             output.filepath="${out.debug.unaligned.file}" /> </target>  <!-- Packages the application without signing it. --> <target name="-package-release" depends="-dex, -package-resources">     <package-helper             output.filepath="${out.unsigned.file}"/> </target>     <target name="-set-release-mode">         <!-- release mode is only valid if the manifest does not explicitly              set debuggable to true. default is false.              We actually store build.packaging.debug, not build.release -->         <xpath input="AndroidManifest.xml" expression="/manifest/application/@android:debuggable"                output="build.packaging.debug" default="false"/>          <!-- Enable proguard -->         <property name="proguard.enabled" value="true"/>         <property name="proguard.config" value="proguard.cfg"/>          <!-- signing mode: release -->         <property name="build.signing.debug" value="false" />          <if condition="${build.packaging.debug}">             <then>                 <echo>*************************************************</echo>                 <echo>****  Android Manifest has debuggable=true   ****</echo>                 <echo>**** Doing DEBUG packaging with RELEASE keys ****</echo>                 <echo>*************************************************</echo>             </then>             <else>                 <!-- property only set in release mode.                      Useful for if/unless attributes in target node                      when using Ant before 1.8 -->                 <property name="build.mode.release" value="true"/>             </else>         </if>     </target>      <target name="release"             depends="-set-release-mode, -release-obfuscation-check, -package-release, -release-prompt-for-password, -release-nosign"                 if="has.keystore"                 description="Builds the application. The generated apk file must be signed before                             it is published.">         <!-- Signs the APK -->         <echo>Signing final apk...</echo>         <signjar                 jar="${out.unsigned.file}"                 signedjar="${out.unaligned.file}"                 keystore="${key.store}"                 storepass="${key.store.password}"                 alias="${key.alias}"                 keypass="${key.alias.password}"                 verbose="${verbose}" />          <!-- Zip aligns the APK -->         <zipalign-helper in.package="${out.unaligned.file}"                                    out.package="${out.release.file}" />         <echo>Release Package: ${out.release.file}</echo>     </target> 

I'd appreciate any ideas. I copied in most of my build and proguard config from online templates, I suspect that I am actually intructing Proguard to obfuscate the library jars or I have something lisconfigured. I am seeing the following output in my cmd window at the end of the build:

[proguard] Writing output... [proguard] Preparing output jar [C:\Workspace\UI\MyApp\build\proguard\obfuscated.jar] [proguard]   Copying resources from program jar [C:\Workspace\UI\MyApp\build\proguard\original.jar] [proguard]   Copying resources from program jar [C:\Workspace\UI\MyApp\libs\libmessaging.jar] [proguard] Warning: can't write resource [META-INF/MANIFEST.MF] (Duplicate zip entry [libmessaging.jar:META-INF/MANIFEST.MF]) [proguard]   Copying resources from program jar [C:\Workspace\UI\MyApp\libs\protobuf-2.3.0.jar] [proguard] Warning: can't write resource [META-INF/MANIFEST.MF] (Duplicate zip entry [protobuf-2.3.0.jar:META-INF/MANIFEST.MF]) [proguard] Printing classes to [C:\Workspace\Riptide1_1_ptr_74\WPG_HAWKSBILL\UI\MyApp\build\proguard\dump.txt]... 

Thanks!

like image 731
bursk Avatar asked Jul 01 '11 00:07

bursk


People also ask

How does ProGuard obfuscation work?

In the obfuscation step, ProGuard renames classes and class members that are not entry points. In this entire process, keeping the entry points ensures that they can still be accessed by their original names. The preverification step is the only step that doesn't have to know the entry points.

How do I obfuscate my library on Android?

In order to obfuscate your library what you need to do is: Make sure gradle settings for lib module state minifyEnabled true . run ./gradlew assemble{flavor}Release.

Does ProGuard obfuscate package name?

Obfuscating package names myapplication. MyMain is the main application class that is kept by the configuration. All other class names can be obfuscated. Note that not all levels of obfuscation of package names may be acceptable for all code.


1 Answers

You have commented your library jar directives in the Proguard config.
Change:

# -libraryjars /libs/protobuf-2.3.0.jar # -libraryjars /libs/libmessaging.jar 

to:

-libraryjars /libs/protobuf-2.3.0.jar -libraryjars /libs/libmessaging.jar 

(and then don't bother defining your library jars in your build.xml)

EDIT:
I found another way to make Proguard leave library jars alone was to ask it to preserve their package names, eg:

-keep class javax.** { *; } -keep class org.** { *; } -keep class twitter4j.** { *; } 
like image 199
Caspar Harmer Avatar answered Oct 02 '22 18:10

Caspar Harmer