Android Studio:ProGuard 混淆配置

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/doris_d/article/details/52609703

在 Android Studio 中可通过配置 proguard-rules.pro 对生成的 apk 和 jar 进行加密,以免被轻易破解。(附:破解方法

Android Studio 创建Module后,会自动生成 proguard-rules.pro 文件,在其中添加需要的规则即可,另外需要配置 build.gradle,开启混淆功能。

    buildTypes {
        debug {
            buildConfigField "boolean", "LOG_DEBUG", "true"
            // VersionName后缀
            versionNameSuffix "-debug"
            minifyEnabled false
            zipAlignEnabled false
            shrinkResources false
        }
        release {
            // 不显示log
            buildConfigField "boolean", "LOG_DEBUG", "false"
            // 混淆
            minifyEnabled true
            // Zipalign优化
            zipAlignEnabled true
            // 移除无用的resource
            shrinkResources true
            // 混淆配置
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

其中,release 部分配置了开启混淆,保证打包 release 时会进行混淆。debug 不进行混淆,否则无法调试。

若需要混淆的 jar,那么在库类型的 moudle 中也需要配置 proguard-rules.pro 及 build.gradle,生成后即可在 build\intermediates\bundles\release 中获得混淆后的 jar。


ProGuard 简介

ProGuard 能够对 Java 类中的代码进行压缩(Shrink),优化(Optimize),混淆(Obfuscate),预检(Preveirfy)。

  • 压缩(Shrink):检测和删除没有使用的类,字段,方法和属性。

  • 优化(Optimize):对字节码进行优化,并且移除无用指令。

  • 混淆(Obfuscate):使用 a,b,c 等无意义的名称,对类,字段和方法进行重命名。

  • 预检(Preveirfy):主要是在 Java 平台上对处理后的代码进行预检。

常用规则如下:

斜体字 表示需要设置的参数,[ ] 中的内容表示可选的配置。

  • 【-assumenosideeffects class_specification

Assume that the specified methods don’t have any side effects, while
optimizing.

假设调用不产生任何影响,在 proguard 代码优化时会将该调用 remove 掉。如 system.out.println 和 Log.v 等。
  • 【-dontwarn [class_filter]】

Don’t warn about unresolved references at all.

  • 【-dump [filename]】

Write out the internal structure of the processed class files, to the
standard output or to the given file.

  • 【-keep [,modifier,…] class_specification

Preserve the specified classes and class members.

  • 【-keepattributes [attribute_filter]】

Preserve the given optional attributes; typically Exceptions,
InnerClasses, Signature, Deprecated, SourceFile, SourceDir,
LineNumberTable, LocalVariableTable, LocalVariableTypeTable,
Synthetic, EnclosingMethod, and *Annotation*.

  • 【-keepclasseswithmembernames class_specification

Preserve the names of the specified classes and class members, if all
of the specified class members are present (after the shrinking step).

  • 【-keepclassmembers [,modifier,…] class_specification

Preserve the specified class members, if their classes are preserved
as well.

  • 【-keepnames class_specification

Preserve the names of the specified classes and class members (if they
aren’t removed in the shrinking step).

  • 【-libraryjars class_path

Specifies the library jars (or wars, ears, zips, or directories).

应用的依赖包,如 android-support-v4。
  • 【-optimizationpasses n

The number of optimization passes to be performed.

  • 【-optimizations optimization_filter

The optimizations to be enabled and disabled.

  • 【-printmapping [filename]】

Print the mapping from old names to new names for classes and class
members that have been renamed, to the standard output or to the given
file.

  • 【-printseeds [filename]】

List classes and class members matched by the various -keep options,
to the standard output or to the given file.

  • 【-printusage [filename]】

List dead code of the input class files, to the standard output or to
the given file.


ProGuard 常用配置

android sdk 的 /sdk/tools/proguard/proguard-android.txt 中已经提供了基本的混淆配置,不需要在 proguard-rules.pro 中重复配置。

sdk 提供的 proguard-android.txt 中提供的默认配置说明参见 Android : proguard-android.txt 解析

除此之外,需要在 proguard-rules.pro 中添加的常用配置如下:

######################## 公共 ########################

#指定代码的压缩级别
-optimizationpasses 5

# 混淆时所采用的算法
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*

#记录生成的日志数据,gradle build时在本项目根目录输出
#apk 包内所有 class 的内部结构
-dump class_files.txt
#未混淆的类和成员
-printseeds seeds.txt
#列出从 apk 中删除的代码
-printusage unused.txt
#混淆前后的映射
-printmapping mapping.txt

#移除log代码
-assumenosideeffects class android.util.Log {
    public static *** v(...);
    public static *** i(...);
    public static *** d(...);
    public static *** w(...);
    public static *** e(...);
}

#不混淆反射用到的类
-keepattributes Signature
-keepattributes EnclosingMethod

#保持继承自系统类的class不被混淆
-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
-keep interface android.support.v4.app.** { *; }
-keep class android.support.v4.** { *; }
-keep public class * extends android.support.v4.**
-keep interface android.support.v7.app.** { *; }
-keep class android.support.v7.** { *; }
-keep public class * extends android.support.v7.**
-keep public class * extends android.app.Fragment
-keep class * extends android.**{*;}

#不混淆Serializable接口的子类中指定的某些成员变量和方法
-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();
}

######################## Module自定义 ########################

############ 不混淆引用的jar ############

#不混淆butterknife
-keepclasseswithmembernames class * {
    @butterknife.* <fields>;
}
-keepclasseswithmembernames class * {
    @butterknife.* <methods>;
}
-dontwarn butterknife.internal.**

#不混淆AndroidBootstrap
-keep class com.beardedhen.androidbootstrap.**{*;}
-dontwarn com.beardedhen.androidbootstrap.**

#不混淆应用宝自更新jar
-keep class com.qq.**
-dontwarn com.qq.**
-keep class com.tencent.**
-dontwarn com.tencent.**

############ 保持自定义控件不被混淆 ############

-keepclasseswithmembernames class * {
    public <init>(android.content.Context);
}
-keepclasseswithmembernames class * {
    public <init>(android.content.Context, android.util.AttributeSet);
}
-keepclasseswithmembernames class * {
    public <init>(android.content.Context, android.util.AttributeSet, int);
}
-keepclasseswithmembernames class * {
    public <init>(android.content.Context, android.util.AttributeSet, int, int);
}

############ 项目内部类的混淆配置 ############

#不混淆整个包
#-keep class com.test.test.**{*;}

#不混淆对外接口的public类名和成员名,否则外部无法调用
#-keep public interface com.test.test.**{*;}
#-keep public enum com.test.test.**{*;}
#-keep public class com.test.test.**{
#    public *;
#}

#忽略项目中其他Module的警告 ############
#-dontwarn com.test.test.**

注意事项

  • 反射用到的类不能混淆,JNI 方法不混淆

  • AndroidMainfest 中的类不混淆

  • 四大组件和 Application 的子类和 Framework 层下所有的类默认不会进行混淆

  • Parcelable 的子类和 Creator 静态成员变量不混淆,否则会产生 android.os.BadParcelableException 异常

  • 使用 GSON、fastjson 等框架时,所写的 JSON 对象类不混淆,否则无法将 JSON 解析成对应的对象

  • 使用第三方开源库或者引用其他第三方的SDK包时,需要在混淆文件中加入对应的混淆规则

  • 有用到 WEBView 的 JS 调用也需要保证写的接口方法不混淆


参考资料

阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页