前言

正常一个APP都会开启混淆,但是有时后接手的项目并没有开启混淆,然后自己修改的时候就很蛋疼,因为开启混淆便会报错,如果有一些没有用过的第三方库更要自己去处理,这里就记录一下安卓常见的混淆文件和常规用法。

混淆好处以及哪些是不能混淆的

面试常问混淆好处,我们张口就来:

  • 打包时会去掉无用资源有效减少APK体积(尤其对一些开发不规范导致很多无效代码和资源文件)其实这也可以变向的解决64k问题
  • 增加反编译成本,有效提高APK安全性(其实很多APK都会用第三方加密工具如360、爱加密)

但是并不是什么都可以混淆的:(具体配置代码都有)

- 实体类
 - 序列化对象
 - 反射
 - 枚举
 - resource
 - native方法(像java调用c++)
 - 一些自定义控件
 - Gson对象

开启混淆

buildTypes {
        debug {
            // 显示Log
            buildConfigField "boolean", "LOG_DEBUG", "true"

            minifyEnabled false//是否开启混淆
            zipAlignEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'//加载的混淆文件
            signingConfig signingConfigs.debug
        }
        release {
            // 不显示Log
            buildConfigField "boolean", "LOG_DEBUG", "false"

            minifyEnabled true//是否开启混淆
            zipAlignEnabled true
            // 移除无用的resource文件
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'//混淆文件位置
            signingConfig signingConfigs.release
        }
    }

可以看到其实是否开启混淆通过:

minifyEnabled true//是否开启混淆
proguardFiles getDefaultProguardFile(‘proguard-android.txt’), ‘proguard-rules.pro’//混淆文件位置

但是你开启混淆会打包很慢的所以这里一定要区分当前打包模式是:debug还是release,一般debug打包提供测试用,我们不会开启混淆。

如何打签名包

通过AS工具面板Build ---->Generate Singned Bundle or APK

我们选择apk后,输入好签名密码:

android 混淆 json android 混淆文件_android 混淆 json

这里如果你设置渠道包的话会选择当前渠道,我这就简单选择release点击finish便可。

混淆文件配置

重头戏来啦,在android中常用的混淆文件(可以复制我这个常用的然后再添加)

指定代码的压缩级别
-optimizationpasses 5
#包明不混合大小写
-dontusemixedcaseclassnames
#不去忽略非公共的库类
-dontskipnonpubliclibraryclasses
 #优化  不优化输入的类文件
-dontoptimize
 #预校验
-dontpreverify
 #混淆时是否记录日志
-verbose
 # 混淆时所采用的算法
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
#保护注解
-keepattributes *Annotation*
#如果有引用v4包可以添加下面这行
-keep public class * extends android.support.v4.app.Fragment
#忽略警告
-ignorewarning
##记录生成的日志数据,gradle build时在本项目根目录输出##
#apk 包内所有 class 的内部结构
-dump proguard/class_files.txt
#未混淆的类和成员
-printseeds proguard/seeds.txt
#列出从 apk 中删除的代码
-printusage proguard/unused.txt
#混淆前后的映射
-printmapping proguard/mapping.txt
########记录生成的日志数据,gradle build时 在本项目根目录输出-end######
#如果引用了v4或者v7包
-dontwarn android.support.**
#保持 native 方法不被混淆
-keepclasseswithmembernames class * {
    native <methods>;
}

#保持自定义控件类不被混淆
-keepclasseswithmembers class * {
    public <init>(android.content.Context, android.util.AttributeSet);
}
-keepclasseswithmembers class * {
    public <init>(android.content.Context, android.util.AttributeSet, int);
}

#保持自定义控件类不被混淆
-keepclassmembers class * extends android.app.Activity {
   public void *(android.view.View);
}

-keep public class * extends android.view.View {
    public <init>(android.content.Context);
    public <init>(android.content.Context, android.util.AttributeSet);
    public <init>(android.content.Context, android.util.AttributeSet, int);
    public void set*(...);
}

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

