使用混淆ProGuard压缩代码和资源/减少方法数量

ProGuard介绍

ProGuard是一个Java类文件压缩器,优化器,混淆器和预先文件验证器。 压缩步骤检测和删除未使用的类,字段,方法和属性。 优化步骤分析和优化方法的字节码。 混淆步骤使用短无意义的名称重命名剩余的类,字段和方法。 这些步骤使代码更小,更高效,更难以进行逆向工程。 最终的预验证步骤将预验证信息添加到类,这是Java Micro Edition和Java 6及更高版本所必需的。

所以我们可以通过开启 ProGuard 来去除未使用的类、字段、方法和属性,包括自带代码库中的未使用项,这样就以变通方式解决了 64k 限制的问题。同时ProGuard 还可优化字节码,移除未使用的代码指令,以及用短名称混淆其余的类、字段和方法。这样也在一定程度上减少了Apk的大小。

ShrinkResources资源压缩通过 Android Plugin for Gradle 提供,该插件会移除应用中未使用的资源,包括库中未使用的资源。同样也可减少Apk的大小。

如何启用压缩和混淆?

先上代码,在build.gradle中配置如下:

android {
    buildTypes {
        release {
            minifyEnabled true //启用代码压缩
            shrinkResources true //启用资源压缩
            proguardFiles getDefaultProguardFile(‘proguard-android.txt‘),
                    ‘proguard-rules.pro‘//混淆规则文件配置
        }
    }
}
  • getDefaultProguardFile(‘proguard-android.txt’) 
    这个配置的意思是从 Android SDK tools/proguard/ 文件夹获取默认 ProGuard 设置。使用 proguard-android-optimize.txt 可以进一步的压缩代码还包括其他在字节码一级(方法内和方法间)执行分析的优化,可进一步减小 APK 大小和帮助提高其运行速度。
  • proguard-rules.pro 
    可以在这个文件中添加自定义的规则,该文件和build.gradle在同级目录下。

ProGuard的输出文件及用处: 
混淆过程完成后会生成如下几个文件, 
dump.txt 
说明 APK 中所有类文件的内部结构。 
mapping.txt 
提供原始与混淆过的类、方法和字段名称之间的转换。 
seeds.txt 
列出未进行混淆的类和成员。 
usage.txt 
列出从 APK 移除的代码。 
这些文件保存在 /build/outputs/mapping/release/目录下。

这里需要特别注意:每次release新版编译后,最好将这些文件加入git版本库一起保存,因为每次Release编译后这些文件都会被覆盖。

ProGuard配置说明

保留配置(即对配置的内容不进行处理)

-keep [,modifier,…] class_specification 
指定要保留的类和类成员(字段和方法)。

-keepclassmembers [,modifier,…] class_specification 
指定要保留的类成员,如果它们的类也被保留。 例如,你可能希望保留实现Serializable接口的所有序列化字段和类的方法。

-keepclasseswithmembers [,modifier,…] class_specification 
指定要保留的类和类成员,条件是所有指定的类成员都存在。 例如,你可能希望保留所有具有main方法的应用程序,而无需显式列出。

-keepnames class_specification 
-keep的缩写,允许class_specification 
指定要保存的类和类成员的名称(如果它们在压缩阶段不被删除)。 例如,你可能希望保留实现Serializable接口的类的所有类名,以便处理的代码与任何原始的序列化类保持兼容。 根本不使用的类仍然可以删除。 只适用于混淆。

-keepclassmembernames class_specification 
–keepclassmembers的缩写,allowhrinking class_specification 
指定要保存其名称的类成员,如果它们在压缩阶段未被删除。 例如,当处理由JDK 1.2或更旧版本编译的库时,你可能希望保留内部类$ 方法的名称,因此当处理使用已处理库的应用程序时,混淆器可以再次检测它(尽管ProGuard本身不需要 这个)。 只适用于混淆。

-keepclasseswithmembernames class_specification 
–keepclasseswithmembernames的缩写,允许class_specification 
指定要保留其名称的类和类成员,条件是所有指定的类成员在收缩阶段之后都存在。 例如,你可能希望保留所有本机方法名称和其类的名称,以便处理后的代码仍然可以链接到本机库代码。 根本不使用的本地方法仍然可以删除。 如果使用一个类文件,但是它的本机方法都不是,它的名字仍然会被模糊。 只适用于混淆。

