在 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 调用也需要保证写的接口方法不混淆
参考资料
-
其中提供了一些常用第三方库的混淆配置,例如:
glide
(google官方出的图片加载库),stetho
(Facebook出的黑科技,使用Okhttp框架支持Chrome显示app日志及数据库等数据),Gson
(Json转POJO,官方出品的json经典库),butterknife
(注解框架),新浪微博
,Okio
(基于NIO的流),Rxjava
,WebView
等。