#保持 Serializable 不被混淆
-keepnames class * implements java.io.Serializable

#保持 Serializable 不被混淆并且enum 类也不被混淆
-keepclassmembers class * implements java.io.Serializable {
    static final long serialVersionUID;
    private static final java.io.ObjectStreamField[] serialPersistentFields;
    !static !transient <fields>;
    !private <fields>;
    !private <methods>;
    private void writeObject(java.io.ObjectOutputStream);
    private void readObject(java.io.ObjectInputStream);
    java.lang.Object writeReplace();
    java.lang.Object readResolve();
}

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

-keepclassmembers class * {
    public void *ButtonClicked(android.view.View);
}

#不混淆资源类
-keepclassmembers class **.R$* {
    public static <fields>;
}

#避免混淆泛型 如果混淆报错建议关掉
-keepattributes Signature

#移除Log类打印各个等级日志的代码,打正式包的时候可以做为禁log使用,这里可以作为禁止log打印的功能使用,另外的一种实现方案是通过BuildConfig.DEBUG的变量来控制
#-assumenosideeffects class android.util.Log {
#    public static *** v(...);
#    public static *** i(...);
#    public static *** d(...);
#    public static *** w(...);
#    public static *** e(...);
#}

#-------------------------------------------定制化区域----------------------------------------------
#---------------------------------1.实体类---------------------------------
-keep class 自己项目的包名.bean.** { *; }

#########################################################第三方的配置开始#######################
############shareSDK混淆配置################
-keep class cn.sharesdk.**{*;}
-keep class com.sina.**{*;}
-keep class **.R$* {*;}
-keep class **.R{*;}
-keep class com.mob.**{*;}
#####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);
}

###########极光混淆配置
-dontoptimize
-dontpreverify

-dontwarn cn.jpush.**
-keep class cn.jpush.** { *; }
-keep class * extends cn.jpush.android.helpers.JPushMessageReceiver { *; }

-dontwarn cn.jiguang.**
-keep class cn.jiguang.** { *; }


###########okhttputils 和okhttp相关的 的混淆####################
#okhttputils
-dontwarn com.zhy.http.**
-keep class com.zhy.http.**{*;}

#okhttp
-dontwarn okhttp3.**
-keep class okhttp3.**{*;}


#okio
-dontwarn okio.**
-keep class okio.**{*;}

-dontwarn com.squareup.okhttp.**
-dontwarn javax.annotation.**
-dontwarn com.android.volley.toolbox.**
-dontwarn com.facebook.infer.**
-keep class com.squareup.okhttp.** { *;}
-keep interface com.squareup.okhttp.** { *; }

######################### Retrofit混淆配置##############################
-dontnote retrofit2.Platform
-dontnote retrofit2.Platform$IOS$MainThreadExecutor
-dontwarn retrofit2.Platform$Java8
-keepattributes Signature
-keepattributes Exceptions

#########################友盟的混淆配置################

-keep class com.umeng.** {*;}
-keepclassmembers class * {
   public <init> (org.json.JSONObject);
}

-keepclassmembers class * {
   public <init>(org.json.JSONObject);
}
-keep public class [com.uutus.huaxia.geography].R$*{
public static final int *;
}
-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}
-keep public class [com.uutus.huaxia.geography].R$*{
public static final int *;
}

###############加密混淆###########
########腾讯X5内核浏览器中的的代码不被混淆#####
-keep class com.tencent.** {*;}
########RSA中的代码不被混淆
-keep class Decoder.** {*;}
-keep class org.bouncycastle.** {*;}

