Android混淆工具——Proguard实践

最近使用了一个非常高效和方便的混淆工具——Proguard,使用了这个工具混淆打包后,apk体积显著的减少了,而且反编译难度也加大了,所以写个博客记录一下这个混淆的过程。

先说说什么是Proguard吧。

Proguard介绍

官网的介绍是:ProGuard是一个免费的Java类文件缩小,优化,混淆和预验证的工具。它检测和删除未使用的类,字段,方法和属性;优化字节码并删除未使用的指令;它使用短的无意义的名称重命名剩余的类,字段和方法。所得到的应用程序和库更小,更快,并且更好地针对逆向工程进行优化。

而且Proguard已经集成在Android studio构建系统里了,可以通过简单的代码来实现构建apk的时候进行混淆打包。

Proguard使用

首先,我们需要在项目里的build.gradle文件里配置Proguard

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

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


    } 

可以看见,分别在releasedebug两种构建类型配置了Proguard,在debug配置是因为你可以直接编译测试你混淆的效果,是否有影响正常功能的使用。

shrinkResources 是去除无效的资源文件,压缩资源。

minifyEnabled 是开启混淆。

这是默认的Proguard配置,proguard-rules.pro是需要在你的项目里创建的文件,层级跟build.gradle文件一样的,当然你可以随意改他的文件名,只不过需要在配置代码里面跟着修改,其实这个文件就是Proguard的自定义配置文件,没有这个文件你构建是会报错的

proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

Proguard基本语法

-keep 不混淆类和成员或者被重命名

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

-keepclassmembers 不混淆成员被移除或者被重命名

-keepnames 防止成员被重命名

-keepclasseswithmembers 不混淆拥有该成员的类和成员或者被重命名

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

而且还支持通配符*

例如

不混淆某个类

-keep public class com.shadow.example.abc { *; }

不混淆某个包

-keep public class com.shadow.example.** { *; }

不混淆某个类的子类

-keep public class * extends com.shadow.exampl.abc { *; }

了解这些基本语法后,我们就来看一下自定义配置,没有自定义混淆配置的话会构建出错的。

Proguard自定义配置

接下来介绍一下自定义混淆配置

以下是我在项目里使用的配置,我会在注释里说明。

//--- 基础混淆配置 ---

-optimizationpasses 5  //指定代码的压缩级别

-allowaccessmodification  //优化时允许访问并修改有修饰符的类和类的成员

-dontusemixedcaseclassnames  //不使用大小写混合

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

-verbose    //混淆时是否记录日志

-ignorewarnings  //忽略警告,避免打包时某些警告出现,没有这个的话,构建报错

-optimizations !code/simplification/arithmetic,!code/simplification/cast,!field/*,!class/merging/*  //混淆时所采用的算法

-keepattributes *Annotation* //不混淆注解相关

-keepclasseswithmembernames class * {  //保持 native 方法不被混淆
    native <methods>;
}

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

//不混淆Parcelable 
-keep class * implements android.os.Parcelable {   
public static final android.os.Parcelable$Creator *;
}

//不混淆Serializable
-keep class * implements java.io.Serializable {*;}
-keepnames class * implements java.io.Serializable
-keepclassmembers class * implements java.io.Serializable {*;}



-keepclassmembers class **.R$* { //不混淆R文件
    public static <fields>;
}

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


-keepattributes Signature  //过滤泛型  出现类型转换错误时,启用这个


//--- 不能被混淆的基类 ---
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Fragment
-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 class org.xmlpull.v1.** { *; }



//--- 不混淆android-support-v4包 ---
-dontwarn android.support.v4.**
-keep class android.support.v4.** { *; }
-keep interface android.support.v4.app.** { *; }
-keep class * extends android.support.v4.** { *; }
-keep public class * extends android.support.v4.**
-keep public class * extends android.support.v4.widget
-keep class * extends android.support.v4.app.** {*;}
-keep class * extends android.support.v4.view.** {*;}
-keep public class * extends android.support.v4.app.Fragment


//不混淆继承的support类
-keep public class * extends android.support.v4.**
-keep public class * extends android.support.v7.**
-keep public class * extends android.support.annotation.**


//不混淆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(...);
}


//保持Activity中参数类型为View的所有方法
-keepclassmembers class * extends android.app.Activity {
          public void *(android.view.View);
    }



//--- 不混淆第三方库 这个可以去相关的第三方库官网找寻混淆代码 如果被混淆了会无法使用 ---
 
 
//Gson 
-keepattributes *Annotation*
-keep class sun.misc.Unsafe { *; }
-keep class com.idea.fifaalarmclock.entity.***
-keep class com.google.gson.stream.** { *; }
-keep class com.你的bean.** { *; }


//OkHttp3
-dontwarn okhttp3.logging.**
-keep class okhttp3.internal.**{*;}
-dontwarn okio.**


//Retrofit
-dontwarn retrofit2.**
-keep class retrofit2.** { *; }
-keepattributes Signature
-keepattributes Exceptions


//RxJava RxAndroid
-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;
}


//微信
 -keep class com.tencent.mm.** {*;}


//Glide图片库
 -keep class com.bumptech.glide.**{*;}


 //友盟
 -keepclassmembers class * {
         public <init> (org.json.JSONObject);
 }

 -keep class com.umeng.onlineconfig.OnlineConfigAgent {
         public <fields>;
         public <methods>;
 }

 -keep class com.umeng.onlineconfig.OnlineConfigLog {
         public <fields>;
         public <methods>;
 }

 -keep interface com.umeng.onlineconfig.UmengOnlineConfigureListener {
         public <methods>;
 }


//Testin
-dontwarn com.testin.agent.**
-keep class com.testin.agent.** {*;}


//--- 一些特殊的混淆配置 ---


 //有用到WEBView的JS调用接口不被混淆
-keepclassmembers class fqcn.of.javascript.interface.for.webview {
        public *;
   }


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


//抛出异常时保留代码行号 方便测试
-keepattributes SourceFile,LineNumberTable


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




你用了以上的配置文件,我相信大部分项目都是没有问题的

在初次使用Proguard实现混淆配置的时候,会出现很多很多的坑,如果遇上了问题,可以通过报错信息去谷歌一下,有可能会有很多你没想到遗漏,一开始我也是踩了好多坑。。

不过,通过努力还是可以完成这个混淆实践的,混淆后的apk体积会让你惊讶的!

值得试试

最后

这是一个简单的Proguard混淆实践,记录一下思路。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,711评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,932评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,770评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,799评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,697评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,069评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,535评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,200评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,353评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,290评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,331评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,020评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,610评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,694评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,927评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,330评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,904评论 2 341

推荐阅读更多精彩内容