解决方案

Android 代码混淆

seo靠我 2023-09-22 22:20:25

Android混淆最佳实践

1. 混淆配置

因为开启混淆会使编译时间变长,所以debug模式下不开启。我们需要做的是:

1.将release下minifyEnabled的值改为true,打开混淆;

2.加上sSEO靠我hrinkResources true,打开资源压缩。

3.buildConfigField 不显示log日志

4.signingConfig signingConfigs.config配置签名文件文件

SEO靠我定义混淆规则

自定义混淆方案适用于大部分的项目

android{buildTypes {release {buildConfigField "boolean", "LOG_DEBUG", "false" SEO靠我//不显示logminifyEnabled trueshrinkResources trueproguardFiles getDefaultProguardFile(proguard-android.SEO靠我txt), proguard-rules.prosigningConfig signingConfigs.config}} }

or

buildTypes {debug { minifyESEO靠我nabled false // 混淆 zipAlignEnabled true // Zipalign优化 shrinkResources true // 移除无用的resource文件 proguaSEO靠我rdFiles getDefaultProguardFile(proguard-android.txt), proguard-rules.pro // 加载默认混淆配置文件 signingConfigSEO靠我 signingConfigs.debug // 签名}release { minifyEnabled true // 混淆 zipAlignEnabled true // Zipalign优化 shSEO靠我rinkResources true // 移除无用的resource文件 proguardFiles getDefaultProguardFile(proguard-android.txt), prSEO靠我oguard-rules.pro // 加载默认混淆配置文件signingConfig signingConfigs.relealse // 签名}}

2. 混淆规则

混淆会用无意义的短变量去重命名类、变SEO靠我量、方法,但是对于外部的一些引用是通过名字找到对应的方法和类。混淆过后通过原来的名字去找混淆后的名字,是找不到对应方法和类,就会出异常报错。所以有些情况是不能进行混淆的。

自定义控件不进行混淆枚举类不被SEO靠我混淆反射类不进行混淆实体类不被混淆JS调用的Java方法四大组件不进行混淆JNI中调用类不进行混淆Layout布局使用的View构造函数、android:onClick等Parcelable 的子类和SEO靠我 Creator 静态成员变量不混淆第三方开源库或者引用其他第三方的SDK包不进行混淆

3. 混淆模板

1)基本指令

# 设置混淆的压缩比率 0 ~ 7 -optimizationpasseSEO靠我s 5 # 混淆时不使用大小写混合,混淆后的类名为小写 -dontusemixedcaseclassnames # 指定不去忽略非公共库的类 SEO靠我 -dontskipnonpubliclibraryclasses # 指定不去忽略非公共库的成员 -dontskipnonpubliclibraryclassmeSEO靠我mbers # 混淆时不做预校验 -dontpreverify # 混淆时不记录日志 -verbose # 忽略警告 SEO靠我 -ignorewarning # 代码优化 -dontshrink # 不优化输入的类文件 -dontoptimize SEO靠我 # 保留注解不混淆 -keepattributes *Annotation*,InnerClasses # 避免混淆泛型 -keepattSEO靠我ributes Signature # 保留代码行号,方便异常信息的追踪 -keepattributes SourceFile,LineNumberTable SEO靠我 # 混淆采用的算法 -optimizations !code/simplification/cast,!field/*,!class/merging/* # dump.txt文SEO靠我件列出apk包内所有class的内部结构 -dump class_files.txt # seeds.txt文件列出未混淆的类和成员 -printseeSEO靠我ds seeds.txt # usage.txt文件列出从apk中删除的代码 -printusage unused.txt # mapping.txt文SEO靠我件列出混淆前后的映射 -printmapping mapping.txt

2)不需混淆的Android类

-keep public class * extends android.app.SEO靠我Fragment -keep public class * extends android.app.Activity -keep public class * exteSEO靠我nds android.app.Application -keep public class * extends android.app.Service -keep pSEO靠我ublic class * extends android.content.BroadcastReceiver -keep public class * extends androidSEO靠我.preference.Preference -keep public class * extends android.content.ContentProvider SEO靠我-keep public class * extends android.support.v4.** -keep public class * extends android.suppSEO靠我ort.annotation.** -keep public class * extends android.support.v7.** -keep public clSEO靠我ass * extends android.app.backup.BackupAgentHelper -keep public class * extends android.prefSEO靠我erence.Preference -keep public class * extends android.view.View -keep public class SEO靠我com.android.vending.licensing.ILicensingService -keep class android.support.** {*;}

3)supportSEO靠我-v4包

-dontwarn android.support.v4.** -keep class android.support.v4.app.** { *; } -keSEO靠我ep interface android.support.v4.app.** { *; } -keep class android.support.v4.** { *; }

4)suppSEO靠我ort-v7包 

-dontwarn android.support.v7.** -keep class android.support.v7.internal.** { *; } SEO靠我 -keep interface android.support.v7.internal.** { *; } -keep class android.support.v7.**SEO靠我 { *; }

5)support design

