如何在 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?

如何使用 Eclipse + Proguard“运行”导出的 Android 应用程序?

在 Eclipse 中使用 Proguard for Android 出错