Android 代码混淆 混淆方案,熬了整整30天

Android 代码混淆 混淆方案,熬了整整30天,第1张

Android 代码混淆 混淆方案,熬了整整30天

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

常见的混淆指令

=======

  • optimizationpasses

  • dontoptimize

  • dontusemixedcaseclassnames

  • dontskipnonpubliclibraryclasses

  • dontpreverify

  • dontwarn

  • verbose

  • optimizations

  • keep

  • keepnames

  • keepclassmembers

  • keepclassmembernames

  • keepclasseswithmembers

  • keepclasseswithmembernames

更多详细的请到官网

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

| 命令 | 作用 |

| — | — |

| -keep | 防止类和成员被移除或者被重命名 |

| -keepnames | 防止类和成员被重命名 |

| -keepclassmembers | 防止成员被移除或者被重命名 |

| -keepnames | 防止成员被重命名 |

| -keepclasseswithmembers | 防止拥有该成员的类和成员被移除或者被重命名 |

| -keepclasseswithmembernames | 防止拥有该成员的类和成员被重命名 |

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


[保持命令] [类] {

[成员]

}

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

  • 访问修饰符(public、protected、private)

  • 通配符*,匹配任意长度字符,但不含包名分隔符(.)

  • 通配符**,匹配任意长度字符,并且包含包名分隔符(.)

  • extends,即可以指定类的基类

  • implement,匹配实现了某接口的类

  • $,内部类

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

  • 匹配所有域

  • 匹配所有方法

  • 通配符*,匹配任意长度字符,但不含包名分

《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》

【docs.qq.com/doc/DSkNLaERkbnFoS0ZF】 完整内容开源分享

隔符(.)

  • 通配符**,匹配任意长度字符,并且包含包名分隔符(.)

  • 通配符***,匹配任意参数类型

  • …,匹配任意长度的任意类型参数。比如void test(…)就能匹配任意 void test(String a) 或者是 void test(int a, String b) 这些方法。

  • 访问修饰符(public、protected、private)

举个例子,假如需要将com.biaobiao.test包下所有继承Activity的public类及其构造函数都保持住,可以这样写:

-keep public class com.biaobiao.test.** extends Android.app.Activity {

}

常用自定义混淆规则


  • 不混淆某个类

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

不混淆某个包所有的类

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

}

不混淆某个类的子类

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

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

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

不混淆某个接口的实现

-keep class * implements com.biaobiao.example.TestInterface { *; }

不混淆某个类的构造方法

-keepclassmembers class com.biaobiao.example.Test {

public ();

}

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

-keepclassmembers class com.biaobiao.example.Test {

public void test(java.lang.String);

}

}

不混淆某个类的内部类

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

*;

}

自定义资源保持规则


1. keep.xml

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

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

  • keep 定义哪些资源需要被保留(资源之间用“,”隔开)

  • discard 定义哪些资源需要被移除(资源之间用“,”隔开)

  • shrinkMode 开启严格模式

  • 当代码中通过Resources.getIdentifier() 用动态的字符串来获取并使用资源时,普通的资源引用检查就可能会有问题。例如,如下代码会导致所有以“img_”开头的资源都被标记为已使用。

当代码中通过 Resources.getIdentifier() 用动态的字符串来获取并使用资源时,普通的资源引用检查就可能会有问题。例如,如下代码会导致所有以“img_”开头的资源都被标记为已使用。

String name = String.format(“img_%1d”, angle + 1);

res = getResources().getIdentifier(name, “drawable”, getPackageName());

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

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

tools:keep="@layout/l_used*_c,@layout/l_used_a,@layout/l_used_b*"

tools:discard="@layout/unused2"

tools:shrinkMode=“strict”/>

移除替代资源


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

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

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

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

android {

defaultConfig {

resConfigs “en”, “fr”

}

}

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

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

==================

proguard-android.txt文件内容

代码混淆压缩比,在0~7之间

-optimizationpasses 5