-dontwarn android.support.design.** -keep class android.support.desigSEO靠我n.** { *; } -keep interface android.support.design.** { *; } -keep public class andrSEO靠我oid.support.design.R$* { *; }

6)避免混淆自定义控件类的 get/set 方法和构造函数

-keep public class * extends android.view.SEO靠我View{*** get*();void set*(***);public <init>(android.content.Context);public <init>(android.content.SEO靠我Context, android.util.AttributeSet);public <init>(android.content.Context, android.util.AttributeSetSEO靠我, int); }

7)关闭 Log日志

-assumenosideeffects class android.util.Log {public static boolean isLoggSEO靠我able(java.lang.String, int);public static int v(...);public static int i(...);public static int w(..SEO靠我.);public static int d(...);public static int e(...); }

-dontoptimize不要配置,不然将会关闭优化,导致日志语句不会被优SEO靠我化掉。

8)避免资源混淆

-keep class **.R$* {*;}

9)避免layout中onclick方法(android:οnclick="onClick")混淆

-keepclassmembersSEO靠我 class * extends android.app.Activity{public void *(android.view.View); }

10)避免回调函数 onXXEventSEO靠我 混淆

-keepclassmembers class * {void *(*Event); }

11)避免混淆枚举类

-keepclassmembers enum * {public stSEO靠我atic **[] values();public static ** valueOf(java.lang.String); }

12)Natvie 方法不混淆

-keepclasseswSEO靠我ithmembernames class * {native <methods>; }

13)避免Parcelable混淆

-keep class * implements androidSEO靠我.os.Parcelable {public static final android.os.Parcelable$Creator *; }

14)避免Serializable接口的子类SEO靠我中指定的某些成员变量和方法混淆

-keepclassmembers class * implements java.io.Serializable {static final long serialVeSEO靠我rsionUID;private static final java.io.ObjectStreamField[] serialPersistentFields;!static !transient SEO靠我<fields>;private void writeObject(java.io.ObjectOutputStream);private void readObject(java.io.ObjectSEO靠我InputStream);java.lang.Object writeReplace();java.lang.Object readResolve(); }

15)WebView混淆配置SEO靠我

-keepclassmembers class fqcn.of.javascript.interface.for.webview {public *; } -keepcSEO靠我lassmembers class * extends android.webkit.webViewClient {public void *(android.webkit.WebView, javaSEO靠我.lang.String, android.graphics.Bitmap);public boolean *(android.webkit.WebView, java.lang.String); SEO靠我 } -keepclassmembers class * extends android.webkit.webViewClient {public void *(androSEO靠我id.webkit.webView, jav.lang.String); }

16)ButterKnife混淆配置

-keep class butterknife.** { *; } SEO靠我 -dontwarn butterknife.internal.** -keep class **$$ViewBinder { *; } -keepclassSEO靠我eswithmembernames class * {@butterknife.* <fields>; } -keepclasseswithmembernames clSEO靠我ass * {@butterknife.* <methods>; }

17)OkHttp3混淆配置

-dontwarn com.squareup.okhttp3.** -kSEO靠我eep class com.squareup.okhttp3.** { *;} -dontwarn okio.**

18)Retrofit2混淆配置

-dontwarn retrofit2SEO靠我.** -keep class retrofit2.** { *; } -keepattributes Signature -keepattributeSEO靠我s Exceptions

19)RxJava、RxAndroid混淆配置

-dontwarn sun.misc.** -keepclassmembers class rx.internalSEO靠我.util.unsafe.*ArrayQueue*Field* {long producerIndex;long consumerIndex; } -keepclassSEO靠我members class rx.internal.util.unsafe.BaseLinkedQueueProducerNodeRef {rx.internal.util.atomic.LinkedSEO靠我QueueNode producerNode; } -keepclassmembers class rx.internal.util.unsafe.BaseLinkedSEO靠我QueueConsumerNodeRef {rx.internal.util.atomic.LinkedQueueNode consumerNode; }

20)Glide混淆配置

GliSEO靠我de 3 -keep public class * implements com.bumptech.glide.module.GlideModule -keep pubSEO靠我lic enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** {**[] $VALUES;public *; SEO靠我 } Glide 4 -keep public class * implements com.bumptech.glide.module.AppGlideModulSEO靠我e -keep public class * implements com.bumptech.glide.module.LibraryGlideModule -keepSEO靠我 public enum com.bumptech.glide.load.ImageHeaderParser$** {**[] $VALUES;public *; }

21)PicassSEO靠我o混淆配置