-printseeds [filename] 
指定彻底列出由各种保护选项匹配的类和类成员。 列表打印到标准输出或给定文件。 该列表可用于验证是否真正找到预期的类成员,特别是如果你使用通配符。 例如,你可能希望列出所有应用程序或所有保留的小程序。

压缩

-dontshrink 
指定不压缩的类文件。 
-printusage {filename} 
指定需要列出dead code的类文件。 可以列出应用程序的未使用的代码。 只适用于压缩。 
-whyareyoukeeping {class_specification} 
指定打印关于给定类和类成员在压缩步骤中keep的原因的详细信息。 只适用于压缩。

优化

-dontoptimize 
指定不优化输入类文件。 默认情况下,启用优化; 所有方法都以字节码级别进行了优化。

-optimizations optimization_filter 
指定要在更细粒度的级别启用和禁用的优化。 仅适用于优化。 这是一个专家选项。

-optimizationpasses n 
指定要执行的优化通过次数。 默认情况下,执行单程。 多次通过可能会导致进一步的改进。 如果在优化通过后没有找到改进,则优化结束。 仅适用于优化。

-assumenosideeffects class_specification 
指定没有任何副作用的方法(可能返回值除外)。 在优化步骤中,ProGuard会删除对这些方法的调用,如果可以确定不使用返回值。例如,你可以指定方法System.out(),以便 用该选项来删除日志记录代码。 注意,该选项 仅适用于优化。 除非你很清楚这个方法的作用,否则请勿使用这个选项!

-allowaccessmodification 
指定在处理过程中可以扩展类和类成员的访问修饰符。 这可以改善优化步骤的结果。

-mergeinterfacesaggressively 
指定接口可能被合并,即使它们的实现类不实现所有接口方法。 这可以通过减少类的总数来减少输出的大小。

混淆

-dontobfuscate 不混淆输入的类文件 
-obfuscationdictionary {filename} 使用给定文件中的关键字作为要混淆方法的名称 
-overloadaggressively 混淆时应用侵入式重载 
-useuniqueclassmembernames 确定统一的混淆类的成员名称来增加混淆 
-flattenpackagehierarchy {package_name} 重新包装所有重命名的包并放在给定的单一包中 
-repackageclass {package_name} 重新包装所有重命名的类文件中放在给定的单一包中 
-dontusemixedcaseclassnames 混淆时不会产生形形色色的类名 
-keepattributes {attribute_name,…} 保护给定的可选属性,例如LineNumberTable, LocalVariableTable, SourceFile, Deprecated, Synthetic, Signature, and InnerClasses. 
-renamesourcefileattribute {string} 设置源文件中给定的字符串常量

在配置过程中可以使用通配符,关于通配符的说明如下,

通配符 说明
? 匹配任何单字符。
* 匹配除了包分隔符或目录分隔符之外的任何字符。
** 匹配任何字符的名称

自定义要保留的代码

通常来说,默认 ProGuard 配置文件 (proguard-android.txt) 足以满足需要,ProGuard 会移除所有(并且只会移除)未使用的代码。但是对许多情况进行正确分析时,可能会移除有用的代码。 
以下几种情况下它可能错误移除有用代码:

  • 当应用引用的类只来自 AndroidManifest.xml 文件时
  • 当应用调用的方法来自 Java 原生接口 (JNI) 时
  • 当应用在运行时(例如使用反射或自检)操作代码时
  • 当使用Parcelable的子类和Creator静态成员变量时
  • 当使用GSON、fastjson等框架时,所写的JSON对象类如果进行混淆会造成无法将JSON解析成对应的对象
  • 当使用第三方开源库或者引用其他第三方的SDK包时
  • 当有用到WEBView的JS调用时

在进行应用测试时应该能够发现这些因不当移除而导致的错误,具体也可查看 usage.txt 的内容来检查移除了哪些代码。 
例如类似下面这样的错误,我们就需要配置keep这些类不被混淆

