How can I go about creating an obfuscate jar file? As of now I can easily export my Android lib project to a jar and use it. How do I obfuscate the jar file?
My end goa
figuring this out was not easy, but once done, repeating the steps is not that hard:
proguard.cfg example
# optimization passes will allow multiple tries to strip dead code
# if it doesn't find anything on the 2nd pass, it won't do a 3rd.
-optimizationpasses 5
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
# it would complain about my missing R stuff, and it does the right thing with this line
-dontwarn com.mycompany.myproject.R*
# the location of the pre-obfuscated .jar built by your project
-injars bin/myproject.jar
-verbose
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
# this will fake "dead-strip" calls to Log.v() & Log.d()
-assumenosideeffects class android.util.Log {
public static int v(...);
public static int d(...);
}
# this will fake "dead-strip" calls to a more complex logging function i created
-assumenosideeffects class com.mycompany.myproject.FirstPackageWithLogging {
private void LogR(...);
}
# this will fake "dead-strip" a function in which i check to see if the
# USB-cable is connected and perform waitForDebugger(), since i don't want
# those making use of my obfuscated library to have to wait for the debgger
# when they won't be debugging my library
-assumenosideeffects class com.mycompany.myproject.MyProject {
private void setupDebugging();
}
# this will fake "dead-strip" a toast i use to measure focus
-assumenosideeffects class com.mycompany.myproject.UXObserver {
private void toastFocus();
}
# i don't want to obfuscate 3rd-party stuff, in case someone else
# is using the same classes, and wants to just get mine via pass-through
-keep class org.thirdparty.package.**
-keep class com.licensedpackage.**
# i want my API to be public, so i expose it
-keep public class com.mycompany.myproject.MyAPI
# almost all the rest are the suggestion of the proguard examples page
-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 com.mycompany.myproject.MyAPI {
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 *;
}
…
$ java -jar $ANDROID_SDK/tools/proguard/lib/proguard.jar
-libraryjars $ANDROID_SDK/platforms/android-18/android.jar @proguard.cfg
-outjars ../MyReleaseSDK/libs/myproject.jar
that's it. the output will contain your obfuscated .jar file.
from that point, i copy over a few items from my project (.project file minus external tools builder for NDK; res folder, libs folder for my jni code, and project.properties and AndroidManifest.xml) into MyReleaseSDK, then create a .zip out of it. that .zip can then be used by someone else as an Eclipse "import" project; it will create an empty src folder, gen the resources properly, and anyone who wants to can now use it as a regular Android library project despite it being obfuscated.
To create an obfuscated jar file you can do that by adding build.xml file to it and making changes in your proguard-project.txt file and running ant release from command line and you will find the obfuscated.jar under a proguard folder in your bin folder of project
Steps
To add build.xml in your project in linux:
open a terminal and go to android/tools/ant folder and run
./android update project -p /path_of_your_android_library_project
and you will find build.xml in your project root directory.
to enable obfuscation in your project:
In your editor open a project.properties file and remove comment from
proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
add your changes to proguard-project.txt file and in terminal go to your project and run
ant release
Turns out it is possible and it's not that hard. After 3hrs of trying I finally figured it out!
Android provides a convenient proguard GUI under:
android-sdk\tools\proguard
Using the GUI you just select the in.jar and the out.jar. Than you must select the android.jar and remove the selected default rt.jar.
Once that's done you must carefully select the Shrinking and Obfuscation options.
I hope in some way or another this helps!
If it is an external jar, then if you have it in "libs" folder and compile with say Android 2.2+ SDK, it automatically uses proguard to obfuscate the apk. If you want this jar as a library and also obfuscate it before using it in your apk, then it may not be possible. If you are talking of apk obfuscation than Android does this from 2.2 on I think (with proguard), and you dont have to worry about it.
you to enable proguard for your project - its very easy. http://developer.android.com/guide/developing/tools/proguard.html
one common error that can occur is that methods aren't found when using reflection. This is because the obfuscation removes method names and sometimes even whole classes. If you have custom views the same thing can happen.
You configure what classes to keep by using the "-keep" flag in proguard.cfg
here are some common ones this is from a maven build - but the concept is the same
-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.view.View {
public <init>(android.content.Context);
public <init>(android.content.Context, android.util.AttributeSet);
public <init>(android.content.Context, android.util.AttributeSet, int);
public void set*(...);
-keepclasseswithmembers class * {
public <init> (android.content.Context, android.util.AttributeSet); }
-keepclasseswithmembers class * {
public <init> (android.content.Context, android.util.AttributeSet, int); }
-keepclassmembers class * implements android.os.Parcelable {
static android.os.Parcelable$Creator *; }
-keepclassmembers class **.R$* { public static <fields>; }
-keepclasseswithmembernames class * { native <methods>; }
-keepclassmembers class * extends java.lang.Enum {
public static **[] values();
public static ** valueOf(java.lang.String); }
-keepclassmembers class * extends android.app.Activity{
public void *(android.view.View); }
quite a big area, but hope it helps ...