-keep class com.parse.*{ *; } -dontwarn com.parse.** -dontwarn com.squareup.picSEO靠我asso.** -keepclasseswithmembernames class * {native <methods>; }

22)Fresco混淆配置

# Keep SEO靠我our interfaces so they can be used by other ProGuard rules. # See http://sourceforge.net/p/pSEO靠我roguard/bugs/466/ -keep,allowobfuscation @interface com.facebook.common.internal.DoNotStrip SEO靠我 -keep,allowobfuscation @interface com.facebook.soloader.DoNotOptimize# Do not strip any methSEO靠我od/class that is annotated with @DoNotStrip -keep @com.facebook.common.internal.DoNotStrip cSEO靠我lass * -keepclassmembers class * {@com.facebook.common.internal.DoNotStrip *; }# Do SEO靠我not strip any method/class that is annotated with @DoNotOptimize -keep @com.facebook.soloadeSEO靠我r.DoNotOptimize class * -keepclassmembers class * {@com.facebook.soloader.DoNotOptimize *; SEO靠我 }# Keep native methods -keepclassmembers class * {native <methods>; }-dontwarSEO靠我n okio.** -dontwarn com.squareup.okhttp.** -dontwarn okhttp3.** -dontwarn jaSEO靠我vax.annotation.** -dontwarn com.android.volley.toolbox.** -dontwarn com.facebook.infSEO靠我er.**

23)Fastjson混淆配置

-dontwarn com.alibaba.fastjson.** -keep class com.alibaba.fastjson.**{*;SEO靠我 }

24)Gson混淆配置

-keep class com.google.gson.** {*;} -keep class com.google.**{*;} -keepSEO靠我 class sun.misc.Unsafe { *; } -keep class com.google.gson.stream.** { *; } -keep claSEO靠我ss com.google.gson.examples.android.model.** { *; }

25)Banner混淆配置

-keep class com.youth.banner.** {*;}SEO靠我

26)GreenDao混淆配置

GreenDAO 2: -keep class de.greenrobot.dao.** {*;} -keepclassmembers cSEO靠我lass * extends de.greenrobot.dao.AbstractDao {public static Java.lang.String TABLENAME; } SEO靠我 -keep class **$Properties GreenDAO 3: -keepclassmembers class * extends org.gSEO靠我reenrobot.greendao.AbstractDao { public static java.lang.String TABLENAME; } SEO靠我 -keep class **$Properties# If you do not use SQLCipher: -dontwarn org.greenrobot.greendao.dSEO靠我atabase.** # If you do not use Rx: -dontwarn rx.**

27)百度定位混淆配置

-keep class vi.com.gdi.SEO靠我** { *; } -keep public class com.baidu.** {*;} -keep public class com.mobclick.** {*SEO靠我;} -dontwarn com.baidu.mapapi.utils.* -dontwarn com.baidu.platform.comapi.b.* SEO靠我 -dontwarn com.baidu.platform.comapi.map.*

28)百度地图混淆配置

-keep class com.baidu.** {*;} -keep clSEO靠我ass vi.com.** {*;} -dontwarn com.baidu.**

29)高徳地图混淆配置

-dontwarn com.amap.api.** -dontwSEO靠我arn com.a.a.** -dontwarn com.autonavi.** -keep class com.amap.api.** {*;} -kSEO靠我eep class com.autonavi.** {*;} -keep class com.a.a.** {*;}

30)Bugly混淆配置

-dontwarn com.tencent.SEO靠我bugly.** -keep public class com.tencent.bugly.**{*;}

31)EventBus混淆配置

EventBus 2: -keepSEO靠我classmembers class ** {public void onEvent*(***); }# Only required if you use AsyncExecutor SEO靠我 -keepclassmembers class * extends de.greenrobot.event.util.ThrowableFailureEvent {<init>(javSEO靠我a.lang.Throwable); } EventBus 3: -keepattributes *Annotation* -keepSEO靠我classmembers class ** {@org.greenrobot.eventbus.Subscribe <methods>; } -keep enum orSEO靠我g.greenrobot.eventbus.ThreadMode { *; }# Only required if you use AsyncExecutor -keepclassmeSEO靠我mbers class * extends org.greenrobot.eventbus.util.ThrowableFailureEvent {<init>(java.lang.ThrowableSEO靠我); }

32)友盟分享混淆配置