混合时不使用大小写混合,混合后的类名为小写

-dontusemixedcaseclassnames

指定不去忽略非公共库的类

-dontskipnonpubliclibraryclasses

不做预校验,preverify是proguard的四个步骤之一,Android不需要preverify,去掉这一步能够加快混淆速度。

-dontpreverify

-verbose

避免混淆泛型

-keepattributes Signature

保留Annotation不混淆

-keepattributes Annotation,InnerClasses

#google推荐算法

-optimizations !code/simplification/arithmetic,!code/simplification/cast,!field/,!class/merging/

避免混淆Annotation、内部类、泛型、匿名类

-keepattributes Annotation,InnerClasses,Signature,EnclosingMethod

重命名抛出异常时的文件名称

-renamesourcefileattribute SourceFile

抛出异常时保留代码行号

-keepattributes SourceFile,LineNumberTable

处理support包

-dontnote android.support.**

-dontwarn android.support.**

保留继承的

-keep public class * extends android.support.v4.**

-keep public class * extends android.support.v7.**

-keep public class * extends android.support.annotation.**

保留R下面的资源

-keep class *.R$ {*;}

保留四大组件,自定义的Application等这些类不被混淆

-keep public class * extends android.app.Activity

-keep public class * extends android.app.Appliction

-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.preference.Preference

-keep public class com.android.vending.licensing.ILicensingService

保留在Activity中的方法参数是view的方法, 这样以来我们在layout中写的onClick就不会被影响

-keepclassmembers class * extends android.app.Activity{

public void *(android.view.View);

}

对于带有回调函数的onXXEvent、**On*Listener的,不能被混淆

-keepclassmembers class * {

void (**OnEvent);

void (**OnListener);

}

保留本地native方法不被混淆

-keepclasseswithmembernames class * {

native ;

}

保留枚举类不被混淆

-keepclassmembers enum * {

public static **[] values();

public static ** valueOf(java.lang.String);

}

保留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();

}

#assume no side effects:删除android.util.Log输出的日志

-assumenosideeffects class android.util.Log {

public static *** v(…);

public static *** d(…);

public static *** i(…);

public static *** w(…);

public static *** e(…);

}

#保留Keep注解的类名和方法

-keep,allowobfuscation @interface android.support.annotation.Keep

-keep @android.support.annotation.Keep class *

-keepclassmembers class * {

@android.support.annotation.Keep *;

}

#3D 地图 V5.0.0之前:

-dontwarn com.amap.api.**

-dontwarn com.autonavi.**

-keep class com.amap.api.**{*;}

-keep class com.autonavi.**{*;}

-keep class com.amap.api.maps.**{*;}

-keep class com.autonavi.amap.mapcore.{;}

-keep class com.amap.api.trace.**{*;}

#3D 地图 V5.0.0之后:

-keep class com.amap.api.maps.**{*;}

-keep class com.autonavi.**{*;}

-keep class com.amap.api.trace.**{*;}

#定位

-keep class com.amap.api.location.**{*;}

-keep class com.amap.api.fence.**{*;}

-keep class com.autonavi.aps.amapapi.model.**{*;}

#搜索

-keep class com.amap.api.services.**{*;}

#2D地图

-keep class com.amap.api.maps2d.**{*;}

-keep class com.amap.api.mapcore2d.**{*;}

#导航

-keep class com.amap.api.navi.**{*;}

-keep class com.autonavi.**{*;}

Retain generic type information for use by reflection by converters and adapters.

-keepattributes Signature

Retain service method parameters when optimizing.

-keepclassmembers,allowshrinking,allowobfuscation interface * {

@retrofit2.http.* ;

}

Ignore annotation used for build tooling.

-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement

Ignore JSR 305 annotations for embedding nullability information.

-dontwarn javax.annotation.**

JSR 305 annotations are for embedding nullability information.

-dontwarn javax.annotation.**

A resource is loaded with a relative path so the package of this class must be preserved.

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5684013.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存