前言
今天对项目进行了混淆配置,一直没开启项目混淆,深感可耻,当然有对项目进行加固。前面迟迟不肯行动,畏惧于他人的错误经验,说是混淆出现的坑,这种旁人的意识观,真是害人不浅,其实敢于“对症下药”的去解决,不会花很多时间。
-
代码混淆
在此我只是抛砖引玉,更高级的混淆知识,可以看如下文章
一篇文章带你领略Android混淆的魅力
在Android Studio中的混淆debug与release
https://zhuanlan.zhihu.com/p/49098044
https://www.jianshu.com/p/f67ac2b52813 -
资源混淆(推荐)
这个还是比较靠谱,可以做到,res下的资源被混淆
代码混淆
开启配置很简单,
比如在debug模式下设置minifyEnable 为true,然后在proguard-android.txt增加项目中对应的库的混淆规则。在处理这个过程中,你需要明白为什么要进行混淆。弄懂一些混淆的一些基础语法。碰到有的开源库又给出对应的混淆配置的写法,有的得自己去配置,比如gson,在官方文档中没有对应的混淆规则,
但是它需要去保证对应的bean不让混淆,所以有了以下的配置
-keep class com.qyy.cloudx.ui.me.bean.** { *; }
至于要不要混淆,还是多去排查下,崩溃就是混淆了不该混淆的类
debug {
//是否优化zip
zipAlignEnabled true
// 移除无用的resource文件
shrinkResources true
minifyEnabled true
signingConfig signingConfigs.config
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
buildConfigField("boolean","LOG_DEBUG","${LOG_DEBUG}")
buildConfigField("boolean","BASE_URL_DEBUG","${BASE_URL_DEBUG}")
}
附上项目中的配置:(有点乱)
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# 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
-optimizationpasses 5
# 混淆后类名都为小写 Aa aA
-dontusemixedcaseclassnames
# 指定不去忽略非公共库的类
-dontskipnonpubliclibraryclasses
#不做预校验的操作
-dontpreverify
# 混淆时不记录日志
-verbose
# 混淆采用的算法.
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
#保留代码行号,方便异常信息的追踪
-keepattributes SourceFile,LineNumberTable
#dump文件列出apk包内所有class的内部结构
-dump class_files.txt
#seeds.txt文件列出未混淆的类和成员
-printseeds seeds.txt
#usage.txt文件列出从apk中删除的代码
-printusage unused.txt
#mapping文件列出混淆前后的映射
-printmapping mapping.txt
# ----------------避免混淆Android基本组件
-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.content.ContentProvider
-keep public class * extends android.app.backup.BackupAgentHelper
-keep public class * extends android.preference.Preference
-keep public class com.android.vending.licensing.ILicensingService
#不提示V4包下错误警告
-dontwarn android.support.v4.**
#保持下面的V4兼容包的类不被混淆
-keep class android.support.v4.**{*;}
#--------------避免混淆所有native的方法,涉及到C、C++
-keepclasseswithmembernames class * {
native <methods>;
}
#-------------避免混淆自定义控件类的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);
}
# ------------避免混淆枚举类
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
#-----------避免混淆序列化类
#不混淆Parcelable和它的实现子类,还有Creator成员变量
-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();
}
#----------避免混淆JSON类的构造函数
#使用GSON、fastjson等框架时,所写的JSON对象类不混淆,否则无法将JSON解析成对应的对象
-keepclassmembers class * {
public <init>(org.json.JSONObject);
}
#----------其它混淆指令
#避免混淆属性动画兼容库
-dontwarn com.nineoldandroids.*
-keep class com.nineoldandroids.** { *;}
#不混淆泛型
-keepattributes Signature
#避免混淆注解类
-dontwarn android.annotation
-keepattributes *Annotation*
#避免混淆内部类
-keepattributes InnerClasses
#避免混淆实体类,修改成你对应的包名
-keep class com.wyk.test.bean.** { *; }
-keep class com.wyk.test.event.** { *; }
-keep public class com.wyk.test.utils.eventbus.** { *;}
#避免混淆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;
}
#避免混淆js相关的接口
#-keepattributes *JavascriptInterface*
#-keep class com.wyk.test.js.** { *; }
#---------避免混淆第三方框架 TODO
# 1 https://github.com/CymChad/BaseRecyclerViewAdapterHelper 此资源库自带混淆规则,并且会自动导入,正常情况下无需手动导入。
# 2https://github.com/woxingxiao/XEditText 没看到混淆的代码配置 TODO why
# 3 https://github.com/bumptech/glide
-keep public class * implements com.bumptech.glide.module.GlideModule
-keep class * extends com.bumptech.glide.module.AppGlideModule {
<init>(...);
}
-keep public enum com.bumptech.glide.load.ImageHeaderParser$** {
**[] $VALUES;
public *;
}
-keep class com.bumptech.glide.load.data.ParcelFileDescriptorRewinder$InternalRewinder {
*** rewind();
}
# for DexGuard only
#-keepresourcexmlelements manifest/application/meta-data@value=GlideModule
# 4 https://github.com/chaychan/BottomBarLayout 为啥也没看到 TODO
# 5 https://github.com/huanghaibin-dev/CalendarView
#-keep class your brproject path.MonthView {
# public <init>(android.content.Context);
#}
#-keep class your project path.WeekBar {
# public <init>(android.content.Context);
#}
#-keep class your project path.WeekView {
# public <init>(android.content.Context);
#}
#-keep class your project path.YearView {
# public <init>(android.content.Context);
#}
# 6 https://github.com/gyf-dev/ImmersionBar 也没有 TODO
# 7 greendao https://github.com/greenrobot/greenDAO
-keepclassmembers class * extends org.greenrobot.greendao.AbstractDao {
public static java.lang.String TABLENAME;
}
-keep class **$Properties { *; }
# If you DO use SQLCipher:
-keep class org.greenrobot.greendao.database.SqlCipherEncryptedHelper { *; }
# If you do NOT use SQLCipher:
-dontwarn net.sqlcipher.database.**
# If you do NOT use RxJava:
-dontwarn rx.**
# 8 https://github.com/yuweiguocn/GreenDaoUpgradeHelper
-keepclassmembers class * extends org.greenrobot.greendao.AbstractDao {
public static void dropTable(org.greenrobot.greendao.database.Database, boolean);
public static void createTable(org.greenrobot.greendao.database.Database, boolean);
}
# 9 gson https://github.com/google/gson 也没有 TODO
# 10 eventbus
-keepattributes *Annotation*
-keepclassmembers class * {
@org.greenrobot.eventbus.Subscribe <methods>;
}
-keep enum org.greenrobot.eventbus.ThreadMode { *; }
# And if you use AsyncExecutor:
-keepclassmembers class * extends org.greenrobot.eventbus.util.ThrowableFailureEvent {
<init>(java.lang.Throwable);
}
# 11 okgo
#okgo
-dontwarn com.lzy.okgo.**
-keep class com.lzy.okgo.**{*;}
#okrx
-dontwarn com.lzy.okrx.**
-keep class com.lzy.okrx.**{*;}
#okrx2
-dontwarn com.lzy.okrx2.**
-keep class com.lzy.okrx2.**{*;}
#okserver
-dontwarn com.lzy.okserver.**
-keep class com.lzy.okserver.**{*;}
-keepattributes Signature
# gson***************************
# For using GSON @Expose annotation
-keepattributes *Annotation*
# Gson specific classes
-keep class sun.misc.Unsafe { *; }
#-keep class com.google.gson.stream.** { *; }
# Application classes that will be serialized/deserialized over Gson
-keep class com.qyy.cloudx.ui.me.bean.** { *; }
-keep class com.qyy.cloudx.ui.message.bean.** { *; }
-keep class com.qyy.cloudx.ui.server.bean.**{*;}
-keep class com.qyy.corelib.bean.**{*;}
-keep class com.qyy.cloudx.common.appversion.**{*;}
-keep class com.qyy.cloudx.ui.server.cloud_system.task.**{*;}
-keep class com.qyy.cloudx.ui.server.resource_monitor.bean.**{*;}
-keep class com.qyy.cloudx.common.umpush.CustomBean
-keep class com.qyy.cloudx.ui.login.bean.**{*;}
-keep class com.qyy.cloudx.ui.server.envir_manager.bean.**{*;}
-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();
}
-keep public class * implements java.io.Serializable {*;}
# 推送相关 https://developer.umeng.com/docs/67966/detail/153908#h2-4-6
-dontwarn com.umeng.**
-dontwarn com.taobao.**
-dontwarn anet.channel.**
-dontwarn anetwork.channel.**
-dontwarn org.android.**
-dontwarn org.apache.thrift.**
-dontwarn com.xiaomi.**
-dontwarn com.huawei.**
-dontwarn com.meizu.**
-keepattributes *Annotation*
-keep class com.taobao.** {*;}
-keep class org.android.** {*;}
-keep class anet.channel.** {*;}
-keep class com.umeng.** {*;}
-keep class com.xiaomi.** {*;}
-keep class com.huawei.** {*;}
-keep class com.meizu.** {*;}
-keep class org.apache.thrift.** {*;}
-keep class com.alibaba.sdk.android.**{*;}
-keep class com.ut.**{*;}
-keep class com.ta.**{*;}
-keep public class **.R$*{
public static final int *;
}
资源混淆
混淆前
混淆后,效果很明显,无论包体积,还是资源命名,都可以做到外界无法猜测里面的内容
方案
注意打包的方式
步骤,新建一个and_res_guard.gradle,里面可以这样
apply plugin: 'AndResGuard'
andResGuard {
mappingFile = null
use7zip = true
useSign = true
keepRoot = false
compressFilePattern = [
"*.png",
"*.jpg",
"*.jpeg",
"*.gif",
"resources.arsc"
]
whiteList = [
// your icon
"R.drawable.icon",
// for fabric
"R.string.com.crashlytics.*",
// for umeng update
"R.string.tb_*",
"R.layout.tb_*",
"R.drawable.tb_*",
"R.drawable.u1*",
"R.drawable.u2*",
"R.color.tb_*",
// umeng share for sina
"R.drawable.sina*",
// for google-services.json
"R.string.google_app_id",
"R.string.gcm_defaultSenderId",
"R.string.default_web_client_id",
"R.string.ga_trackingId",
"R.string.firebase_database_url",
"R.string.google_api_key",
"R.string.google_crash_reporting_api_key",
//友盟
"R.string.umeng*",
"R.string.UM*",
"R.layout.umeng*",
"R.drawable.umeng*",
"R.id.umeng*",
"R.anim.umeng*",
"R.color.umeng*",
"R.style.*UM*",
"R.style.umeng*",
]
sevenzip {
artifact = 'com.tencent.mm:SevenZip:1.2.10'
//path = "/usr/local/bin/7za"
}
}
在build.gradle
引用
apply from: 'and_res_guard.gradle'
在项目build.gradle
配置
classpath 'com.tencent.mm:AndResGuard-gradle-plugin:1.2.19'