-dontshrink -dontoptimize -dontwarn com.google.android.maps.*SEO靠我* -dontwarn android.webkit.WebView -dontwarn com.umeng.** -dontwarn com.tencSEO靠我ent.weibo.sdk.** -dontwarn com.facebook.** -keep public class javax.** -keepSEO靠我 public class android.webkit.** -dontwarn android.support.v4.** -keep enum com.facebSEO靠我ook.** -keepattributes Exceptions,InnerClasses,Signature -keepattributes *AnnotationSEO靠我* -keepattributes SourceFile,LineNumberTable-keep public interface com.facebook.** -SEO靠我keep public interface com.tencent.** -keep public interface com.umeng.socialize.** -SEO靠我keep public interface com.umeng.socialize.sensor.** -keep public interface com.umeng.scrshotSEO靠我.**-keep public class com.umeng.socialize.* {*;}-keep class com.facebook.** -keep class com.SEO靠我facebook.** { *; } -keep class com.umeng.scrshot.** -keep public class com.tencent.*SEO靠我* {*;} -keep class com.umeng.socialize.sensor.** -keep class com.umeng.socialize.hanSEO靠我dler.** -keep class com.umeng.socialize.handler.* -keep class com.umeng.weixin.handlSEO靠我er.** -keep class com.umeng.weixin.handler.* -keep class com.umeng.qq.handler.** SEO靠我 -keep class com.umeng.qq.handler.* -keep class UMMoreHandler{*;} -keep class coSEO靠我m.tencent.mm.sdk.modelmsg.WXMediaMessage {*;} -keep class com.tencent.mm.sdk.modelmsg.** impSEO靠我lements com.tencent.mm.sdk.modelmsg.WXMediaMessage$IMediaObject {*;} -keep class im.yixin.sdSEO靠我k.api.YXMessage {*;} -keep class im.yixin.sdk.api.** implements im.yixin.sdk.api.YXMessage$YSEO靠我XMessageData{*;} -keep class com.tencent.mm.sdk.** {*; } -keep class com.tenSEO靠我cent.mm.opensdk.** {*; } -keep class com.tencent.wxop.** {*; } -keepSEO靠我 class com.tencent.mm.sdk.** {*; } -dontwarn twitter4j.** -keep class twitteSEO靠我r4j.** { *; }-keep class com.tencent.** {*;} -dontwarn com.tencent.** -keep class coSEO靠我m.kakao.** {*;} -dontwarn com.kakao.** -keep public class com.umeng.com.umeng.soexamSEO靠我ple.R$*{public static final int *; } -keep public class com.linkedin.android.mobilesSEO靠我dk.R$*{public static final int *; } -keepclassmembers enum * {public static **[] valSEO靠我ues();public static ** valueOf(java.lang.String); }-keep class com.tencent.open.TDialog$* SEO靠我 -keep class com.tencent.open.TDialog$* {*;} -keep class com.tencent.open.PKDialog SEO靠我 -keep class com.tencent.open.PKDialog {*;} -keep class com.tencent.open.PKDialog$* SEO靠我 -keep class com.tencent.open.PKDialog$* {*;} -keep class com.umeng.socialize.impl.ImageImSEO靠我pl {*;} -keep class com.sina.** {*;} -dontwarn com.sina.** -keep class com.aSEO靠我lipay.share.sdk.** {*; }-keepnames class * implements android.os.Parcelable {public static fSEO靠我inal ** CREATOR; }-keep class com.linkedin.** { *; } -keep class com.android.dingtalSEO靠我k.share.ddsharemodule.** { *; } -keepattributes Signature

33)友盟推送混淆配置

-dontwarn com.umeng.** SEO靠我 -dontwarn com.taobao.** -dontwarn anet.channel.** -dontwarn anetwork.channel.SEO靠我** -dontwarn org.android.** -dontwarn org.apache.thrift.** -dontwarn com.xiaSEO靠我omi.** -dontwarn com.huawei.** -dontwarn com.meizu.**-keepattributes *Annotation*-keSEO靠我ep class com.taobao.** {*;} -keep class org.android.** {*;} -keep class anet.channelSEO靠我.** {*;} -keep class com.umeng.** {*;} -keep class com.xiaomi.** {*;} -keep SEO靠我class com.huawei.** {*;} -keep class com.meizu.** {*;} -keep class org.apache.thriftSEO靠我.** {*;}-keep class com.alibaba.sdk.android.**{*;} -keep class com.ut.**{*;} -keep cSEO靠我lass com.ta.**{*;}-keep public class **.R$*{public static final int *; } #指定压缩级别 SEO靠我 -optimizationpasses 5#不跳过非公共的库的类成员 -dontskipnonpubliclibraryclassmembers#混淆时采用的算法 SEO靠我 -optimizations !code/simplification/arithmetic,!field/*,!class/merging/*#把混淆类中的方法名也混淆了 SEO靠我-useuniqueclassmembernames#优化时允许访问并修改有修饰符的类和类的成员 -allowaccessmodification#将文件来源重命名为“SourceFiSEO靠我le”字符串 -renamesourcefileattribute SourceFile #保留行号 -keepattributes SourceFilSEO靠我e,LineNumberTable #保持泛型 -keepattributes Signature#保持所有实现 Serializable 接口的类成员 SEO靠我 -keepclassmembers class * implements java.io.Serializable {static final long serialVersionUID;privaSEO靠我te static final java.io.ObjectStreamField[] serialPersistentFields;private void writeObject(java.io.SEO靠我ObjectOutputStream);private void readObject(java.io.ObjectInputStream);java.lang.Object writeReplaceSEO靠我();java.lang.Object readResolve(); }#Fragment不需要在AndroidManifest.xml中注册,需要额外保护下 -keeSEO靠我p public class * extends android.support.v4.app.Fragment -keep public class * extends androiSEO靠我d.app.Fragment# 保持测试相关的代码 -dontnote junit.framework.** -dontnote junit.runner.** SEO靠我 -dontwarn android.test.** -dontwarn android.support.test.** -dontwarn org.junitSEO靠我.**

