Android Gradle插件升级至3.4.0版本之后,带来一个新特性-新一代混淆工具R8,做为D8的升级版替代Proguard;在应用压缩、应用优化方面提供更极致的体验。

Gradle插件版本3.4.0之后:

R8 默认处于启用状态:R8 将脱糖、压缩、混淆、优化和 dex 处理整合到了一个步骤中,从而显著提升了构建性能。 R8 是在 Android Gradle 插件 3.3.0 中引入的,对于使用插件 3.4.0 及更高版本的应用和 Android 库项目,R8 现已默认处于启用状态。

下图是 R8 引入之前的编译流程的简要概览。

现在,有了 R8,可以在一个步骤中完成脱糖、压缩、混淆、优化和 dex 处理 (D8),如下图所示。

请注意,R8 旨在与您现有的 ProGuard 规则配合使用,因此您可能不需要采取任何操作即可从 R8 中受益。但是,相对专为 Android 项目设计的 ProGuard 而言,R8 是一项不同的技术,因此压缩和优化可能会导致移除 ProGuard 可能没有的代码。因此,在这种情况(尽管不太可能发生)下,您可能需要添加其他规则,以在构建输出中保留这些代码。

如果您在使用 R8 时遇到问题,请阅读 R8 兼容性常见问题解答一文,以检查是否有针对您的问题的解决方案。如果没有记录的解决方案,请报告错误。您可以停用 R8,只需将以下其中一行代码添加到项目的 gradle.properties文件即可:

# Disables R8 for Android Library modules only.
android.enableR8.libraries = false
# Disables R8 for all modules.
android.enableR8 = false

注意:对于指定构建类型,如果您在应用模块的 build.gradle 文件中将 useProguard 设为 false,Android Gradle 插件会使用 R8 压缩该构建类型的应用代码,无论您是否在项目的 gradle.properties 文件中停用 R8 都是如此。

R8 和 Proguard

 R8 一步到位地完成了所有的缩减(shrinking),去糖(desugaring)和 转换成 Dalvik 字节码(dexing )过程。

缩减(shrinking)过程实现以下三个重要的功能:

  • 代码缩减:从应用及其库依赖项中检测并安全地移除未使用的类、字段、方法和属性。
  • 资源缩减:从封装应用中移除不使用的资源,包括应用库依赖项中的不使用的资源。
  • 优化:检查并重写代码,以进一步减小应用的 DEX 文件的大小。
  • 混淆:缩短类和成员的名称,从而减小 DEX 文件的大小。

 R8 和当前的代码缩减解决方案 Proguard 相比,R8 可以更快地缩减代码,同时改善输出大小。下面将通过几张数据图来对比(数据源自于 benchmark):

shrinkingTime.png

dexSize.png

apkSize.png

R8混淆使用

 R8的使用非常简单,使用方式与Proguard并无差异,Android Studio创建项目时默认是关闭的,因为这会加长工程打包时间,所以开发阶段不建议开启。开启方式如下:

buildTypes {release {// 启用代码收缩、混淆和优化。minifyEnabled true// 启用资源缩减shrinkResources trueproguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'}}

 可以看到gradle中加载了两个混淆配置文件, 其中 proguard-rules.pro 供开发者自定义混淆规则;proguard-android-optimize.txt 这是默认的配置文件,包含一些通用的混淆规则,在sdk/tools/proguard目录下,其中包含的内容如下:

# This is a configuration file for ProGuard.
# http://proguard.sourceforge.net/index.html#manual/usage.html
#
# This file is no longer maintained and is not used by new (2.2+) versions of the
# Android plugin for Gradle. Instead, the Android plugin for Gradle generates the
# default rules at build time and stores them in the build directory.# Optimizations: If you don't want to optimize, use the
# proguard-android.txt configuration file instead of this one, which
# turns off the optimization flags.  Adding optimization introduces
# certain risks, since for example not all optimizations performed by
# ProGuard works on all versions of Dalvik.  The following flags turn
# off various optimizations known to have issues, but the list may not
# be complete or up to date. (The "arithmetic" optimization can be
# used if you are only targeting Android 2.0 or later.)  Make sure you
# test thoroughly if you go this route.
-optimizations !code/simplification/arithmetic,!code/simplification/cast,!field/*,!class/merging/*
-optimizationpasses 5
-allowaccessmodification
-dontpreverify# The remainder of this file is identical to the non-optimized version
# of the Proguard configuration file (except that the other file has
# flags to turn off optimization).-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-verbose-keepattributes *Annotation*
-keep public class com.google.vending.licensing.ILicensingService
-keep public class com.android.vending.licensing.ILicensingService# For native methods, see http://proguard.sourceforge.net/manual/examples.html#native
-keepclasseswithmembernames class * {native <methods>;
}# keep setters in Views so that animations can still work.
# see http://proguard.sourceforge.net/manual/examples.html#beans
-keepclassmembers public class * extends android.view.View {void set*(***);*** get*();
}# We want to keep methods in Activity that could be used in the XML attribute onClick
-keepclassmembers class * extends android.app.Activity {public void *(android.view.View);
}# For enumeration classes, see http://proguard.sourceforge.net/manual/examples.html#enumerations
-keepclassmembers enum * {public static **[] values();public static ** valueOf(java.lang.String);
}-keepclassmembers class * implements android.os.Parcelable {public static final android.os.Parcelable$Creator CREATOR;
}-keepclassmembers class **.R$* {public static <fields>;
}# The support library contains references to newer platform versions.
# Don't warn about those in case this app is linking against an older
# platform version.  We know about them, and they are safe.
-dontwarn android.support.**# Understand the @Keep support annotation.
-keep class android.support.annotation.Keep-keep @android.support.annotation.Keep class * {*;}-keepclasseswithmembers class * {@android.support.annotation.Keep <methods>;
}-keepclasseswithmembers class * {@android.support.annotation.Keep <fields>;
}-keepclasseswithmembers class * {@android.support.annotation.Keep <init>(...);
}

ProGuard常用规则

关闭压缩

-dontshrink

关闭代码优化

-dontoptimize

关闭混淆

-dontobfuscate

指定代码优化级别,值在0-7之间,默认为5

-optimizationpasses 5

混淆时不使用大小写混合类名

-dontusemixedcaseclassnames

不忽略库中的非public的类

-dontskipnonpubliclibraryclasses

不忽略库中的非public的类成员

-dontskipnonpubliclibraryclassmembers

输出详细信息

-verbose

不做预校验,预校验是作用在Java平台上的,Android平台上不需要这项功能,去掉之后还可以加快混淆速度

-dontpreverify

保持指定包下的类名,不包括子包下的类名

-keep class com.xy.myapp*

保持指定包下的类名,包括子包下的类名

-keep class com.xy.myapp**

保持指定包下的类名以及类里面的内容

-keep class com.xy.myapp.* {*;}

保持所有继承于指定类的类

-keep public class * extends android.app.Activity

其它keep方法:

保留 防止被移除或者被混淆 防止被混淆
类和类成员 -keep -keepnames
仅类成员 -keepclassmembers -keepclassmembernames
如果拥有某成员,保留类和类成员 -keepclasseswithmembers -keepclasseswithmembernames

如果我们要保留一个类中的内部类不被混淆则需要用$符号,如下例子表示保持MyClass内部类JavaScriptInterface中的所有public内容。

-keepclassmembers class com.xy.myapp.MyClass$JavaScriptInterface {public *;
}

保持指定类的所有方法

-keep class com.xy.myapp.MyClass {public <methods>;
}

保持指定类的所有字段

-keep class com.xy.myapp.MyClass {public <fields>;
}

保持指定类的所有构造器

-keep class com.xy.myapp.MyClass {public <init>;
}

保持用指定参数作为形参的方法

-keep class com.xy.myapp.MyClass {public <methods>(java.lang.String);
}

类文件除了定义类,字段,方法外,还为它们附加了一些属性,例如注解,异常,行号等,优化操作会删除不必要的属性,使用-keepattributes可以保留指定的属性

-keepattributes Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,*Annotation*,EnclosingMethod

使指定的类不输出警告信息

-dontwarn com.squareup.okhttp.**

常用混淆模版

# 指定代码的压缩级别
-optimizationpasses 5     # 不忽略库中的非public的类成员
-dontskipnonpubliclibraryclassmembers # google推荐算法
-optimizations !code/simplification/arithmetic,!code/simplification/cast,!field/*,!class/merging/*# 避免混淆Annotation、内部类、泛型、匿名类
-keepattributes *Annotation*,InnerClasses,Signature,EnclosingMethod# 抛出异常时保留代码行号
-keepattributes SourceFile,LineNumberTable# 保持四大组件
-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# 保持support下的所有类及其内部类
-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.**# 保持自定义控件
-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);
}# 保持所有实现 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();
}# 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);
}

输出文件

 启用R8构建项目后会在模块下的build\outputs\mapping\release文件夹下输出下列文件:

  • dump.txt:说明 APK 中所有类文件的内部结构。
  • mapping.txt:提供原始与混淆过的类、方法和字段名称之间的转换。
  • seeds.txt:列出未进行混淆的类和成员。
  • usage.txt:列出从 APK 移除的代码。

必须保持的代码

  • AndroidManifest.xml引用的类。
  • JNI调用的方法。
  • 反射用到的类。
  • WebView中JavaScript使用的类。
  • Layout文件引用的自定义View。

混淆心得

 我们在开发过程中,可以先记录下必须保持的类及方法,后面在做混淆时,维度可以不用做的那么细致,当然如果有安全、规范要求,那就还是一步一步的走吧。只要细心一点,混淆并不复杂。

参考文章

混淆压缩官方指导文档
Android代码压缩工具R8详解
Android使用R8压缩,混淆,优化App

Android代码压缩工具R8详解 android.enableR8=true

作者:望着天数月亮
链接:https://www.jianshu.com/p/fdadca8e2094
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

Android 代码混淆 R8与Proguard相关推荐

  1. android加密墙,Android代码混淆加密配置(Proguard文件解析)

    Android代码混淆加密配置(Proguard文件解析) Android代码混淆加密配置(Proguard文件解析) 为了防止自己的APP被轻易反编译,我们需要对APK进行混淆,或者特殊加密处理.可 ...

  2. Android 代码混淆Proguard

    混淆概念 Android代码混淆,又称Android混淆,是伴随着Android系统的流行而产生的一种APP保护技术,用于保护APP不被破解和逆向分析. 在Android的具体表现就是打包时,将项目里 ...

  3. 使用ProGuard进行Android代码混淆(保姆级教程)

    使用ProGuard进行Android代码混淆(保姆级教程) 一.ProGuard的功能 ProGuard是一个混淆代码的开源项目,主要是用来对java代码进行混淆,当然也就可以对java代码进行混淆 ...

  4. android aidl混淆代码,Android代码混淆

    什么是代码混淆 代码混淆就是将代码中的各种元素,如变量,方法,类和包的名字改写成无意义的名字,增加项目反编译后被读懂的难度. Android代码混淆使用ProGuard工具,ProGuard是一个压缩 ...

  5. android代码混淆个人总结及踩坑

    android代码混淆个人总结及踩坑 前言 公司项目使用组件化开发的形式,需要对自己负责的模块进行一些混淆配置,关于混淆相信做android开发的都或多或少有过一些接触,通过对混淆文件的配置从而将代码 ...

  6. android 混淆后的机制,Android 代码混淆机制

    Android 代码混淆机制 由于Android项目是基于java语言的,而java属于高层抽象语言,易于反编译,其编译后的程序包包含了大量的源代码变量.函数名.数据结构等信息,根据其编译打包后的AP ...

  7. android混淆语法(android代码混淆工具)

    android 代码混淆算法有哪些 根据SDK的版本不同有2中不同的代码混淆方式,以上的proguard.cfg参数详解中所涉及到的信息是在较低版本SDK下的混淆脚本,事实上在高版本的SDK下混淆的原 ...

  8. Android 代码混淆语法讲解及常用模板(转)

    转载请注明原博客地址  Android 代码混淆语法讲解及常用模板 前言 混淆对于每一个开发者来说都不陌生,对于大多数 APP 而言,在上线之前,通常会进行代码混淆,加固,防止自己的 APP 被别人轻 ...

  9. Android代码混淆配置说明

    1.为什么需要代码混淆 Proguard混淆用于保护APP不被破解和逆向分析,Proguard通过移除没有用到的代码以及通过特定规则重命名类.变量.方法来压缩.优化.混淆你的代码.这样可以让你APK更 ...

最新文章

  1. 为什么要进行数据归一化
  2. 【Python】青少年蓝桥杯_每日一题_1.19_Python 求和
  3. [BZOJ3245]最快路线
  4. html+cs入门实例,CS50 HTML和CSS基础(介绍最简单的HTML和CSS)
  5. 排序算法(一)--插入排序法折半插入排序法
  6. “bim”技术助力“智慧城市”建设
  7. 如何删除数据库SQL重复数据
  8. mac地址厂商查询_3.15干货你的手机mac地址泄漏了吗
  9. nginx 源码安装
  10. 以太坊存储项目Swarm (代币bzz)1.0 主网正式上线
  11. java输入日期计算天数_Java输入日期得到天数
  12. 学人工智能电脑主机八大件配置选择指南
  13. 安卓模拟器对应键盘快捷键
  14. 可怕的乖孩子_你知道乖孩子的一生,有多可怕吗?
  15. 农行c语言笔试题,中国农业银行总行计算机类笔试面试经验
  16. 马尔科夫链-转移概率
  17. 海思HI35xx平台软件开发快速入门之背景知识
  18. CSS浮动父级塌陷的解决办法
  19. python圆面积怎么算_如何编写圆和squ面积计算程序
  20. 四象限法推导lm曲线_试用几何方法推导IS曲线(四象限法)

热门文章

  1. matlab的randi函数
  2. 怎样在PDF文件中查找某个特定的词?
  3. Linux系统启动流程(超详细)
  4. 欧洲杯爆冷:法国点球大战遭瑞士淘汰,本泽马3分钟2球,姆巴佩罚丢点球
  5. 树莓派:获取传感器数据
  6. 用MybatisPlus代码生成器生成代码
  7. MacBook Pro合上盖子不休眠的问题简单分析
  8. javascript兼容性很好的省市区联动,易修改
  9. reactjs中文入门教程
  10. 很抱歉此功能看似已中断,并需要修复。请使用Windows控制面板中的“程序和功能”选项修复Microsoft Office