(通用)Android App代码混淆终极解决方案

Posted Sharley

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了(通用)Android App代码混淆终极解决方案相关的知识,希望对你有一定的参考价值。

App虽然没有那么的高大上,但是代码的混淆是代表了程序员对App的责任心, 也是对App安全的一点点保证。今天我会将自己做Android混淆的过程和体会分享给大家,也避免大家少走弯路,少跳坑。

本篇博客混淆基于Android Studio的IDE开发环境。

其实在android Studio中做混淆,基本就是对Proguard-rules.pro文件的操作。混淆的过程也是有规律可循的。下面我将分几个部分来分别介绍混淆过程。

(1)如何开启混淆。

(2)混淆的公共部分。

(3)需要我们不混淆的代码。

(4)libs下的第三方Jar包的混淆方式。

(5)complie的第三方Jar包的混淆方式。

(6)代码注释的混淆方式。

ok,大家准备好了吗?下面我就以流水账的方式与大家分别介绍啦!(O(∩_∩)O 哈哈~)

1.如何开启混淆

开始混淆很简单,android Studio中找到你的项目module的build.gradle,如下图所示:

 

将minifyEnabled设置为true就ok。

2.公共部分

在混淆的过程中,有一部分是固定不变的。下面我将列出保持不变的模块,只需将代码Copy即可。

 

#1.基本指令区
-optimizationpasses 5
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-dontskipnonpubliclibraryclassmembers
-dontpreverify
-verbose
-ignorewarning
-printmapping proguardMapping.txt
-optimizations !code/simplification/cast,!field/*,!class/merging/*
-keepattributes *Annotation*,InnerClasses
-keepattributes Signature
-keepattributes SourceFile,LineNumberTable

#2.默认保留区
-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.** {*;}

-keepclasseswithmembernames class * {
    native <methods>;
}
-keepclassmembers class * extends android.app.Activity{
    public void *(android.view.View);
}
-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}
-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);
}
-keep class * implements android.os.Parcelable {
  public static final android.os.Parcelable$Creator *;
}
-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 class **.R$* {
 *;
}
-keepclassmembers class * {
    void *(**On*Event);
}

#3.webview
-keepclassmembers class fqcn.of.javascript.interface.for.webview {
   public *;
}
-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.webViewClient {
    public void *(android.webkit.webView, jav.lang.String);
}

 

以上就是固定不变的部分。

3.需要我们不混淆的代码

不混淆用关键字-keep来修饰。不混淆的部分大概分为如下几个模块:

(1)实体类,json解析类

(2)第三方jar包

(3)js和webview的调用模块

(4)与反射相关的类和方法

大概就是以上几个模块,下面来看不混淆的代码:

 

#1.实体类
-keep class com.xx.xx.entity.** { *; }

#2.第三方包
#eventBus
-keepattributes *Annotation*
-keepclassmembers class ** {
    @org.greenrobot.eventbus.Subscribe <methods>;
}
-keep enum org.greenrobot.eventbus.** { *; }
-keepclassmembers class * extends org.greenrobot.eventbus.util.ThrowableFailureEvent {
    <init>(java.lang.Throwable);
}

#3.与js互相调用的类
 没有可不写
#4.反射相关的类和方法
-keep class com.xx.xx.xx.xx.view.** { *; }
-keep class com.xx.xx.xx.xx.xx.** { *; }

 

4.libs下的第三方Jar包的混淆方式
保留libs下的jar包的方式也很简单,同样是使用-keep关键字:
找到libs目录,打开相对于的jar文件,找到对应的包名,然后添加如下代码:

-keep class 包名.** { *; }
5.complie的第三方Jar包的混淆方式
complie的第三方Jar包的混淆方式和libs下的相同,只需要打开:

打开对应的引用jar文件,然后同样使用

-keep class 包名.** { *; }
6.代码注释的混淆方式
我们在项目中肯定用到过有注释方式的代码,例如小刀(butterknife)。需要使用@Bind来修饰变量。此时保留这种注释需要如下代码:
-keep class butterknife.** { *; }
-dontwarn butterknife.internal.**
-keep class **$$ViewBinder { *; }

-keepclasseswithmembernames class * {
    @butterknife.* <fields>;
}

-keepclasseswithmembernames class * {
    @butterknife.* <methods>;
}

emm...自己说一句,如果butterknife版本较低时可能要把第三行换成

-keep class **$$ViewInjector{ *; }

 

以上是关于(通用)Android App代码混淆终极解决方案的主要内容,如果未能解决你的问题,请参考以下文章

Android之app混淆深入分析-层层解析解决开发中痛点

Android多模块混淆的问题

安卓 dex 通用脱壳技术研究

安卓 dex 通用脱壳技术研究

Android App 混淆打包错误日志追踪

Android组件化之终极方案