真正通用的、需要添加的就是上面这些,除此之外,需要每个项目根据自身的需求添加一些混淆规则:

第三方库所需的混淆规则。正规的第三方库一般都会在接入文档中写好所需混淆规则,使用时注意添加。

在运行时动态SEO靠我改变的代码,例如反射。比较典型的例子就是会与 json 相互转换的实体类。假如项目命名规范要求实体类都要放在model包下的话,可以添加类似这样的代码把所有实体类都保持住:-keep public cSEO靠我lass **.*Model*.** {*;}

JNI中调用的类。

WebView中JavaScript调用的方法

Layout布局使用的View构造函数、android:onClick等。

检查混淆结果

混淆SEO靠我过的包必须进行检查,避免因混淆引入的bug。

一方面,需要从代码层面检查。使用上文的配置进行混淆打包后在<module-name>/build/outputs/mapping/release/目录下会输SEO靠我出以下文件:

dump.txt

描述APK文件中所有类的内部结构

mapping.txt

提供混淆前后类、方法、类成员等的对照表

seeds.txt

列出没有被混淆的类和成员

usage.txt

列出被移除的代码

我们SEO靠我可以根据 seeds.txt 文件检查未被混淆的类和成员中是否已包含所有期望保留的,再根据 usage.txt文件查看是否有被误移除的代码。

另一方面,需要从测试方面检查。将混淆过的包进行全方面测试,检SEO靠我查是否有 bug 产生。

解出混淆栈

混淆后的类、方法名等等难以阅读,这固然会增加逆向工程的难度,但对追踪线上 crash 也造成了阻碍。我们拿到 crash 的堆栈信息后会发现很难定位,这时需要将混淆反SEO靠我解。

在 <sdk-root>/tools/proguard/路径下有附带的的反解工具(Window 系统为proguardgui.bat,Mac 或 Linux 系统为proguardgui.sh)。SEO靠我

这里以 Window 平台为例。双击运行 proguardgui.bat 后,可以看到左侧的一行菜单。点击 ReTrace,选择该混淆包对应的 mapping 文件(混淆后在 <module-nameSEO靠我>/build/outputs/mapping/release/ 路径下会生成 mapping.txt 文件,它的作用是提供混淆前后类、方法、类成员等的对照表),再将 crash 的 stack trSEO靠我ace 黏贴进输入框中,点击右下角的 ReTrace ,混淆后的堆栈信息就显示出来了。

以上使用 GUI 程序进行操作,另一种方式是利用该路径下的 retrace 工具通过命令行进行反解,命令是

retrSEO靠我ace.bat|retrace.sh [-verbose] mapping.txt [<stacktrace_file>]

例如:

retrace.bat -verbose mapping.txt obfSEO靠我uscated_trace.txt

注意事项:

所有在 AndroidManifest.xml 涉及到的类已经自动被保持,因此不用特意去添加这块混淆规则。(很多老的混淆文件里会加,现在已经没必要)

progSEO靠我uard-android.txt已经存在一些默认混淆规则,没必要在 proguard-rules.pro 重复添加

混淆简介

Android中的“混淆”可以分为两部分,一部分是Java 代码的优化与混淆,SEO靠我依靠 proguard混淆器来实现;另一部分是资源压缩,将移除项目及依赖的库中未被使用的资源(资源压缩严格意义上跟混淆没啥关系,但一般我们都会放一起用)。

代码压缩

代码混淆是包含了代码压缩、优化、混淆等SEO靠我一系列行为的过程。如上图所示,混淆过程会有如下几个功能:

压缩。移除无效的类、类成员、方法、属性等;

优化。分析和优化方法的二进制代码;根据proguard-android-optimize.txt中的描SEO靠我述,优化可能会造成一些潜在风险,不能保证在所有版本的Dalvik上都正常运行。

混淆。把类名、属性名、方法名替换为简短且无意义的名称;

预校验。添加预校验信息。这个预校验是作用在Java平台上的,AndrSEO靠我oid平台上不需要这项功能,去掉之后还可以加快混淆速度。

