【发布时间】:2011-05-23 20:31:46
【问题描述】:
如何创建混淆 jar 文件?到目前为止,我可以轻松地将我的 Android lib 项目导出到 jar 中并使用它。如何混淆 jar 文件?
我的最终目标是允许其他人在他们的项目中使用我的 lib.jar。我只是想尽可能地保护代码...... :)
【问题讨论】:
标签: android obfuscation proguard
如何创建混淆 jar 文件?到目前为止,我可以轻松地将我的 Android lib 项目导出到 jar 中并使用它。如何混淆 jar 文件?
我的最终目标是允许其他人在他们的项目中使用我的 lib.jar。我只是想尽可能地保护代码...... :)
【问题讨论】:
标签: android obfuscation proguard
事实证明这是可能的,而且并不难。经过3小时的尝试,我终于弄明白了!
Android 下提供了一个方便的 proguard GUI:
android-sdk\tools\proguard
使用 GUI,您只需选择 in.jar 和 out.jar。比您必须选择 android.jar 并删除选定的默认 rt.jar。
完成后,您必须仔细选择 Shrinking 和 Obfuscation 选项。
我希望这会有所帮助!
【讨论】:
弄清楚这一点并不容易,但一旦完成,重复这些步骤并不难:
proguard.cfg 示例
# 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
就是这样。输出将包含您的混淆 .jar 文件。
从那时起,我将项目中的一些项目(.project 文件减去 NDK 的外部工具生成器;res 文件夹、我的 jni 代码的 libs 文件夹以及 project.properties 和 AndroidManifest.xml)复制到 MyReleaseSDK,然后从中创建一个 .zip。然后其他人可以将 .zip 用作 Eclipse“导入”项目;它将创建一个空的 src 文件夹,正确生成资源,并且任何想要的人现在都可以将它用作常规的 Android 库项目,尽管它被混淆了。
【讨论】:
如果它是一个外部 jar,那么如果你将它放在“libs”文件夹中并使用 Android 2.2+ SDK 进行编译,它会自动使用 proguard 来混淆 apk。如果您希望将此 jar 作为库并在将其用于您的 apk 之前对其进行混淆,那么这可能是不可能的。如果您谈论的是 apk 混淆,我认为(使用 proguard)从 2.2 开始,Android 会这样做,您不必担心。
【讨论】:
您可以为您的项目启用 proguard - 这非常简单。 http://developer.android.com/guide/developing/tools/proguard.html
可能发生的一个常见错误是使用反射时找不到方法。这是因为混淆删除了方法名称,有时甚至删除了整个类。如果您有自定义视图,可能会发生同样的事情。
您可以使用 proguard.cfg 中的“-keep”标志来配置要保留的类
这里有一些常见的,来自 maven 构建 - 但概念是相同的
-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); }
相当大的区域,但希望它有所帮助......
【讨论】:
要创建一个混淆的 jar 文件,您可以通过向其中添加 build.xml 文件并在您的 proguard-project.txt 文件中进行更改并从命令行运行 ant release 来创建混淆的 jar 文件,您将在 proguard 下找到 obfuscated.jar项目的 bin 文件夹中的文件夹
步骤
在 linux 的项目中添加 build.xml:
打开终端并进入 android/tools/ant 文件夹并运行
./android update project -p /path_of_your_android_library_project
您会在项目根目录中找到 build.xml。
在您的项目中启用混淆:
在您的编辑器中打开一个 project.properties 文件并从中删除注释
proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
将您的更改添加到 proguard-project.txt 文件并在终端中转到您的项目并运行
ant release
【讨论】: