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版本中也开启混淆,这样在不断进行开发的过程中就可以发现问题。
使用
- 前提:在项目中已经默认配置了 proguard-rules.pro文件。只需在使用的时候找到并进行修改即可
- 使用:
①开启混淆 minifyEnable : true (打开app.build(app)设置)
②配置混淆 系统默认的混淆文件为:proguard-android.txt。我们只需配置proguard-rules.pro即可。buildTypes { release { minifyEnabled true proguardFiles getDefaultProguardFile('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);
}
不能混淆的几类代码
- 实体类不能混淆
-keep public class 自己存放实体的包.** {
public void set*(***);
public *** get*();
public *** is*();
}
- 使用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);
}
- 包含html5与javascript交互的地方
-keepclassmembers class com.ljd.example.JSInterface {
<methods>;
}
- 含有反射的类的处理
-keep class 类所在的包.** { *; }
打包注意
在开启混淆并打包的过程中,会输出大量的warning信息,如果没有错误,可以将此信息进行忽略,采用 java -dontwarn 产生waning信息的包.
的方式,不要直接使用 java -ignorewarnings
这样的语句,会直接忽略很多信息,潜在风险。