这四个流程默认开启。

在Android项目中我们可以选择将“优化”和“预校验”关闭,对应命令是-dontoptimize、-dontpreveriSEO靠我fy(当然,默认的 proguard-android.txt文件已包含这两条混淆命令,不需要开发者额外配置)。

资源压缩

资源压缩将移除项目及依赖的库中未被使用的资源,这在减少apk 包体积上会有不错的效SEO靠我果,一般建议开启。具体做法是在 build.grade文件中,将shrinkResources属性设置为true。需要注意的是,只有在用minifyEnabled true开启了代码压缩后,资源压缩才SEO靠我会生效。

资源压缩包含了“合并资源”和“移除资源”两个流程。

“合并资源”流程中,名称相同的资源被视为重复资源会被合并。需要注意的是,这一流程不受shrinkResources属性控制,也无法被禁止,grSEO靠我adle必然会做这项工作,因为假如不同项目中存在相同名称的资源将导致错误。gradle 在四处地方寻找重复资源:

src/main/res/ 路径

不同的构建类型(debug、release等等)

不同的构SEO靠我建渠道

项目依赖的第三方库

合并资源时按照如下优先级顺序 依赖 -> main -> 渠道 -> 构建类型

假如重复资源同时存在于main文件夹和不同渠道中,gradle 会选择保留渠道中的资源。

同时,如果重SEO靠我复资源在同一层次出现,比如src/main/res/ 和 src/main/res2/,则 gradle无法完成资源合并,这时会报资源合并错误。

“移除资源”流程则见名知意,需要注意的是,类似代码,混淆SEO靠我资源移除也可以定义哪些资源需要被保留,这点在下文给出。

自定义混淆规则

在上文“混淆配置”中有这样一行代码

proguardFiles getDefaultProguardFile(proguard-andSEO靠我roid.txt), proguard-rules.pro

这行代码定义了混淆规则由两部分构成:位于 SDK 的 tools/proguard/ 文件夹中的 proguard-android.txt 的SEO靠我内容以及默认放置于模块根目录的 proguard-rules.pro 的内容。前者是 SDK 提供的默认混淆文件,后者是开发者自定义混淆规则的地方。

常见的混淆指令

optimizationpassesdSEO靠我ontoptimizedontusemixedcaseclassnamesdontskipnonpubliclibraryclassesdontpreverifydontwarnverboseoptiSEO靠我mizationskeepkeepnameskeepclassmemberskeepclassmembernameskeepclasseswithmemberskeepclasseswithmembeSEO靠我rnames

更多详细的请到官网

需要特别介绍的是与保持相关元素不参与混淆的规则相关的几种命令:

命令作用-keep防止类和成员被移除或者被重命名-keepnames防止类和成员被重命名-keepclassSEO靠我members防止成员被移除或者被重命名-keepnames防止成员被重命名-keepclasseswithmembers防止拥有该成员的类和成员被移除或者被重命名-keepclasseswithmeSEO靠我mbernames防止拥有该成员的类和成员被重命名

保持元素不参与混淆的规则

[保持命令] [类] {[成员] }

“类”代表类相关的限定条件,它将最终定位到某些符合该限定条件的类。它的内容SEO靠我可以使用:

具体的类访问修饰符(public、protected、private)通配符*,匹配任意长度字符,但不含包名分隔符(.)通配符**,匹配任意长度字符,并且包含包名分隔符(.)extends,SEO靠我即可以指定类的基类implement,匹配实现了某接口的类$,内部类

“成员”代表类成员相关的限定条件,它将最终定位到某些符合该限定条件的类成员。它的内容可以使用:

匹配所有构造器 匹配所有域匹配所有方法通SEO靠我配符*,匹配任意长度字符,但不含包名分隔符(.)通配符**,匹配任意长度字符,并且包含包名分隔符(.)通配符***,匹配任意参数类型…,匹配任意长度的任意类型参数。比如void test(…)就能匹配SEO靠我任意 void test(String a) 或者是 void test(int a, String b) 这些方法。访问修饰符(public、protected、private)

举个例子,假如需要将SEO靠我com.biaobiao.test包下所有继承Activity的public类及其构造函数都保持住,可以这样写: -keep public class com.biaobiao.tesSEO靠我t.** extends Android.app.Activity {<init> }

常用自定义混淆规则

不混淆某个类 -keep public class com.biSEO靠我aobiao.example.Test { *; }

不混淆某个包所有的类

-keep class com.biaobiao.test.** { *; } }

不混淆某个类的子类

-keep SEO靠我public class * extends com.biaobiao.example.Test { *; }

不混淆所有类名中包含了“model”的类及其成员

-keep public class * SEO靠我extends com.biaobiao.example.Test { *; }

不混淆某个接口的实现

-keep class * implements com.biaobiao.example.TestSEO靠我Interface { *; }

