Android 混杂及反编译东西Jadx

Android Studio本身集成Java言语的ProGuard作为紧缩,优化和混杂东西,合作Gradle构建东西运用很简单,只需要在工程使用目录的gradle文件中设置minifyEnabled为true即可。然后咱们就能够到proguard-rules.pro文件中参加咱们的混杂规矩了。

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

以上示例代码表明对release版本就行混杂处理。下面咱们先来简介下ProGuard的三大效果,并简要阐明下它们常用的指令。

ProGuard效果

紧缩(Shrinking):默许敞开,用以减小使用体积,移除未被运用的类和成员,并且会在优化动作履行之后再次履行(由于优化后可能会再次露出一些未被运用的类和成员)。

-dontshrink 封闭紧缩

优化(Optimization):默许敞开,在字节码等级履行优化,让使用运转的更快。

-dontoptimize 封闭优化
-optimizationpasses n 表明proguard对代码进行迭代优化的次数,Android一般为5

混杂(Obfuscation):默许敞开,增大反编译难度,类和类成员会被随机命名,除非用keep维护。

-dontobfuscate 封闭混杂

混杂后默许会在工程目录app/build/outputs/mapping/release下生成一个mapping.txt文件,这便是混杂规矩,咱们能够根据这个文件把混杂后的代码反推回源本的代码,所以这个文件很重要,注意维护好。原则上,代码混杂后越乱越无规律越好,但有些当地咱们是要避免混杂的,不然程序运转就会犯错,所以就有了下面咱们要教大家的,怎么让自己的部分代码避免混杂从而避免犯错。

根本规矩

先看如下两个比较常用的指令,很多童鞋可能会比较迷惑以下两者的差异。

-keep class cn.hadcn.test.**
-keep class cn.hadcn.test.*

一颗星表明仅仅坚持该包下的类名,而子包下的类名还是会被混杂;两颗星表明把本包和所含子包下的类名都坚持;用以上办法坚持类后,你会发现类名尽管未混杂,但里边的具体办法和变量命名还是变了,这时假如既想坚持类名,又想坚持里边的内容不被混杂,咱们就需要以下办法了

-keep class cn.hadcn.test.* {*;}

在此基础上,咱们也能够运用Java的根本规矩来维护特定类不被混杂,比如咱们能够用extend,implement等这些Java规矩。如下例子就避免一切继承Activity的类被混杂

-keep public class * extends android.app.Activity

假如咱们要保存一个类中的内部类不被混杂则需要用$符号,如下例子表明坚持ScriptFragment内部类JavaScriptInterface中的一切public内容不被混杂。

-keepclassmembers class cc.ninty.chat.ui.fragment.ScriptFragment$JavaScriptInterface {
    public *;
}

再者,假如一个类中你不希望坚持全部内容不被混杂,而仅仅希望维护类下的特定内容,就能够运用

<init>; //匹配一切构造器 
<fields>; //匹配一切域
<methods>; //匹配一切办法办法

你还能够在或前面加上private 、public、native等来进一步指定不被混杂的内容,如

-keep class cn.hadcn.test.One {
    public <methods>; 
}

表明One类下的一切public办法都不会被混杂,当然你还能够参加参数,比如以下表明用JSONObject作为入参的构造函数不会被混杂

-keep class cn.hadcn.test.One {
    public <init>(org.json.JSONObject); 
}

有时候你是不是还想着,我不需要坚持类名,我只需要把该类下的特定办法坚持不被混杂就好,那你就不能用keep办法了,keep办法会坚持类名,而需要用keepclassmembers ,如此类名就不会被坚持,为了便于对这些规矩进行理解,官网给出了以下表格

保存 避免被移除或许被重命名 避免被重命名
类和类成员 -keep -keepnames
仅类成员 -keepclassmembers -keepclassmembernames
假如具有某成员,保存类和类成员 -keepclasseswithmembers -keepclasseswithmembernames

移除是指在紧缩(Shrinking)时是否会被删去。以上内容时混杂规矩中需要要点把握的,了解后,根本一切的混杂规矩文件你应该都能看懂了。再合作以下几点注意事项,敞开你为自己代码,实现混杂规矩之旅吧。

注意事项

1,jni办法不可混杂,由于这个办法需要和native办法坚持一致;

-keepclasseswithmembernames class * { # 坚持native办法不被混杂
    native <methods>;
}

2,反射用到的类不混杂(不然反射可能出现问题);

3,AndroidMainfest中的类不混杂,所以四大组件和Application的子类和Framework层下一切的类默许不会进行混杂。自定义的View默许也不会被混杂;所以像网上贴的很多排除自定义View,或四大组件被混杂的规矩在Android Studio中是无需参加的;

4,与服务端交互时,运用GSON、fastjson等结构解析服务端数据时,所写的JSON对象类不混杂,不然无法将JSON解析成对应的对象;

5,运用第三方开源库或许引证其他第三方的SDK包时,假如有特别要求,也需要在混杂文件中参加对应的混杂规矩;

6,有用到WebView的JS调用也需要确保写的接口办法不混杂,原因和第一条相同;

7,Parcelable的子类和Creator静态成员变量不混杂,不然会产生Android.os.BadParcelableException异常;

-keep class * implements Android.os.Parcelable { # 坚持Parcelable不被混杂
    public static final Android.os.Parcelable$Creator *; 
}

8,运用enum类型时需要注意避免以下两个办法混杂,由于enum类的特殊性,以下两个办法会被反射调用,见第二条规矩。

-keepclassmembers enum * {
    public static **[] values(); 
    public static ** valueOf(java.lang.String);
 }

写在最后

发布一款使用除了设minifyEnabled为ture,你也应该设置zipAlignEnabled为true,像Google Play强制要求开发者上传的使用必须是通过zipAlign的,zipAlign能够让安装包中的资源按4字节对齐,这样能够削减使用在运转时的内存耗费。

android 反编译东西Jadx

github.com/skylot/jadx

检查源码东西

Source Insight