如何在 Eclipse 中使用 Proguard 混淆 Android 库(.jar 文件)
Posted
技术标签:
【中文标题】如何在 Eclipse 中使用 Proguard 混淆 Android 库(.jar 文件)【英文标题】:How to obfuscate an Android library (.jar file) using Proguard in Eclipse 【发布时间】:2011-12-26 16:48:14 【问题描述】:我看过很多关于如何在 Eclipse 中使用 ProGuard 混淆 android 应用程序(.apk 文件)的帖子。另见http://developer.android.com/guide/developing/tools/proguard.html:
“当您在发布模式下构建应用程序(通过运行 ant release 或使用 Eclipse 中的导出向导)时,构建系统会自动检查是否设置了 proguard.config 属性。如果是,ProGuard 会在将所有内容打包成.apk 文件之前自动处理应用程序的字节码。”
但如果使用 Eclipse 导出向导将 Android 项目导出为 .jar 文件,请按照所述步骤(创建文件 proguard.cfg,在文件 default.properties 中将 proguard.config 属性配置为 proguard.cfg,使用导出向导等)似乎不起作用 - 我在生成的 jar 文件中没有看到类名等的混淆。我的 proguard.cfg 文件中也有以下设置,但在我的项目目录或 proguard 目录中看不到任何输出文件(甚至没有创建该目录)。
-dump class_files.txt
-printseeds seeds.txt
-printusage unused.txt
-printmapping mapping.txt
我什至在我的项目目录中使用以下行创建了一个文件 project.properties,但这似乎并没有吸引 ProGuard 采取行动:
proguard.config=proguard.cfg
此项目中未定义任何活动。我在 Windows 上使用 Android 2.3.1 和 Eclipse Galileo 3.5.2。与 Android 3.0 的结果相同。似乎必须在 Eclipse 导出向导中以某种方式显式插入混淆步骤。我将不胜感激任何帮助或见解。谢谢。
【问题讨论】:
@user1040716... 你能生成混淆的 JAR 吗? 【参考方案1】:正如 cmets 对上述答案之一的建议(但我一开始并没有注意到,因为它被埋在“其他 cmets”之一中)......
我们只需在命令行(参见下面的第一个块)在 eclipse 之外的库上运行 progruard,并在我们的proguard.cfg
文件中使用下面第二个块中的参数(绝对是 请勿使用-dontpreverify
,否则将您的项目用作android 库的项目将无法正确混淆,因为您的project.jar 中存在StackMapTable 问题。
命令行:
$ 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 *;
可能并非所有参数和 -keep 项都是绝对必要的(除了不使用前面提到的-dontpreverify
),但其中大部分对我来说是有意义的,因为如果你有一个活动则需要在那里您要导出的库中的类扩展。
【讨论】:
【参考方案2】:我使用间接方式生成导出的android混淆jar,我的方式是:
使用eclipse导出签名的apk
解压apk,找到classes.dex
使用dex2jar.bat,将classes.dex改成jar
解压jar并删除不需要的类,然后将其压缩并 把文件名改成XXX.jar
然后你在其他项目中使用这个jar,或者把它交给客户,它 很模糊!
我相信这会对你有所帮助!尽情享受吧!
【讨论】:
经过这些步骤后,我不能像旧罐子一样使用这个罐子了。旧导入 > com.abc.123 自动修复新导入 > XXX.com.abc.123 所以我的混淆类找不到彼此...有什么想法吗? 压缩 com 文件夹,而不是容器文件夹 在这里我的班级找不到彼此,即班级名称已更改【参考方案3】:java -jar proguard.jar @yourconfig.pro
yourconfig.pro(扩展自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();
结果可以用jd-gui验证
【讨论】:
谢谢!在 Mac 上:除了调整上述脚本的 -libraryjars 路径外,我还需要按照此处的说明软链接 rt.jar -> classes.jar:bruehlicke.blogspot.com/2009/11/…【参考方案4】:调用 ProGuard 的方法相当简单:
-
将
proguard.config=proguard.cfg
行添加到project.properties
导出应用程序包
默认的 proguard.cfg 文件应该已由新项目向导自动创建。
【讨论】:
@user1040716 - 你提到创建 proguard.cfg。当您设置项目时,它应该已自动为您创建。如果不存在,则可能项目配置不正确。尝试一个全新的 Android 项目。这应该是开箱即用的(一旦您将该行添加到 project.properties)。确保您的 SDK 工具是最新的。 我刚刚在Android 3.0下创建了一个全新的项目。从旧项目复制 src 文件。 proguard.cfg 文件是自动生成的,但 project.properties 不是自动生成的。所以首先我在 default.properties 中添加了“proguard.config=proguard.cfg”行。是否导出了 Java JAR 文件。没有发现混淆。然后我创建了一个本地文件 project.properties 并添加了该行。然后进行 Java JAR 文件的导出。同样,没有发现混淆。如果我“导出 Android 应用程序”,那么它会创建一个 .apk 文件。但我想要一个混淆的 .jar 文件。谢谢。 这个想法是让这个带有混淆代码的 .jar 文件在其他 Android 项目中使用,使用 Java Build Path/Libraries 下的“Add External Jars...”选项。 我认为您必须为此在 Eclipse 之外运行 ProGuard(或至少在 Android 构建过程之外)。 Android 构建过程仅在导出 .apk 文件时调用 ProGuard。 按照 Ted 的建议,我最终在 Eclipse 之外运行 ProGuard。谢谢。【参考方案5】:不要混淆你的纯Java Jar。在生成 Jar 时完全跳过该阶段(无论是在 Eclipse 中手动还是通过命令行中的 Ant 构建)。
相反,在 client 项目中设置并执行适当的混淆,该项目使用 Jar,您可以在其中将库添加为外部 Jar。 Proguard 也将能够混淆 Jar 中的代码。
我偶然发现了这个问题,并按照我在这里描述的那样成功地结束了。
【讨论】:
好吧,我想分发带有混淆代码的库(.jar 文件);其他人将在他们的客户项目中使用我的库。所以我需要在分发之前混淆我的纯 Java Jar。按照 Ted Hopp 的建议,我最终在 Eclipse 之外运行 ProGuard。 哈哈。抱歉,我的脑子肯定跳过了! @the down-voter:您能否详细说明建议的解决方案有什么问题。 Tnx以上是关于如何在 Eclipse 中使用 Proguard 混淆 Android 库(.jar 文件)的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Eclipse 中使用 Proguard 混淆 Android 库(.jar 文件)
如何在 Eclipse 和调试模式下使用 proguard?
Android Proguard:如何在 Eclipse 中设置?
导出已签名、混淆的 Android 应用程序时,如何在 Eclipse 中设置 ProGuard?