不混淆某个类的构造方法

-keepclassmembers class com.biaobiao.example.Test { public <init>(); SEO靠我 }

不混淆某个类的特定的方法

-keepclassmembers class com.biaobiao.example.Test { public void test(java.lang.StriSEO靠我ng); } }

不混淆某个类的内部类

-keep class com.biaobiao.example.Test$* {*;}

自定义资源保持规则

1. keep.xml

用sSEO靠我hrinkResources true开启资源压缩后,所有未被使用的资源默认被移除。假如你需要定义哪些资源必须被保留,在 res/raw/ 路径下创建一个 xml 文件,例如keep.xml 。

通过一SEO靠我些属性的设置可以实现定义资源保持的需求,可配置的属性有:

keep 定义哪些资源需要被保留(资源之间用“,”隔开)discard 定义哪些资源需要被移除(资源之间用“,”隔开)shrinkMode 开启SEO靠我严格模式当代码中通过Resources.getIdentifier() 用动态的字符串来获取并使用资源时,普通的资源引用检查就可能会有问题。例如,如下代码会导致所有以“img_”开头的资源都被标记为已SEO靠我使用。

当代码中通过 Resources.getIdentifier() 用动态的字符串来获取并使用资源时,普通的资源引用检查就可能会有问题。例如,如下代码会导致所有以“img_”开头的资源都被标记为已SEO靠我使用。 String name = String.format("img_%1d", angle + 1); res = getResources().getIdentSEO靠我ifier(name, "drawable", getPackageName());

我们可以设置 tools:shrinkMode 为strict来开启严格模式,使只有确实被使用的资源被保留。

以上就是SEO靠我自定义资源保持规则相关的配置,举个例子:

<?xml version="1.0" encoding="utf-8"?> <resources xmlns:tools="http://scSEO靠我hemas.android.com/tools"tools:keep="@layout/l_used*_c,@layout/l_used_a,@layout/l_used_b*"tools:discaSEO靠我rd="@layout/unused2"tools:shrinkMode="strict"/>

移除替代资源

一些替代资源,例如多语言支持的 strings.xml,多分辨率支持的 layout.xml SEO靠我等,在我们不需要使用又不想删除掉时,可以使用资源压缩将它们移除。

我们使用 resConfig 属性来指定需要支持的属性,例如

一些替代资源,例如多语言支持的strings.xml,多分辨率支持的 laySEO靠我out.xml等,在我们不需要使用又不想删除掉时,可以使用资源压缩将它们移除。

我们使用 resConfig属性来指定需要支持的属性,例如

android {defaultConfig {...resCoSEO靠我nfigs "en", "fr"} }

其他未显式声明的语言资源将被移除。

最后附上一个我在实际项目中的混淆方案

proguard-android.txt文件内容

