Android 混淆全面解析

前言

大家在打包正式apk包,发布应用市场时,都会开启混淆配置,这样可以优化包体积大小,而且能增加别人反编译的难度,有没有人和我一样,对于混淆只停留在使用层面上,发布release包时打开minifyEnable设置为true,然后添加混淆时到网上copy一份混淆配置,就ok了,这些配置到底是什么意思呢?以及混淆在打包过程中处于哪个阶段呢?sdk打包成aar如何配置混淆呢?下文会告诉你答案。

  一、apk打包的编译过程,认识D8和R8。

我们知道,从java代码经过编译过程,变成dex文件,是经过一系列的任务处理的。

在gradle3.0版本之后,引入了d8处理器,java代码由Javac处理成.class文件,再经过proguard混淆优化,变成优化过的.class文件,最后由d8处理成最终的dex文件。

1.什么D8?

D8是gradle编译时的task的名字的简称,主要是处理字节码脱糖和dx打包。我们知道在Java1.8之后,可以使用lamada语法糖,可以让代码更加的简洁,d8的任务是将art不认识的java8字节码处理成编译器认识的java低版本的字节码指令,然后由DX处理成dex文件。

2.什么是R8?

R8是将Proguard任务和D8任务合并成一个task

在gradle3.2之后引入R8编译,3.4版本之后将R8作为默认的编译处理器。

R8优化了编译速度,同时减小apk的体积,它主要做以下事情:

1.将D8和Proguard两个过程融合成一个任务,减少了编译步骤,编译速度更快。

2.缩减了代码,将没有使用的代码移除掉,减小了apk包的体积。

3.缩减资源文件,将重复和无用的资源文件移除

4.如果开启了multidex开关,会进行dex分包处理。

二、组件化aar混淆方案

在创建Module时,在build.gradle中会自动生成两个混淆文件

defaultConfig {
    ...
    consumerProguardFiles 'consumer-rules.pro'
}

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

1.proguardFiles和consumerProguardFiles的区别:

   在打包发布aar文件时,开启minifyEnabled=true,proguardFiles会生效,此时别人反编译代码,看到的是已混淆的文件。

consumerProguardFiles是依赖主项目时生效的文件,在此文件中你可以添加对外暴露的类不混淆的代码,它会作用于整个app中。

proguardFiles不会打包进aar中,而consumerProguardFiles会打包进aar中。

2.添加混淆配置

方案一:

将aar的反混淆代码写到宿主的proguardFiles中,这样的好处是统一维护,不好的地方在于如果需要移除某个aar时,相应的要移除它的反混淆的代码。

方案二:

在aar中的consumerProguardFiles添加混淆配置,宿主app不需要收到添加。这样做的好处是不需要依赖主项目,最大限度做到解藕的目的。

三、自定义混淆规则介绍

            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'

在app的gradle文件中默认有两个混淆文件,其中proguard-android-optimize文件位于SDK内tools/proguard文件夹中,配置了默认不需要混淆的代码,比如Android的四大组件,以及继承view的构造方法等。

proguard-rules.pro配置自定义的混淆规则。

1.常见的混淆命令说明

命令作用
-keep防止类和成员被移除或者被重命名
-keepnames防止类和成员被重命名
-keepclassmembers防止成员被移除或者被重命名
-keepnames防止成员被重命名
-keepclasseswithmembers防止拥有该成员的类和成员被移除或者被重命名
-keepclasseswithmembernames防止拥有该成员的类和成员被重命名

2.常用的混淆规则举例

  • 不混淆某个类

    -keep public class name.huihui.example.Test { *; }
  • 不混淆某个包所有的类

    -keep class name.huihui.test.** { *; }
  • 不混淆某个类的子类

    -keep public class * extends name.huihui.example.Test { *; }
  • 不混淆所有类名中包含了“model”的类及其成员

    -keep public class **.*model*.** {*;}
  • 不混淆某个接口的实现

    -keep class * implements name.huihui.example.TestInterface { *; }
  • 不混淆某个类的构造方法

    -keepclassmembers class name.huihui.example.Test { 
      public <init>(); 
    }
  • 不混淆某个类的特定的方法

    -keepclassmembers class name.huihui.example.Test { 
      public void test(java.lang.String); 
    }

参考资料

1.Android代码混淆&组件化和SDK混淆方案 - 掘金

2.写给Android开发者的混淆使用手册 - 掘金

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值