################Glide加载图片添加混淆
-keep public class * implements com.bumptech.glide.module.GlideModule
-keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** {
  **[] $VALUES;
  public *;
}
######## glide类库
########  com.github.bumptech.glide:okhttp3-integration:1.4.0@aar中的代码不被混淆
########  jp.wasabeef:glide-transformations:2.0.1 不被混淆
-keep class com.bumptech.** {*;}
-keep class jp.wasabeef.glide.** {*;}
##########  保证类库Image 中导入的jar包不被混淆
-keep class com.davemorrissey.** {*;}
-keep class com.filippudak.** {*;}
-keep class am.util.** {*;}
-keep class com.blankj.** {*;}

#########################################################第三方的配置结束#######################

#==================gson && protobuf==========================
-dontwarn com.google.**
-keep class com.google.gson.** {*;}
-keep class com.google.protobuf.** {*;}

#ProGuard 混淆

# keep住源文件以及行号
-keepattributes SourceFile,LineNumberTable


-keepattributes Signature
-dontwarn com.jcraft.jzlib.**
-keep class com.jcraft.jzlib.**  { *;}

-dontwarn sun.misc.**
-keep class sun.misc.** { *;}

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

-dontwarn sun.security.**
-keep class sun.security.** { *; }

-dontwarn com.google.**
-keep class com.google.** { *;}

-dontwarn com.avos.**
-keep class com.avos.** { *;}

-keep public class android.net.http.SslError
-keep public class android.webkit.WebViewClient

-dontwarn android.webkit.WebView
-dontwarn android.net.http.SslEr
-dontwarn android.webkit.WebViewClient

-dontwarn android.support.**

-dontwarn org.apache.**
-keep class org.apache.** { *;}

-dontwarn org.jivesoftware.smack.**
-keep class org.jivesoftware.smack.** { *;}

-dontwarn com.loopj.**
-keep class com.loopj.** { *;}


-dontwarn org.xbill.**
-keep class org.xbill.** { *;}

-keepattributes *Annotation*


# Gson
-keep class com.example.testing.retrofitdemo.bean.**{*;} # 自定义数据模型的bean目录
#gson
#如果用用到Gson解析包的,直接添加下面这几行就能成功混淆,不然会报错。

##---------------Begin: proguard configuration for Gson  ----------
# Gson uses generic type information stored in a class file when working with fields. Proguard
# removes such information by default, so configure it to keep all of it.
-keepattributes Signature

# For using GSON @Expose annotation
-keepattributes *Annotation*

# Gson specific classes
-dontwarn sun.misc.**
#-keep class com.google.gson.stream.** { *; }

# Prevent proguard from stripping interface information from TypeAdapterFactory,
# JsonSerializer, JsonDeserializer instances (so they can be used in @JsonAdapter)
-keep class * implements com.google.gson.TypeAdapterFactory
-keep class * implements com.google.gson.JsonSerializer
-keep class * implements com.google.gson.JsonDeserializer
# Application classes that will be serialized/deserialized over Gson


##---------------End: proguard configuration for Gson  ----------

#基础混淆添加配置
-keepclassmembers class **.R$* {
    public static <fields>;
    public static final int *;
}
-keepclassmembers class * extends android.app.Activity { # 保持自定义控件类不被混淆
    public void *(android.view.View);
}

Ps: 这个也是我找的其实蛮全的,基本上常用的像:Gosn fastJson、Okhttp,以及一些初始化配置这里都用。
但是需要注意的是:

关于实体类和一些自己常用的混淆命令

我们知道实体类是不能混淆的,并且每个项目的实体类都不一样的,比如:你的实体类完整包名字:

com.xxx.xxx.bean
-keep class com.xxx.xxx.bean.**{*;}
表示当前路径下全部文件都保持不被混淆

还有一个常用命令是:
-dontwarn

很多时候你会发现有些不能混淆的类你加了keep配置但是打包还是报错,编译不通过,这个时候你不妨用上这个命令比如:
-keep class com.jianke.ui.{*;}
-dontwarn com.jianke.ui.

这个表示不对当前包名下类警告,让编译通过

还有一些
-libraryjars class_path 不混淆指定的jar库(android 项目中一般不混淆引入的第三方类库)
等,具体可以看:
最全面的混淆规则