# 代码混淆压缩比,在0~7SEO靠我之间 -optimizationpasses 5 # 混合时不使用大小写混合,混合后的类名为小写 -dontusemixedcaseclassnamesSEO靠我 # 指定不去忽略非公共库的类 -dontskipnonpubliclibraryclasses # 不做预校验,preverify是proguard的SEO靠我四个步骤之一,Android不需要preverify,去掉这一步能够加快混淆速度。 -dontpreverify -verbose # 避免混淆泛型 SEO靠我 -keepattributes Signature# 保留Annotation不混淆 -keepattributes *Annotation*,InnerClasses SEO靠我 #google推荐算法 -optimizations !code/simplification/arithmetic,!code/simplification/castSEO靠我,!field/*,!class/merging/* # 避免混淆Annotation、内部类、泛型、匿名类 -keepattributes *Annotation*,SEO靠我InnerClasses,Signature,EnclosingMethod # 重命名抛出异常时的文件名称 -renamesourcefileattribute SoSEO靠我urceFile # 抛出异常时保留代码行号 -keepattributes SourceFile,LineNumberTable # 处理supporSEO靠我t包 -dontnote android.support.** -dontwarn android.support.** # 保留继承的 SEO靠我 -keep public class * extends android.support.v4.** -keep public class * extends android.supSEO靠我port.v7.** -keep public class * extends android.support.annotation.**# 保留R下面的资源 -keeSEO靠我p class **.R$* {*;} # 保留四大组件,自定义的Application等这些类不被混淆 -keep public class * extends anSEO靠我droid.app.Activity -keep public class * extends android.app.Appliction -keep public SEO靠我class * extends android.app.Service -keep public class * extends android.content.BroadcastReSEO靠我ceiver -keep public class * extends android.content.ContentProvider -keep public claSEO靠我ss * extends android.preference.Preference -keep public class com.android.vending.licensing.SEO靠我ILicensingService# 保留在Activity中的方法参数是view的方法, # 这样以来我们在layout中写的onClick就不会被影响 -keepcSEO靠我lassmembers class * extends android.app.Activity{public void *(android.view.View); } SEO靠我 # 对于带有回调函数的onXXEvent、**On*Listener的,不能被混淆 -keepclassmembers class * {void *(**On*Event);voiSEO靠我d *(**On*Listener); } # 保留本地native方法不被混淆 -keepclasseswithmembernames class *SEO靠我 {native <methods>; }# 保留枚举类不被混淆 -keepclassmembers enum * {public static **[] valuesSEO靠我();public static ** valueOf(java.lang.String); }# 保留Parcelable序列化类不被混淆 -keep class *SEO靠我 implements android.os.Parcelable {public static final android.os.Parcelable$Creator *; }-keSEO靠我epclassmembers class * implements java.io.Serializable {static final long serialVersionUID;private sSEO靠我tatic final java.io.ObjectStreamField[] serialPersistentFields;private void writeObject(java.io.ObjeSEO靠我ctOutputStream);private void readObject(java.io.ObjectInputStream);java.lang.Object writeReplace();jSEO靠我ava.lang.Object readResolve(); } #assume no side effects:删除android.util.Log输出的日志 SEO靠我 -assumenosideeffects class android.util.Log {public static *** v(...);public static *** d(...);SEO靠我public static *** i(...);public static *** w(...);public static *** e(...); } #保留KeeSEO靠我p注解的类名和方法 -keep,allowobfuscation @interface android.support.annotation.Keep -keep @aSEO靠我ndroid.support.annotation.Keep class * -keepclassmembers class * {@android.support.annotatioSEO靠我n.Keep *; } #3D 地图 V5.0.0之前:-dontwarn com.amap.api.** -dontwarn com.autonaviSEO靠我.** -keep class com.amap.api.**{*;} -keep class com.autonavi.**{*;}-keep class com.aSEO靠我map.api.maps.**{*;} -keep class com.autonavi.amap.mapcore.*{*;} -keep class com.amapSEO靠我.api.trace.**{*;}#3D 地图 V5.0.0之后: -keep class com.amap.api.maps.**{*;} -keep class cSEO靠我om.autonavi.**{*;} -keep class com.amap.api.trace.**{*;}#定位 -keep class com.amap.apiSEO靠我.location.**{*;} -keep class com.amap.api.fence.**{*;} -keep class com.autonavi.aps.SEO靠我amapapi.model.**{*;}#搜索 -keep class com.amap.api.services.**{*;}#2D地图 -keep class coSEO靠我m.amap.api.maps2d.**{*;} -keep class com.amap.api.mapcore2d.**{*;}#导航 -keep class coSEO靠我m.amap.api.navi.**{*;} -keep class com.autonavi.**{*;} # Retain generic type informaSEO靠我tion for use by reflection by converters and adapters. -keepattributes Signature# Retain serSEO靠我vice method parameters when optimizing. -keepclassmembers,allowshrinking,allowobfuscation inSEO靠我terface * {@retrofit2.http.* <methods>; }# Ignore annotation used for build tooling. SEO靠我 -dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement# Ignore JSR 305 annotations for embSEO靠我edding nullability information. -dontwarn javax.annotation.**# JSR 305 annotations are for eSEO靠我mbedding nullability information. -dontwarn javax.annotation.**# A resource is loaded with aSEO靠我 relative path so the package of this class must be preserved. -keepnames class okhttp3.inteSEO靠我rnal.publicsuffix.PublicSuffixDatabase# Animal Sniffer compileOnly dependency to ensure APIs are comSEO靠我patible with older versions of Java. -dontwarn org.codehaus.mojo.animal_sniffer.*# OkHttp plSEO靠我atform used only on JVM and when Conscrypt dependency is available. -dontwarn okhttp3.internSEO靠我al.platform.ConscryptPlatform#fastjson混淆 -keepattributes Signature -dontwarn com.aliSEO靠我baba.fastjson.** -keep class com.alibaba.**{*;} -keep class com.alibaba.fastjson.**{SEO靠我*; } -keep public class com.ninstarscf.ld.model.entity.**{*;}

所有文章参考

Shrink Your Code and ResoSEO靠我urcesproguardAndroid安全攻防战,反编译与混淆技术完全解析(下)Android混淆从入门到精通Android代码混淆之ProGuard

原文连接:Android 代码混淆 - EndvSEO靠我 - 博客园

“SEO靠我”的新闻页面文章、图片、音频、视频等稿件均为自媒体人、第三方机构发布或转载。如稿件涉及版权等问题,请与 我们联系删除或处理,客服邮箱:html5sh@163.com,稿件内容仅为传递更多信息之目的,不代表本网观点,亦不代表本网站赞同 其观点或证实其内容的真实性。

网站备案号:浙ICP备17034767号-2