10:47:34.635 [ERROR] [system.err] Warning: com.kennyc.view.MultiStateView$1: can‘t find referenced method ‘com.kennyc.view.MultiStateView$ViewState[] values()‘ in program class com.kennyc.view.MultiStateView$ViewState
10:47:34.636 [ERROR] [system.err] Warning: com.kennyc.view.MultiStateView$1: can‘t find referenced field ‘com.kennyc.view.MultiStateView$ViewState LOADING‘ in program class com.kennyc.view.MultiStateView$ViewState

配置内容如下即可解决问题:

-keep class com.kennyc.**

在AndroidMainfest中的类不会混淆,四大组件和Application的子类和Framework层下所有的类默认不会进行混淆,android提供的默认配置中都有。以下就是Android SDK中默认的ProGuard配置,即proguard-android.txt的内容

# This is a configuration file for ProGuard.
# http://proguard.sourceforge.net/index.html#manual/usage.html

-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-verbose

# Optimization is turned off by default. Dex does not like code run
# through the ProGuard optimize and preverify steps (and performs some
# of these optimizations on its own).
-dontoptimize
-dontpreverify
# Note that if you want to enable optimization, you cannot just
# include optimization flags in your own project configuration file;
# instead you will need to point to the
# "proguard-android-optimize.txt" file instead of this one from your
# project.properties file.

-keepattributes *Annotation*
-keep public class com.google.vending.licensing.ILicensingService
-keep public class com.android.vending.licensing.ILicensingService

# For native methods, see http://proguard.sourceforge.net/manual/examples.html#native
-keepclasseswithmembernames class * {
    native <methods>;
}

# keep setters in Views so that animations can still work.
# see http://proguard.sourceforge.net/manual/examples.html#beans
-keepclassmembers public class * extends android.view.View {
   void set*(***);
   *** get*();
}

# We want to keep methods in Activity that could be used in the XML attribute onClick
-keepclassmembers class * extends android.app.Activity {
   public void *(android.view.View);
}

# For enumeration classes, see http://proguard.sourceforge.net/manual/examples.html#enumerations
-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}

-keepclassmembers class * implements android.os.Parcelable {
  public static final android.os.Parcelable$Creator CREATOR;
}

-keepclassmembers class **.R$* {
    public static <fields>;
}

# The support library contains references to newer platform versions.
# Don‘t warn about those in case this app is linking against an older
# platform version.  We know about them, and they are safe.
-dontwarn android.support.**

# Understand the @Keep support annotation.
-keep class android.support.annotation.Keep

-keep @android.support.annotation.Keep class * {*;}

-keepclasseswithmembers class * {
    @android.support.annotation.Keep <methods>;
}

-keepclasseswithmembers class * {
    @android.support.annotation.Keep <fields>;
}

-keepclasseswithmembers class * {
    @android.support.annotation.Keep <init>(...);
}

列举一些库的混淆配置

##---------------Begin: proguard configuration for Twitter  ----------
-dontwarn com.squareup.okhttp.**
-dontwarn com.google.appengine.api.urlfetch.**
-dontwarn rx.**
-dontwarn retrofit.**
-keepattributes Signature
-keepattributes *Annotation*
-keep class com.squareup.okhttp.** { *; }
-keep interface com.squareup.okhttp.** { *; }
-keep class retrofit.** { *; }
-keepclasseswithmembers class * {
    @retrofit.http.* <methods>;
}
##---------------End: proguard configuration for Twitter  ----------

  

##---------------Begin: proguard configuration for Gson  ----------
# Gson uses generic type information stored in a class file when working with fields. Proguard
# removes such information by default, so configure it to keep all of it.
-keepattributes Signature

# For using GSON @Expose annotation
-keepattributes *Annotation*

# Gson specific classes
-keep class sun.misc.Unsafe { *; }
#-keep class com.google.gson.stream.** { *; }

# Application classes that will be serialized/deserialized over Gson
-keep class com.google.gson.examples.android.model.** { *; }

