混淆,将类名、方法名、成员变量等重命名为无意义的简短名称,以增加逆向工程的难度,同时通过移除无用的类减少包的大小。
proguard-android.txt
:sdk 默认的混淆配置proguard-rules.pro
:针对本模块做出的特殊混淆处理
混淆基础语法
混淆语法主要用于定义不需要混淆的代码。
混淆的语法有很多,下面列出常用语法及使用说明:
- 不混淆指定类
-keep class com.xx.Test{*;}
- 不混淆指定路径下的所有类/接口
-keep class com.xx.model.** { *; }
- 不混淆某个类的特定函数
-keepclassmembers class com.xx.Test{
public void 函数名(java.lang.String);
}
对于构造函数:
-keepcalssmembers clsss com.xx.Test{
public <init>(java.lang.String)
}
- 不混淆某个类/接口的子类/实现
-keep public class * extend com.xx.Test
-keep class * implements com.xx.Test {
public static final com.xx.Test$Creator *;
}
- 如果项目混淆,则会在
build/outputs/mapping/xx
目录下生成以下几个文件:
mapping.txt
:混淆前后的映射关系;
seeds.txt
:未混淆的类及成员;
usage.txt
:从 apk 中删除的代码;(混淆会优化代码,将一些不使用的类删除)
dump.txt
:所有 class 的内部结构。
利用 mapping.txt,收到异常报告时,可以定位问题来源,但需要注意的是每次混淆打包都会覆盖之前的 mapping.txt
。
- 其它(选配)
-ignorewarnings # 忽略警告,避免打包时某些警告出现
-optimizationpasses 5 # 指定代码的压缩级别
-dontusemixedcaseclassnames # 不使用大小写混合类名
-dontskipnonpubliclibraryclasses # 不混淆第三方 jar 中的非 public classes
-dontskipnonpubliclibraryclassmembers #不混淆第三方 jar 的非 public class
-dontpreverify # 混淆时不做预校验
-dontshrink # 禁止删除无用包
-dontoptimize # 不启用优化、合并代码
-verbose # 混淆时记录日志
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/* # 混淆时所采用的算法
-renamesourcefileattribute SourceFile
更多可配置选项可查询 Android 代码混淆选项详细说明
混淆注意事项
因为混淆会重新命名类名、方法名、变量名,当某些代码要求原名调用时,混淆后的代码因为类名找不到会导致 crash。以下情况不能/不建议混淆(可作为基本混淆规则配置在混淆文件中,多余的配置不会导致编译失败):
1.反射中使用的类或变量;
2.bean 对象;
3.四大组件;(四大组件需要在 AndroidManifest 注册)
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Fragment
-keep public class * extends android.support.v4.app.Fragment
-keep public class * extends android.support.v4.app.FragmentActivity
-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 public class * extends android.view.View
-keep public class com.android.vending.licensing.ILicensingService
-dontnote com.android.vending.licensing.ILicensingService
4.注解;(用于运行时、编译时反射)
-keepattributes *Annotation*
5.枚举;
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
6.JNI 调用 Java 方法;
7.Java 调用 Native 方法;
-keepclasseswithmembernames class * {
native <methods>;
}
8.JS 调用 Java 方法;
-keepattributes *JavascriptInterface*
9.WebView 中 JavaScript 的调用方法不能混淆;
-keepclassmembers class fqcn.of.javascript.interface.for.Webview {
pub1ic *;
}
-keepclassmembers class * extends android.webkit.WebViewClient {
public void * (android.webkit.WebView, java.lang.String, android.graphics.Bitmap);
public boolean * (android.webkit.WebView, java.lang.String);
}
-keepclassmembers class * extends android.webkit.WebViewClient {
public void * (android.webkit.Webview, java.lang.String);
}
10.第三方库使用其自身混淆规则,或干脆一律不混淆;
-dontwarn com.xx.xx.**
-keep class com.xx.xx.** { *;}
11.Parcelable 序列化相关类;
-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}
-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();
}
12.Gson;
-keep class com.google.gson.** { *; }
-keep class sun.misc.Unsafe { *; }
-keep class com.google.gson.stream.** { *; }
-keep class com.google.gson.examples.android.model.** { *; }
-keep class com.google.** {
<fields>;
<methods>;
}
-dontwarn com.google.gson.**
部分内容参考自《 Android 组件化架构》一书,并查缺补漏。
转载于:https://www.jianshu.com/p/266774a713c0