2022

Android 混淆介绍

2020-08-13  本文已影响0人  mumuxi_

目录:
一、启用混淆文件
二、ProGuard作用
三、编辑混淆文件 (五步搞定)
四、常用混淆写法
五、其他一些混淆注意事项

一、启用混淆文件

开发中直接使用Android Studio即可实现启用混淆文件。Android Studio自身集成Java语言的ProGuard作为压缩,优化和混淆工具,配合Gradle构建工具使用很简单,只需要在工程应用目录的gradle文件中设置minifyEnabled为true即可。然后我们就可以到proguard-rules.pro文件中加入我们的混淆规则。

buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
}

二、ProGuard作用

三、编辑混淆文件(五步搞定)

1.第一步
打开项目中的proguard-rules.pro,将下面的代码复制进去。我的思路是将混淆分为2个主要部分

#-------------------------------------------定制化区域----------------------------------------------

#---------------------------------1.实体类---------------------------------

#-------------------------------------------------------------------------

#---------------------------------2.第三方包-------------------------------

#-------------------------------------------------------------------------

#---------------------------------3.与js互相调用的类------------------------

#-------------------------------------------------------------------------

#---------------------------------4.反射相关的类和方法-----------------------

#----------------------------------------------------------------------------

#-------------------------------------------基本不用动区域--------------------------------------------

#---------------------------------基本指令区----------------------------------

# 代码混淆压缩比,在0~7之间
-optimizationpasses 5

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

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

# 指定不忽略包可见的库类成员(字段和方法)。默认地,当解析库类的时候ProGuard会跳过这些类成员,项目类一般不会去引用它们。然而有的时候,程序里的类相当于库类存在于相同包。此时它们会引用他们的包可见的类成员。在这种情况下为了保持程序代码保持一致性去读取这些类的成员是有用的。
-dontskipnonpubliclibraryclassmembers

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

指定处理期间打印更多相关信息。
-verbose

-printmapping proguardMapping.txt

#指定要启用和禁用的优化,在更精细的水平。只有当优化适用。 混淆时采用的算法(google推荐,一般不改变)
-optimizations !code/simplification/cast,!field/*,!class/merging/*

# 避免混淆Annotation、内部类
-keepattributes *Annotation*,InnerClasses

# 避免混淆泛型
-keepattributes Signature

# 抛出异常时保留代码行号
-keepattributes SourceFile,LineNumberTable

#----------------------------------------------------------------------------

#---------------------------------默认保留区---------------------------------

-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 public class * extends android.view.View

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

-keep class android.support.** {*;}

-keepclasseswithmembernames class * {

    native <methods>;

}

-keepclassmembers class * extends android.app.Activity{

    public void *(android.view.View);

}

-keepclassmembers enum * {

    public static **[] values();

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

}

-keep public class * extends android.view.View{

    *** get*();

    void set*(***);

    public <init>(android.content.Context);

    public <init>(android.content.Context, android.util.AttributeSet);

    public <init>(android.content.Context, android.util.AttributeSet, int);

}

-keepclasseswithmembers class * {

    public <init>(android.content.Context, android.util.AttributeSet);

    public <init>(android.content.Context, android.util.AttributeSet, int);

}

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

}

-keep class **.R$* {

*;

}

-keepclassmembers class * {

    void *(**On*Event);

}

#----------------------------------------------------------------------------

#---------------------------------webview------------------------------------

-keepclassmembers class fqcn.of.javascript.interface.for.Webview {

   public *;

}

-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, jav.lang.String);

}

#----------------------------------------------------------------------------

2.第二步
理解完战略级思想后,我们开始第一部分补充-实体类。实体类由于涉及到与服务端的交互,各种gson的交互如此等等,是要保留的。将你项目中实体类都拎出来,用以下语法进行保留。如果项目本身就是一个sdk,那么需要不混淆需要直接提供给第三方使用的类。

#不混淆某个类
-keep public class com.mumuxi.example.Test { *; }

#不混淆某个包的所有类
-keep class 你的实体类所在的包.** { *; }
-keep class com.mumuxi.test.** { *; }

#不混淆某个类的内部类
keep class com.mumuxi.example.Test$* { *;}

当然你的实体类肯定不止这一个,请用上边的方式一一添加,如果你的实体类都在一个包下,那你就幸福了。

3.第三步
第2部分是第三方包。打开你的build.gradle文件,查看你用了哪些第三方的包。
我去他们的官网把已经写好的混淆copy下来。直接包含jar包的话,方式另外写。

整理Android最全的混淆规则大全(最新的开源框架混淆)
Android混淆配置总结-持续更新

4.第四步
第三部分与js互调的类,工程中没有直接跳过。一般你可以这样写

-keep class 你的类所在的包.** { *; }

5.第五步
第四部分与反射有关的类,工程中没有直接跳过。类的话直接这样

-keep class 你的类所在的包.** { *; }

四、常用混淆写法

keep 保留类和类中的成员,防止被混淆或被移除。
keepnames 保留类和类中的成员,防止被混淆,但当成员没有被引用时会被移除。
keepclassmembers 只保留类中的成员,防止被混淆或被移除。
keepclassmembernames 只类中的成员,防止被混淆,但当成员没有被引用时会被移除。
keepclasseswithmembers 保留类和类中的成员,防止被混淆或被移除。前提是指明的类中的成员必须存在。如果不存在,还是会被混淆。
keepclasseswithmembernames 保留类和类中的成员,防止被混淆,但当成员没有被引用时会被移除。前提是指明的类中的成员必须存在。如果不存在,还是会被混淆。

#不混淆某个类
-keep public class com.mumuxi.example.Test { *; }

#不混淆某个包的所有类
-keep class com.mumuxi.test.** { *; }

#不混淆某个类的子类
-keep public class * extends com.biaobiao.mumuxi.Test { *; }

#不混淆某个类的内部类
keep class com.mumuxi.example.Test$* { *;}

#不混淆某个接口的实现
-keep class * implements com.mumuxi.example.TestInterface { *; }

#不混淆某个类的构造方法
-keepclassmembers class com.mumuxi.example.Test { 
    public <init>(); 
}

#不混淆某个类的特定的方法
-keepclassmembers class com.mumuxi.example.Test { 
    public void test(java.lang.String); 
}

五、其他一些混淆注意事项

参考:
混淆必知必会
Android混淆精炼详解+常用库混淆+通用混淆模板

上一篇下一篇

猜你喜欢

热点阅读