19

I have seen many posts about how to obfuscate an Android application (.apk file) using ProGuard in Eclipse. Also see http://developer.android.com/guide/developing/tools/proguard.html:

"When you build your application in release mode, either by running ant release or by using the Export Wizard in Eclipse, the build system automatically checks to see if the proguard.config property is set. If it is, ProGuard automatically processes the application's bytecode before packaging everything into an .apk file."

But in case of exporting an Android project in a .jar file using Eclipse Export Wizard, following the described steps (of creating a file proguard.cfg, configuring proguard.config property to proguard.cfg in the file default.properties, using Export Wizard etc.) does not seem to work - I see no obfuscation of class names, etc. in the resulting jar file. I also have the following settings in my proguard.cfg file, but I don't see any output files in my project directory or in the proguard directory (that directory is not even created).

-dump class_files.txt 
-printseeds seeds.txt 
-printusage unused.txt 
-printmapping mapping.txt

I have even created a file project.properties in my project directory with the following line but that did not seem to entice ProGuard into action:

proguard.config=proguard.cfg

There are no activities defined in this project. I am using Android 2.3.1 and Eclipse Galileo 3.5.2 on Windows. Same results with Android 3.0. Seems like the obfuscation step has to be somehow interjected explicitly in the Eclipse Export Wizard. I will appreciate any help or insight. Thanks.

Damodar Periwal
  • 399
  • 1
  • 2
  • 13

5 Answers5

18

as suggested in the comments to one of the answers above (but which i didn't notice at first because it was buried amongst one of the "additional comments") …

we simply run progruard on the command line (see the first block below) on the library outside of eclipse with the parameters in the second block below in our our proguard.cfg file (and definitely do not use -dontpreverify, or projects that use your project as an android library won't be able to properly be obfuscated due to StackMapTable problems from your project.jar).

command line:

$ java -jar $ANDROID_SDK/tools/proguard/lib/proguard.jar \
  -libraryjars $ANDROID_SDK/platforms/android-18/android.jar @proguard.cfg
  -outjars /tmp/project.jar -verbose

proguard.cfg:

-optimizationpasses 5
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-dontwarn our.company.project.R*
-injars bin/project.jar
-verbose
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*

-keep class org.apache.3rdparty.stuff.**
-keep public class our.company.project.ProjectAPI
-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

-keepclassmembers public class our.company.project.ProjectAPI {
    public static <fields>;
}

-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);
}

-keep class * implements android.os.Parcelable {
    public static final android.os.Parcelable$Creator *;
}

it's possible not all of the parameters and -keep items are strictly necessary (other than not using -dontpreverify as previously mentioned), but most of these make sense to me as items that need to be there if you have an Activity class extension in the library you are exporting.

Guillaume Barré
  • 4,168
  • 2
  • 27
  • 50
john.k.doe
  • 7,533
  • 2
  • 37
  • 64
11

I use an indirect way to generate a exported android obfuscate jar, my way is:

  1. export a signed apk use eclipse

  2. unzip the apk, find the classes.dex

  3. use dex2jar.bat ,change the classes.dex to a jar

  4. unzip the jar and delete the class you do not need,then zip it and change the file name to XXX.jar

  5. Then you use this jar in other project,or give it to customer, it is obfuscate!

I am sure this will help you! Enjoy it!

Ken
  • 30,811
  • 34
  • 116
  • 155
Xitao
  • 121
  • 1
  • 4
  • After these steps, I cant use this jar like old jar. Old import > com.abc.123 Auto fix new Import > XXX.com.abc.123 So my obfustcate classes cant find each others... Any Idea? – atasoyh Sep 05 '13 at 12:59
  • Zip the com folder, not the container one – Zorb Dec 03 '14 at 17:02
  • same here my classes can't find each other,i.e name of the classes got chnaged – abh22ishek Dec 03 '15 at 13:38
7
java -jar proguard.jar @yourconfig.pro

yourconfig.pro (extended from http://proguard.sourceforge.net/index.html#manual/examples.html):

-injars yourjar.jar
-outjars yourjar_out.jar

-libraryjars 'C:\android\sdk\platforms\android-10\android.jar'

-printmapping mapping.txt
-verbose
-dontoptimize
-dontpreverify
-dontshrink
-dontskipnonpubliclibraryclassmembers
-dontusemixedcaseclassnames
-keepparameternames
-renamesourcefileattribute SourceFile
-keepattributes Exceptions,InnerClasses,Signature,Deprecated,
                SourceFile,LineNumberTable,*Annotation*,EnclosingMethod

-keep public class * {
    public protected *;
}

-keepclassmembernames class * {
    java.lang.Class class$(java.lang.String);
    java.lang.Class class$(java.lang.String, boolean);
}

-keepclasseswithmembernames class * {
    native <methods>;
}

-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}

-keepclassmembers class * implements java.io.Serializable {
    static final long serialVersionUID;
    private static final java.io.ObjectStreamField[] serialPersistentFields;
    private void writeObject(java.io.ObjectOutputStream);
    private void readObject(java.io.ObjectInputStream);
    java.lang.Object writeReplace();
    java.lang.Object readResolve();
}

Result can be verified with jd-gui

pulp
  • 698
  • 1
  • 6
  • 13
  • Thanks! On Mac: in addition to tweaking the -libraryjars path for the script above I also needed to softlink rt.jar -> classes.jar following the instructions here: http://bruehlicke.blogspot.com/2009/11/missing-rtjar-mac-os-x-using-proguard.html – AbePralle Aug 13 '14 at 19:06
2

The way to invoke ProGuard is fairly straightforward:

  1. Add the line proguard.config=proguard.cfg to project.properties
  2. Export the application package

A default proguard.cfg file should have been automatically created by the new project wizard.

Ted Hopp
  • 232,168
  • 48
  • 399
  • 521
  • @user1040716 - you mention creating proguard.cfg. That should have been created for you automatically when you set up the project. If it isn't there, perhaps the project is not configured properly. Try with a brand new Android project. This should work out of the box (once you add the line to project.properties). Make sure your SDK tools are up to date. – Ted Hopp Nov 11 '11 at 04:01
  • I just now created a brand new project under Android 3.0. Copied src files from the old project. proguard.cfg file was automatically generated but project.properties was not auto-generated. So first I added the line 'proguard.config=proguard.cfg' in default.properties. Did the export of Java JAR file. No obfuscation noticed. Then I created a local file project.properties and added the line. Then did the export of Java JAR file. Again, no obfuscation noticed. If I 'Export Android Application' then it creates an .apk file. But I want an obfuscated .jar file. Thanks. – Damodar Periwal Nov 11 '11 at 05:20
  • The idea is for this .jar file with obfuscated code to be used in other Android projects using 'Add External Jars...' option under Java Build Path/Libraries. – Damodar Periwal Nov 11 '11 at 05:28
  • 2
    I think you'll have to run ProGuard outside of Eclipse for this (or at least outside the Android build process). The Android build process only invokes ProGuard when exporting .apk files. – Ted Hopp Nov 11 '11 at 16:48
  • I have ended up running ProGuard outside Eclipse as suggested by Ted. Thanks. – Damodar Periwal Jan 20 '12 at 02:34
  • That worked for me. I edited project.properties and added: proguard.config=proguard.cfg even though the file says not to modify it! THEN the proguard folder was created in my project root. – Yar Feb 16 '12 at 18:43
  • after read I don't know so many post, finally I solved thanks to this response. I was trying all good options but my file wasn't never read. – Lisitso May 06 '13 at 22:28
2

Do not obfuscated your pure Java Jar. Skip that phase completely while producing the Jar (whether manually in Eclipse or via Ant build from command line).

Instead, setup and perform proper obfuscation in the client project, the one using the Jar, where you add the library as external Jar. Proguard will be able to obfuscate code within the Jar too.

I stumbled upon this issue, and ended up successfully as I described here.

superjos
  • 12,189
  • 6
  • 89
  • 134
  • 4
    Well, I would like to distribute the library (.jar file) with obfuscated code; others will use my library in their client projects. So I need to obfuscate my pure Java Jar before distributing. I have ended up running ProGuard outside Eclipse as suggested by Ted Hopp. – Damodar Periwal Jan 20 '12 at 02:33
  • a-ha. Sorry, my head must have skipped that! – superjos Jan 20 '12 at 11:12
  • @the down-voter: could you please elaborate on what's wrong with the proposed solution. Tnx – superjos Mar 27 '13 at 17:42