参考:
Android Studio系列之代码混淆proguardFiles
Android混淆配置总结-持续更新
5分钟搞定android混淆
Android混淆总结篇(一)
Android Proguard(混淆)
混淆的概念:
将Android项目进行打包之时,可以将项目里的包名、类名、变量名进行更改,使得代码不容易泄露,类似于对其apk中的文件加密.
混淆的作用:
1.增加Apk反编译之后代码泄露的困难性
2.生成的apk体积会缩小
什么是混淆?
Android SDK 本身就提供混淆的功能,将混淆开关进行开启后,开发者需要做的是对Android Studio工程项目中的proguard-rules.pro文件进行混淆白名单的配置.
那么什么是混淆白名单呢?其实就是指定一些包名、类名、变量等不可以被混淆。假设没指定白名单就进行混淆打包,而某某类的类名被混淆了(假设变成了a),那么可能其他引用或使用该类的类就找不到该类,说不定应用就会因此崩溃或是导致相应的功能无法使用.
什么时候配置混淆白名单
一般以下情况都会不混淆:
1.使用了自定义控件那么要保证它们不参与混淆
2.使用了枚举要保证枚举不被混淆
3.对第三方库中的类不进行混淆
4.运用了反射的类也不进行混淆
5.使用了 Gson 之类的工具要使 JavaBean 类即实体类不被混淆
6.在引用第三方库的时候,一般会标明库的混淆规则的,建议在使用的时候就把混淆规则添加上去,免得到最后才去找
7.有用到 WebView 的 JS 调用也需要保证写的接口方法不混淆,原因和第一条一样
8.Parcelable 的子类和 Creator 静态成员变量不混淆,否则会产生 Android.os.BadParcelableException 异常
一颗星表示只是保持该包下的类名,而子包下的类名还是会被混淆,内容也会被混淆;
-keep class cn.xq.test.*
两颗星表示把本包和所含子包下的类名都保持,内容也会被混淆;
-keep class cn.xq.test.**
如果本包和所含子包下的类名都保持,内容也不想被混淆:
-keep class cn.xq.test.** { *; }
-libraryjars class_path 应用的依赖包,如android-support-v4
-keep [,modifier,...] class_specification 不混淆某些类
-keepclassmembers [,modifier,...] class_specification 不混淆类的成员
-keepclasseswithmembers [,modifier,...] class_specification 不混淆类及其成员
-keepnames class_specification 不混淆类及其成员名
-keepclassmembernames class_specification 不混淆类的成员名
-keepclasseswithmembernames class_specification 不混淆类及其成员名
-assumenosideeffects class_specification
假设调用不产生任何影响,在proguard代码优化时会将该调用remove掉。如system.out.println和Log.v等等
-dontwarn [class_filter] 不提示warnning
ProGuard 能够对 Java 类中的代码进行压缩(Shrink),优化(Optimize),混淆(Obfuscate),预检(Preveirfy)。
压缩(Shrink):检测和删除没有使用的类,字段,方法和属性。
优化(Optimize):对字节码进行优化,并且移除无用指令。
混淆(Obfuscate):使用 a,b,c 等无意义的名称,对类,字段和方法进行重命名。
预检(Preveirfy):主要是在 Java 平台上对处理后的代码进行预检。
1.开启混淆开关
android studio
1、将minifyEnabled设为true
2、proguardFiles 设置混淆的文件proguard-rules.pro
android {
compileSdkVersion 25
buildToolsVersion "25.0.3"
defaultConfig {
applicationId "example.com.myping"
minSdkVersion 15
targetSdkVersion 25
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
minifyEnabled true表示进行代码加密,false表示不加密
proguardFiles 代码加密原则 有两个文件对,getDefaultProguardFile(‘proguard-android.txt’)表示默认文件,这个文件是sdk自带的,有一些通用的配置;但是如果apk需要更加严格的加密,我们可以在’proguard-rules.pro’文件中进行更加详尽的配置
eclipse:
project.properties中添加proguard.config属性,并指定混淆文件。
target=android-25
android.library=false
proguard.config=proguard-project.txt
2.设置混淆白名单
#---------------------------------实体类---------------------------------
# -keep class 你的实体类所在的包.** { *; }
#避免混淆实体类,修改成你对应的包名
-keep class com.xq.test.bean.** { *; }
#---------------------------------第三方包-------------------------------
# 打开你的build.gradle文件,查看你用了哪些第三方的包。
# 去他们的官网把已经写好的混淆copy下来
#glide
-keep public class * implements com.bumptech.glide.module.GlideModule
-keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** {
**[] $VALUES;
public *;
}
#避免混淆属性动画兼容库
-dontwarn com.nineoldandroids.*
-keep class com.nineoldandroids.** { *;}
#Universal Image Loader
-keep class com.nostra13.universalimageloader.** { *; }
-keepattributes Signature
#使用GSON、fastjson等框架时,所写的JSON对象类不混淆,否则无法将JSON解析成对应的对象
-keepclassmembers class * {
public <init>(org.json.JSONObject);
}
#---------------------------------与js互相调用的类------------------------
#-keep class 你的类所在的包.** { *; } 保留类名不变,也就是类名不混淆
#-keepclasseswithmembers class 你的类所在的包.父类$子类 { <methods>; } 保留类名和成员名。
# 保留所有注解
-keepattributes *Annotation*
-keepattributes *JavascriptInterface*
# 改成自己的包名,类名和内部类名
-keepclasseswithmembers class <package>.MainActivity$JSInterface {
<methods>;
}
#---------------------------------反射相关的类和方法-----------------------
#-keep class 你的类所在的包.** { *; }
#-----------------------------------基本不变-----------------------------------------
# 指定代码的压缩级别
-optimizationpasses 5
# 是否使用大小写混合,类名均小写
-dontusemixedcaseclassnames
# 是否混淆第三方jar
-dontskipnonpubliclibraryclasses
# 指定不去忽略非公共库的类成员
-dontskipnonpubliclibraryclassmembers
# 混淆时是否做预校验,可加快混淆速度
-dontpreverify
# 混淆时是否记录日志
-verbose
# 混淆时所采用的算法
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
#抛出异常时保留代码行号
-keepattributes SourceFile,LineNumberTable
#泛型,解决出现类型转换错误的问题
-keepattributes Signature
#避免混淆js相关的接口
-keepattributes *JavascriptInterface*
#避免混淆注解类
-dontwarn android.annotation
-keepattributes *Annotation*
#避免混淆内部类
-keepattributes InnerClasses
# 保持哪些类不被混淆
-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 * extends android.view.View
-keep public class com.android.vending.licensing.ILicensingService
#保持兼容包的类不被混淆
-keep class android.support.** {*;}
# 保留继承的
-keep public class * extends android.support.v4.**
-keep public class * extends android.support.v7.**
-keep public class * extends android.support.annotation.**
# 保留R下面的资源
-keep class **.R$* {*;}
# 保持 native 方法不被混淆
-keepclasseswithmembernames class * {
native <methods>;
}
# 保持自定义控件类不被混淆
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet);
public <init>(android.content.Context, android.util.AttributeSet, int);
}
# 保留在Activity中的方法参数是view的方法,
# 这样以来我们在layout中写的onClick就不会被影响
-keepclassmembers class * extends android.app.Activity {
public void *(android.view.View);
}
#避免混淆自定义控件类的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();
}
# 对于带有回调函数的onXXEvent、**On*Listener的,不能被混淆
-keepclassmembers class * {
void *(**On*Event);
void *(**On*Listener);
}