Android Proguard 混淆文件的规则及使用

傅玮
2023-12-01

Android Proguard 混淆文件的规则及使用

原文:https://blog.csdn.net/ljd2038/article/details/51308768

简介

一个能够 压缩优化混淆整个项目代码的配置文件,可以通过配置,删除项目中的移除无用代码减小apk体积、通过使用无意义的名称重命名类、字段和方法,达到混淆的作用,防止反编译,使得apk更不容易进行逆向工程。

原理

ProGuard能够对Java类中的代码进行压缩(Shrink),优化(Optimize),混淆(Obfuscate),预检(Preveirfy)。
  1. 压缩(Shrink):用于检测和删除没有使用的类,字段,方法和属性。
  2. 优化(Optimize):对字节码进行优化,并且移除无用指令。
  3. 混淆(Obfuscate):使用a,b,c等无意义的名称,对类,字段和方法进行重命名。
  4. 预检(Preveirfy):主要是在Java平台上对处理后的代码进行预检。

特别注意

为了确保开发后期可以正常生成release 版本的apk,尽量在平时开发过程中,虽然输出地是debug版本的apk,但可以提前将proguard配置好,并且,在debug版本中也开启混淆,这样在不断进行开发的过程中就可以发现问题。

使用

  1. 前提:在项目中已经默认配置了 proguard-rules.pro文件。只需在使用的时候找到并进行修改即可
  2. 使用
    开启混淆 minifyEnable : true (打开app.build(app)设置)
    buildTypes {
    release {
       minifyEnabled true
       proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
    
    配置混淆 系统默认的混淆文件为:proguard-android.txt。我们只需配置proguard-rules.pro即可。
    注意:每个项目由于目录不同,所以,每次都需要额外进行修改部分混淆文件,比如登陆的lib,实体类,R文件,基本上需要修改包名的地方都需要继续修改。
    打开 app/proguard-rules.pro

# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in D:\Tools\AndroidSDK/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
#   http://developer.android.com/guide/developing/tools/proguard.html

# Add any project specific keep options here:

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
#   public *;
#}

# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable

# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

####################基本配置#####################

#指定压缩级别(在0~7之间,默认为5,一般不需要更改)
-optimizationpasses 5

#不跳过非公共的库的类成员
-dontskipnonpubliclibraryclassmembers

#指定不去忽略非公共的库的类 (默认跳过,有些情况下编写的代码与类库中的类在同一个包下,并且持有包内容的引用,此时就需要提示不跳过)
-dontskipnonpubliclibraryclasses

#混合时采用的算法(一般不改变)
-optimizations !code/simplification/arithmetic,!filed\/*,!class/merging \/*

#混淆时不使用大小写混合,混淆后的类名为小写(大小写混淆容易导致class文件相互覆盖)
-dontusemixedcaseclassnames

#不做预检验,preverify是proguard的四大步骤之一,可以加快混淆速度
-dontpreverify

#混淆后生成映射文件
-verbose
-printmapping proguardMapping.txt

#保护代码中的Annotation不被混淆(这在Json实体映射是非常重要,例如FastJson)
-keepattributes *Annotation*

#避免混淆泛型,
#这在JSON实体映射时非常重要,比如fastJson
-keepattribute Signature

#保留本地方法不被混淆
-keepclasseswithmembernames class * {
		native <method>;
		}



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

#忽略警告 (慎用)
-ignorewarnings



#输出apk包内所有的class的内部结构
-dump class_files.txt
#未混淆的类和成员
-printseeds seeds.txt
#列出从apk中删除的代码
-printusage unused.txt
=


#======================项目配置=======================
#保留所有的本地native方法不被混淆
-keepclasseswithmembernames class *{
    native <methods>;
 }
 #保留继承自Activity、Application这些类的子类
 -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.app.BroadcastReceiver
 -keep public class * extends android.app.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

#如果有引用android-support-v4.jar包,可以添加下面这行
-keep public class xxx(包名).fragment.**{*;}

#保留在Activity中的方法参数是view的方法
#从而我们在layout里面编写onClick就不会被影响
-keepclassmembers class * extends android.app.Activity{
	public void *(android.view.View);
	}

 -keep public class * extends android.database.sqlite.SQLiteOpenHelper{*;}
 -keepnames class * extends android.view.View
 -keep class * extends android.app.Fragment {
     public void setUserVisibleHint(boolean);
     public void onHiddenChanged(boolean);
     public void onResume();
     public void onPause();
 }
 -keep class android.support.v4.app.Fragment {
     public void setUserVisibleHint(boolean);
     public void onHiddenChanged(boolean);
     public void onResume();
     public void onPause();
 }
 -keep class * extends android.support.v4.app.Fragment {
     public void setUserVisibleHint(boolean);
     public void onHiddenChanged(boolean);
     public void onResume();
     public void onPause();
 }

 
 #如果引用v4或者v7包
 -dontwarn android.support.**
 #以防onClick不被影响,保留Activity中包含view的方法
 -keepclasseswithmembers class * extends android.app.Activity{
    public void * (android.view.View);
 }
 #枚举类不能被混淆
 -keepclassmembers enum *{
    public static **[] values();
    public static ** valueOf(java.lang.String);
    }

 #保留自定义控件不能被混淆(即继承自View)不能被混淆
 -keep public class * extends android.view.View{
    public <int>(android.content.Context);
    public <int>(android.content.Context,android.util.AttributeSet);
    public <int>(android.content.Context,android.util.AttributeSet,int);
    public void set*(***);
    *** get*();
    }

  #保留Parcelable序列化的类不能被混淆
  -keep class * implements android.os.Parcelable{
    public static final android.os.Parcelable$Creator *;
    }

  #保留Serializable序列化的类不能被混淆
  -keepclassmembers class * implements java.io.Serializable{
    static final long serialVersionUID;
    private static final java.io.ObjectStreamFiled[] serialPersistentFields;
    !static !transient <fields>;
    private void writeObject(java.io.ObjectOutputStream);
    private void readObject(java.io.ObjectInputStream);
    java.lang.Object writeReplace();
    java.lang.Object readResolve();
}
   #对R文件下的所有类及其方法都不能混淆
   -keep class class **.R$*{
        *;
   }
   
   #对于回调函数onXXEvent的,不能被混淆
   -keepclassmembers class * {
   void *(**Event);
   }





   #第三方框架的混淆
  #okhttp
  -keep class com.squareup.okhttp.** { *;}
  -dontwarn okio.**
  -keepclassmembers class **.R$* {
      public static <fields>;
  }
  #eventbus
  -keepattributes *Annotation*
  -keepclassmembers class ** {
      @org.greenrobot.eventbus.Subscribe <methods>;
  }
  -keep enum org.greenrobot.eventbus.ThreadMode { *; }
  # Only required if you use AsyncExecutor
  -keepclassmembers class * extends org.greenrobot.eventbus.util.ThrowableFailureEvent {
      <init>(java.lang.Throwable);
  }
  #retroift
  -dontwarn retrofit2.**
  -keep class retrofit2.** { *; }
  -keepattributes Signature
  -keepattributes Exceptions

  #ButterKnife
  -keep class butterknife.** { *; }
  -dontwarn butterknife.internal.**
  -keep class **$$ViewBinder { *; }

  -keepclasseswithmembernames class * {
      @butterknife.* <fields>;
  }

  -keepclasseswithmembernames class * {
      @butterknife.* <methods>;
  }

  #fastjson
  -dontwarn com.alibaba.fastjson.**
  -keep class com.alibaba.fastjson.** { *; }

  #rxjava
  -dontwarn sun.misc.**
  -keepclassmembers class rx.internal.util.unsafe.*ArrayQueue*Field* {
   long producerIndex;
   long consumerIndex;
  }
  -keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueProducerNodeRef {
   rx.internal.util.atomic.LinkedQueueNode producerNode;
  }
  -keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueConsumerNodeRef {
   rx.internal.util.atomic.LinkedQueueNode consumerNode;
  }
#Facebook
-keep class com.facebook.** {*;}
-keep interface com.facebook.** {*;}
-keep enum com.facebook.** {*;}

#Fresco
-keep class com.facebook.fresco.** {*;}
-keep interface com.facebook.fresco.** {*;}
-keep enum com.facebook.fresco.** {*;}
  #友盟分享
  -dontwarn com.google.android.maps.**
  -dontwarn android.webkit.WebView
  -dontwarn com.umeng.**
  -dontwarn com.tencent.weibo.sdk.**
  -dontwarn com.facebook.**
  -keep public class javax.**
  -keep public class android.webkit.**
  -dontwarn android.support.v4.**
  -keep class android.support.** {*;}
  -keep enum com.facebook.**
  -keepattributes Exceptions,InnerClasses,Signature
  -keepattributes *Annotation*
  -keepattributes SourceFile,LineNumberTable
  -keep public interface com.facebook.**
  -keep public interface com.tencent.**
  -keep public interface com.umeng.socialize.**
  -keep public interface com.umeng.socialize.sensor.**
  -keep public interface com.umeng.scrshot.**
   
    #对引入的webview不能进行混
    -keepclassmembers class 自己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,java.lang.String);
   }
	
	#对JavaScript的处理 需要将js使用到的原生方法不被混淆
	-keepclassmembers class xxx.xxx.xxx.xxActivity$Jsxx{
	<method>;
	}

    #包含反射的处理
    -keep class 自己的反射类的包.** {*;}

################################### -项目自定义- #######################################
   #保留实体类和成员不被混淆
   -keep public class 自己实体包名.bean.**{
	public void set*(***);
	public  *** get*();
	public *** is*();
  }
   
   #保留内部类 $是区别内嵌类与其母体的标志
   -keep class com.xxx.xxx.xxxActivity$*{ *; }
   

proguard配置详解

基本配置
#代码混淆压缩比,在0~7之间,默认为5,一般不做修改
-optimizationpasses 5

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

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

#这句话能够使我们的项目混淆后产生映射文件
#包含有类名->混淆后类名的映射关系
-verbose

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

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

#保留Annotation不混淆
-keepattributes *Annotation*,InnerClasses

#避免混淆泛型
-keepattributes Signature

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

#指定混淆是采用的算法,后面的参数是一个过滤器
#这个过滤器是谷歌推荐的算法,一般不做更改
-optimizations !code/simplification/cast,!field/* !class/merging/*

设置需要保留的地方

#保留我们使用的四大组件,自定义的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.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

#保留support下的所有类及其内部类
-keep class android.support.** {*;}

-libraryjars libs/android-support-v4.jar
-dontwarn android.support.v4 **
-keep class android.support.v4.** { *; }
-keep interface android.support.v4.app.*** { *; }
-keep public class * extends android.support.v4.**
-keep public class * extends android.app.Fragment

#

#保留R下面的资源
-keep class **.R$* {*;}

#保留本地native方法不被混淆
-keepclasseswithmembernames class * {
    native <methods>;
}

#保留在Activity中的方法参数是view的方法,
#这样以来我们在layout中写的onClick就不会被影响
-keepclassmembers class * extends android.app.Activity{
    public void *(android.view.View);
}

#保留枚举类不被混淆
-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}

#保留我们自定义控件(继承自View)不被混淆
-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);
}

#保留Parcelable序列化类不被混淆
-keep class * implements android.os.Parcelable {
  public static final android.os.Parcelable$Creator *;
}

#保留Serializable序列化的类不被混淆
-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();
}

#对于带有回调函数的onXXEvent的,不能被混淆
-keepclassmembers class * {
    void *(**On*Event);
}
 

不能混淆的几类代码

  1. 实体类不能混淆
-keep public class 自己存放实体的包.** {
   public void set*(***);
   public *** get*();
   public *** is*();
}
  1. 使用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);
}
  1. 包含html5与javascript交互的地方
-keepclassmembers class com.ljd.example.JSInterface {
   <methods>;
}
  1. 含有反射的类的处理
-keep class 类所在的包.** { *; }

打包注意
在开启混淆并打包的过程中,会输出大量的warning信息,如果没有错误,可以将此信息进行忽略,采用 java -dontwarn 产生waning信息的包.的方式,不要直接使用 java -ignorewarnings这样的语句,会直接忽略很多信息,潜在风险。

Proguard开发手册

 类似资料: