前提
为了android应用的安全性,往往我们在应用发布之前都会进行代码混淆处理。以前都是网上了解大概,运用网上写好的混淆规则进行修改。为了更加系统的学习混淆,现针对混淆做一个整理笔记。
混淆原理
android studio自带java语言的ProGuard工具,主要用来压缩、优化、混淆,然后配合Gradle构建工具实现混淆。
混淆步骤
1、在工程目录下的gradle文件中设置release下的minifyEnabled=true。
buildTypes {
...
release {
minifyEnabled true
zipAlignEnabled false
signingConfig signingConfigs.release
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
1.minifyEnabled 表示是否打开混淆,true表示打开。
2.zipAlignEnabled是表示是否优化。true表示打开,zipalign 是 Android 提供的一个整理优化 apk 文件的工具,可在一定程度上上提高系统和应用的运行效率,更快的读取 apk 中的资源,降低内存的使用。
3.signingConfig signingConfigs.release配置签名文件。
4.getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 配置混淆文件。
2、配置混淆文件。
a.基本语法详解
#保持com.xiaohu.android包下的类名
-keep class com.xiaohu.android.*
#保持com.xiaohu.android包下以及子包下的类名
-keep class com.xiaohu.android.**
#保持类里面的方法和变量名不变
-keep class com.xiaohu.android.*{*;}
b.特殊语法
#保持类中部分内容
# <init>; 匹配所有构造器
# <fieids>; 匹配所有域
# <methods>; 匹配所有方法
#有时候我们需要在<fields>或<methods>前面加上private、public、native等访问修饰符来指定不被混淆的内容
#例如:表示Test类下所有的方法都不被混淆
-keep class com.xiaohu.android.Test{
public <methods>;
}
#表示用JSONObject作为入参的构造函数不会被混淆
-keep class com.xiaohu.android.Test {
public <init>(org.json.JSONObject);
}
c.keep 与 keepclassmembers , keepclasseswithmembers简介
d.通用语法、适合大部分项目
#指定压缩级别
-optimizationpasses 5
#不跳过非公共的库的类成员
-dontskipnonpubliclibraryclassmembers
#混淆时采用的算法
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
#把混淆类中的方法名也混淆了
-useuniqueclassmembernames
#优化时允许访问并修改有修饰符的类和类的成员
-allowaccessmodification
#将文件来源重命名为“SourceFile”字符串
-renamesourcefileattribute SourceFile
#假如项目中有用到注解,应加入这行配置,对JSON实体映射也很重要,eg:fastjson
-keepattributes *Annotation*
#抛出异常时保留代码行数
-keepattributes SourceFile,LineNumberTable
#保持泛型
-keepattributes Signature
#保持所有实现 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();
}
#Fragment不需要在AndroidManifest.xml中注册,需要额外保护下
-keep public class * extends android.support.v4.app.Fragment
-keep public class * extends android.app.Fragment
#继承activity,application,service,broadcastReceiver,contentprovider....不进行混淆
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.support.multidex.MultiDexApplication
-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.** {*;}
#自定义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);
}
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet);
public <init>(android.content.Context, android.util.AttributeSet, int);
}
#这个主要是在layout 中写的onclick方法android:onclick="onClick",不进行混淆
-keepclassmembers class * extends android.app.Activity {
public void *(android.view.View);
}
#保持枚举
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
#保持 Parcelable 不被混淆(aidl文件不能去混淆)
-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}
#保持R文件不被混淆,否则,你的反射是获取不到资源id的
-keep class **.R$* { *; }
# natvie 方法不混淆
-keepclasseswithmembernames class * {
native <methods>;
}
#保持 Parcelable 不被混淆
-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}
#特殊配置
#保护WebView对HTML页面的API不被混淆
#对WebView的简单说明下:经过实战检验,做腾讯QQ登录,如果引用他们提供的jar,
#若不加防止WebChromeClient混淆的代码,oauth认证无法回调,反编译基代码后可看到他们有用到WebChromeClient,加入此代码即可。
-keep class **.Webview2JsInterface { *; }
#如果你的项目中用到了webview的复杂操作,最好加入
-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.WebChromeClient {
public void *(android.webkit.WebView,java.lang.String);
}
#转换JSON的JavaBean,类成员名称保护,使其不被混淆
-keepclassmembernames class com.xiaohu.android.bean.** { *; }
# 保持测试相关的代码
-dontnote junit.framework.**
-dontnote junit.runner.**
-dontwarn android.test.**
-dontwarn android.support.test.**
-dontwarn org.junit.**