【问题标题】:How to create an obfuscated jar file?如何创建一个混淆的 jar 文件?
【发布时间】:2011-05-23 20:31:46
【问题描述】:

如何创建混淆 jar 文件?到目前为止,我可以轻松地将我的 Android lib 项目导出到 jar 中并使用它。如何混淆 jar 文件?

我的最终目标是允许其他人在他们的项目中使用我的 lib.jar。我只是想尽可能地保护代码...... :)

【问题讨论】:

    标签: android obfuscation proguard


    【解决方案1】:

    事实证明这是可能的,而且并不难。经过3小时的尝试,我终于弄明白了!

    Android 下提供了一个方便的 proguard GUI:

    android-sdk\tools\proguard

    使用 GUI,您只需选择 in.jar 和 out.jar。比您必须选择 android.jar 并删除选定的默认 rt.jar。

    完成后,您必须仔细选择 Shrinking 和 Obfuscation 选项。

    我希望这会有所帮助!

    【讨论】:

    • 把rt.jar换成android.jar绝对值得一提。 +1。
    • 感谢您发布此答案 - 您能否添加您如何保存库类以便可以访问它们?导入(libs 文件夹,添加到构建路径)带有 A.class 等类的混淆库后,什么都没有被识别出来,我一直坚持到底要保留什么,同时仍然保护代码
    【解决方案2】:

    弄清楚这一点并不容易,但一旦完成,重复这些步骤并不难:

    • 像往常一样创建和构建您的 Android 库项目
    • 创建一个 proguard.cfg 文件(以下是一个配方,但包含一些重要部分。

    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 *;
    }
    
    • 在命令行上(这是面向 darwin,但在 Windows 上应该基本相同

    $ 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 库项目,尽管它被混淆了。

    【讨论】:

      【解决方案3】:

      如果它是一个外部 jar,那么如果你将它放在“libs”文件夹中并使用 Android 2.2+ SDK 进行编译,它会自动使用 proguard 来混淆 apk。如果您希望将此 jar 作为库并在将其用于您的 apk 之前对其进行混淆,那么这可能是不可能的。如果您谈论的是 apk 混淆,我认为(使用 proguard)从 2.2 开始,Android 会这样做,您不必担心。

      【讨论】:

      • 感谢您的评论。我实际上正在研究混淆实际的 lib.jar 文件。 Flurry 使用他们的 SDK 库做到这一点。
      • 混淆那个jar可能就像在它上面运行proguard一样简单,在Android apk中使用那个混淆过的jar可能很困难。
      【解决方案4】:

      您可以为您的项目启用 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); } 
      

      相当大的区域,但希望它有所帮助......

      【讨论】:

      • 这是一个完整的 Android 项目,我已经可以正常工作了。我只想用我的代码混淆一个 jar 文件。 jar 与最终项目完全分开。 jar 确实包含 Android 代码。此 jar 旨在分发给其他开发人员。
      【解决方案5】:

      要创建一个混淆的 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 
        

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-07-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-10-28
        • 2010-10-23
        相关资源
        最近更新 更多