Android之app混淆深入分析-层层解析解决开发中痛点

783 阅读3分钟

前言

在应用发布前,就需要对代码进行混淆处理,从而让我们代码即使被反编译,也难以阅读; 很多人不知道怎么设置混淆,哪些不需要混淆,那来了老铁们,可以直接拿来用的知识点。

Android之OkHttp网络架构源码深入分析(揭开神秘的面纱)

AS中混淆配置

在AS中可以通过配置proguard-rules.pro文件,对生成的apkjar进行加密,另外还需要配置项目中 app下的 build.gradle 来开启混淆功能。

AS中项目混淆配置

gradle中代码如下,直接拿来用

buildTypes {
        debug {         
            minifyEnabled false // 混淆  
            zipAlignEnabled true // Zipalign优化 
            shrinkResources true // 移除无用的resource文件    
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'  // 加载默认混淆配置文件  
            signingConfig signingConfigs.debug // 签名
        }
        release {                      
            minifyEnabled true // 混淆            
            zipAlignEnabled true // Zipalign优化          
            shrinkResources true  // 移除无用的resource文件           
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'  // 加载默认混淆配置文件
            signingConfig signingConfigs.relealse  // 签名
        }
    }

规则

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

  1. 自定义控件不进行混淆
  2. 枚举类不被混淆
  3. 反射类不进行混淆
  4. 实体类不被混淆
  5. JS调用的Java方法
  6. 四大组件不进行混淆
  7. JNI中调用类不进行混淆
  8. Layout布局使用的View构造函数、android:onClick
  9. Parcelable的子类和Creator静态成员变量不混淆

混淆文件内容

基本混淆指令

# 设置混淆的压缩比率 0 ~ 7
-optimizationpasses 5  
# 混淆时不使用大小写混合,混淆后的类名为小写
-dontusemixedcaseclassnames  
# 指定不去忽略非公共库的类
-dontskipnonpubliclibraryclasses
# 指定不去忽略非公共库的成员
-dontskipnonpubliclibraryclassmembers 
# 混淆时不做预校验
-dontpreverify           
# 混淆时不记录日志
-verbose             
# 忽略警告
-ignorewarning          
# 代码优化
-dontshrink  
# 不优化输入的类文件                
-dontoptimize 
# 保留注解不混淆             
-keepattributes *Annotation*,InnerClasses
# 避免混淆泛型
-keepattributes Signature  
# 保留代码行号,方便异常信息的追踪
-keepattributes SourceFile,LineNumberTable  
# 混淆采用的算法
-optimizations !code/simplification/cast,!field/*,!class/merging/*  

# dump.txt文件列出apk包内所有class的内部结构
-dump class_files.txt        
# seeds.txt文件列出未混淆的类和成员
-printseeds seeds.txt
# usage.txt文件列出从apk中删除的代码
-printusage unused.txt
# mapping.txt文件列出混淆前后的映射
-printmapping mapping.txt

不需混淆的Android类

support design库、support下的所有类及其内部类、Android类

-keep public class * extends android.app.Fragment
-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.preference.Preference
-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.** {*;}
-dontwarn android.support.**
-keep interface android.support.** { *; }

-keep class androidx.** {*;}
-keep interface androidx.** {*;}
-keep public class * extends androidx.**
-dontwarn androidx.**

-dontwarn android.support.design.**
-keep class android.support.design.** { *; }
-keep interface android.support.design.** { *; }
-keep public class android.support.design.R$* { *; }

-keep class com.google.android.material.** {*;}
-dontwarn com.google.android.material.**
-dontnote com.google.android.material.**

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

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

关闭 Log日志

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

避免资源混淆

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

避免layout中onclick方法

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

避免混淆枚举类

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

Natvie 方法不混淆

-keepclasseswithmembernames class * {
    native <methods>;
}

避免Parcelable混淆和Serializable接口

-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;
    !static !transient <fields>;
    private void writeObject(java.io.ObjectOutputStream);
    private void readObject(java.io.ObjectInputStream);
    java.lang.Object writeReplace();
    java.lang.Object readResolve();
}

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);
}
-keep public class [包名.类名]$[内部类]{
    public *;
}
-keepattributes JavascriptInterface

网络框架OkHttp3混淆配置

-dontwarn com.squareup.okhttp3.**
-keep class com.squareup.okhttp3.** { *;}
-dontwarn okio.**

想了解更多Android开发知识点,请关注订阅,多谢

完工,有问题评论

公共号【Android开发编程