# Prevent proguard from stripping interface information from TypeAdapterFactory,
# JsonSerializer, JsonDeserializer instances (so they can be used in @JsonAdapter)
-keep class * implements com.google.gson.TypeAdapterFactory
-keep class * implements com.google.gson.JsonSerializer
-keep class * implements com.google.gson.JsonDeserializer
##---------------End: proguard configuration for Gson  ----------

  

##---------------Begin: proguard configuration for Glide  ----------
-keep public class * implements com.bumptech.glide.module.GlideModule
-keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** {
  **[] $VALUES;
  public *;
}
##---------------End: proguard configuration for Glide  ----------

  

##---------------Begin: proguard configuration for EventBus  ----------
-keepattributes *Annotation*
-keepclassmembers class ** {
    @org.greenrobot.eventbus.Subscribe <methods>;
}
-keep enum org.greenrobot.eventbus.ThreadMode { *; }

# Only required if you use AsyncExecutor
#-keepclassmembers class * extends org.greenrobot.eventbus.util.ThrowableFailureEvent {
#    <init>(java.lang.Throwable);
#}
##---------------End: proguard configuration for EventBus  ----------

  

##---------------Begin: proguard configuration for Paper  ----------
#1.Keep data classes:
-keep class com.bloomsky.android.model.** { *; }
#2.alternatively you can implement Serializable for all your data classes and keep all of them using:
#-keep class * implements java.io.Serializable { *; }
##---------------End: proguard configuration for Paper  ----------

  

##---------------Begin: proguard configuration for retrofit2  ----------
# Platform calls Class.forName on types which do not exist on Android to determine platform.
-dontnote retrofit2.Platform
# Platform used when running on Java 8 VMs. Will not be used at runtime.
-dontwarn retrofit2.Platform$Java8
# Retain generic type information for use by reflection by converters and adapters.
-keepattributes Signature
# Retain declared checked exceptions for use by a Proxy instance.
-keepattributes Exceptions
##---------------End: proguard configuration for retrofit2  ----------

移除调试log代码的配置

移除Log类打印各个等级日志的代码,打正式包的时候可以做为禁log使用,这里可以作为禁止log打印的功能使用,另外的一种实现方案是通过BuildConfig.DEBUG的变量来控制

-assumenosideeffects class android.util.Log {
    public static *** v(...);
    public static *** i(...);
    public static *** d(...);
    public static *** w(...);
    public static *** e(...);
}

  

恢复混淆前的堆栈信息

当混淆后的代码输出一个堆栈信息时,方法名是不可识别的,这使得调试变得很困难,甚至是不可能的。幸运的是,当ProGuard运行时,它都会输出一个/build/outputs/mapping/release/mapping.txt文件,而这个文件中包含了原始的类,方法和字段名被映射成的混淆名字。 
retrace.bat脚本(Window)或retrace.sh脚本(Linux,Mac OS X)可以将一个被混淆过的堆栈跟踪信息还原成一个可读的信息。它位于/tools/proguard文件夹中。执行retrace工具的语法如下: 
retrace.bat|retrace.sh [-verbose] mapping.txt [] 
例如: 
./retrace.sh -verbose mapping.txt obfuscated_trace.txt 
如果你没有指定,retrace工具会从标准输入读取。

原文地址:http://blog.csdn.net/ocean20/article/details/67634130 
更多关于ProGuard的信息可以访问, 
https://www.guardsquare.com/en/proguard/manual/examples

  

  

  

  

  

  

原文地址:https://www.cnblogs.com/ganchuanpu/p/9123482.html

时间: 2024-10-10 23:20:37

使用混淆ProGuard压缩代码和资源/减少方法数量的相关文章

Android开发实践:利用ProGuard进行代码混淆

由于Android的代码大都是Java代码,所以挺容易被反编译的,好在Android ADT为我们集成了混淆代码的工具,一来可以混淆我们的代码,让程序被反编译后基本看不懂,另外还能起到代码优化的作用.发布项目前,建议打开Android的代码混淆功能. Android ADT主要通过ProGuard工具来提供代码混淆,网上也有挺多博客文章讲这个的,但感觉很多都介绍得太过于复杂,这里我就以问答的方式来更加简洁地介绍下ProGuard吧. 1. ProGuard是什么 ProGuard是一个工具,用来

4.2、Android Studio压缩你的代码和资源

为了让你的APK文件尽可能的小,你需要在构建的时候开启压缩来移除无用的代码和资源. 代码压缩可在ProGuard中使用,可以检测和清除无用的类,变量,方法和属性,甚至包括你引用的库.ProGuard同样可以优化字节码,移除无用的代码,并且模糊剩下的类,变量和方法.代码模糊可以让增加APK逆向工程的成本. 资源压缩可在Andorid的Gradle插件中使用,可以清除你打包的APP中无用的资源,包含你引用的库中的无用的资源. 压缩你的代码 为了启用ProGuard的代码压缩,需要在build.gra

JAVA之代码混淆proguard

官方网站用法 http://proguard.sourceforge.net/index.html#/manual/examples.html proguard主要三部分功能 缩减代码.优化代码.混淆代码.三部分功能都可以在配置文件里配置不启用此功能. #Shrink Options #不缩减代码 -dontshrink #Optimization Options #优化代码 -dontoptimize #Obfuscate Options #-不混淆输入的类文件 #-dontobfuscate

Proguard android代码混淆 防止反编译

Proguard android代码混淆 防止反编译 http://www.360doc.com/content/13/1030/13/9171956_325290258.shtml

Android 代码混淆 proguard.flags

在我们编译Android系统的user版本的时候,有时候会出现proguard的错误,在解决这个错误之着,我们需要了解一些知识: 1,proguard是用来干什么的? 简单点说,他就是用来做JAVA代码混淆的一个工具. 2,这个东西在哪里实现的? 我们一般会在Android.mk文件中对其进行支持,比如: 1)指定不需要混淆的native方法和变量的proguard.flags文件 LOCAL_PROGUARD_FLAG_FILES := proguard.flags 2)对使用与不使用进行设定

Android Java混淆(ProGuard)

Android Java混淆(ProGuard)(转) ProGuard简介 ProGuard是一个SourceForge上非常知名的开源项目.官网网址是:http://proguard.sourceforge.net/. Java的字节码一般是非常容易反编译的.为了很好的保护Java源代码,我们往往会对编译好的class文件进行混淆处理.ProGuard的主要作用就是混淆.当然它还能对字节码进行缩减体积.优化等,但那些对于我们来说都算是次要的功能. 引用ProGuard官方的一段话来介绍就是:

图片压缩代码

此压缩代码,直接传入路径即可完成压缩,调用getImage()方法传入图片路径即可. 代码如下: /* * @param srcPath * @return * 图片比例大小压缩 */ private void getImage(String srcPath) { BitmapFactory.Options newOpts = new BitmapFactory.Options(); //开始读入图片,此时把options.inJustDecodeBounds 设回true了 newOpts.i

Cocos2d-x《赵云要格斗》游戏开源啦!要代码要资源就来!~~~~~~~~~~~~~~~~~~~~~

笔者自行开发的Cocos2d-x原创游戏<赵云要格斗>这里把全部的代码和资源全部共享,保证全部可以免费下载,笔者之前开发这个游戏的时就说过,此游戏最后一定会开源.游戏其实还没弄完,只是近期好多博友都在找笔者要代码要资源,笔者原本是想等游戏全部完成之后,再来公布的.现在打算提前点,笔者也认为社区大于代码,开源好于自己闭门造车.虽说笔者这游戏也很简单,代码有些地方也学有待完善,还是有很多地方需要增强.但是,笔者还是打算公布出来,而且要全部免费下载,论坛下载积分对我也没什么用,也希望下载后的人,有什

r.js压缩代码常用的配置及命令

最近用require写了一个网站的模块,到压缩的时候,各种查资料学习,但由于时间较紧,将所有代码都压缩成一个文件,导致代码的体积很大,今天抽时间网上参考下官网的说明配置,将这次压缩代码的配置及运行命令记录下来,以后留着用. 1. js的压缩 这次只是初步应用,如果有好的方法或有误的地方,还望各位大侠们指教. 第一种配置的文件: 需要把所有依赖的文件都压缩到当前代码中. ({ baseUrl: "./", paths: { amd_modules: "../amd_module