在Android开发中,为了使App尽可能小,可以使用R8来压缩,混淆,优化App,当使用Android Gradle插件3.4.0或更高版本时,插件不再使用ProGuard执行优化而是R8。

R8的功能

  • 代码压缩:安全地从App及其库依赖项中删除未使用的类,字段,方法和属性。
  • 资源压缩:从打包的App中删除未使用的资源,包括应用程序库依赖项中未使用的资源。它与代码压缩一起使用,这样一旦删除了未使用的代码,也可以安全地删除不再引用的资源。
  • 代码混淆:使用简短无意义的名称重命名代码里的类,字段和方法,从而减少DEX文件大小。
  • 代码优化:删除未使用的代码或重写代码使其更简洁。

R8 和 Proguard

R8和Proguard 相比,R8 可以更快地缩减代码,同时改善输出大小,R8 默认处于启用状态,你可将以下代码添加到项目的 gradle.properties 文件以停用 R8:

android.enableR8=false

R8 普通模式是兼容 Proguard的,R8 完全模式与会启用一些额外的优化,这个时候可能需要一些其它ProGuard规则以避免运行时问题,可以在 项目的gradle.properties 文件中设置以下内容启用完全模式。

android.enableR8.fullMode=true

启用压缩,混淆,优化

使用Android Studio创建新项目时,默认情况下不启用压缩,混淆,优化,因为这会增加项目的构建时间,而且有些代码混淆后会出错。要想启用这些功能,需要在项目的build.gradle包含下面的内容。

getDefaultProguardFile(‘proguard-android.txt’) 方法可从 Android SDK tools/proguard/ 文件夹获取默认的 ProGuard规则文件。

proguard-rules.pro文件用于添加自定义 ProGuard 规则。默认情况下,该文件位于模块根目录。

android {buildTypes {release {//启用代码压缩,混淆,优化minifyEnabled true//启用资源压缩shrinkResources true//ProGuard规则文件proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'),'proguard-rules.pro'}}...
}

自定义要保留的资源

如果您有想要保留或舍弃的特定资源,请在您的项目中创建一个包含 标记的 XML 文件,并在 tools:keep 属性中指定每个要保留的资源,在 tools:discard 属性中指定每个要舍弃的资源。这两个属性都接受逗号分隔的资源名称列表。您可以使用星号字符作为通配符。

<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"tools:keep="@layout/l_used*_c,@layout/l_used_a,@layout/l_used_b*"tools:discard="@layout/unused2" />

严格压缩模式

如果你的代码或库代码(例如AppCompat)调用了Resources.getIdentifier(),这就表示你的代码将根据动态生成的字符串查询资源名称,默认情况下资源压缩器会采取防御性行为,将所有具有匹配名称格式的资源标记为可能已使用,无法移除。例如,以下代码会使所有带 img_ 前缀的资源标记为已使用。

String name = String.format("img_%1d", angle + 1);
res = getResources().getIdentifier(name, "drawable", getPackageName());

在 keep.xml 文件中将 shrinkMode 设置为 strict可以停用该防御性行为,这个时候你必须用tools:keep 属性手动保留这些资源。

<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"tools:shrinkMode="strict" />

合并重复资源

默认情况下,Gradle 还会合并同名资源,例如可能位于不同资源文件夹中的同名可绘制对象。这一行为不受 shrinkResources 属性控制,也无法停用,因为在有多个资源匹配代码查询的名称时,有必要利用这一行为来避免错误。

只有在两个或更多个文件具有完全相同的资源名称类型限定符时,才会进行资源合并。

自定义要保持的代码

在ProGuard规则文件中可以使用-keep保持特定代码不被移除或混淆,或者向你想保持的代码添加 @Keep 注解,在类上添加 @Keep 可原样保持整个类,在方法或字段上添加它可完整保持方法/字段(及其名称)以及类名称。

-keep public class MyClass

必须保持的代码

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

常用ProGuard规则

关闭压缩

-dontshrink

关闭代码优化,默认Proguard规则文件已包含

-dontoptimize

关闭混淆

-dontobfuscate

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

-optimizationpasses 5

混淆时不使用大小写混合类名,默认Proguard规则文件已包含

-dontusemixedcaseclassnames

不忽略库中的非public的类,默认Proguard规则文件已包含

-dontskipnonpubliclibraryclasses

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

-dontskipnonpubliclibraryclassmembers

输出详细信息,默认Proguard规则文件已包含

-verbose

不做预校验,预校验是作用在Java平台上的,Android平台上不需要这项功能,去掉之后还可以加快混淆速度,默认Proguard规则文件已包含

-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.**

特殊ProGuard规则

由于enum类的特殊性,下面两个方法会被反射调用,默认Proguard规则文件已经处理。

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

Parcelable的子类和Creator静态成员变量要保持,否则会产生Android.os.BadParcelableException异常,默认Proguard规则文件已经处理。

-keepclassmembers class * implements android.os.Parcelable {public static final android.os.Parcelable$Creator CREATOR;
}

常用混淆模板

# 指定代码的压缩级别
-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或ProGuard构建项目后会在模块下的build\outputs\mapping\release文件夹下输出下列文件:

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

Android使用R8压缩,混淆,优化App相关推荐

  1. android 万能混淆文件,Android ProGuard 代码压缩混淆与打包优化

    为什么要启动ProGuard(所有试验都在AS 环境) 代码压缩通过 ProGuard 提供,ProGuard 会检测和移除封装应用中未使用的类.字段.方法和属性, 包括自带代码库中的未使用项(这使其 ...

  2. Android包体积优化上篇- 资源混淆优化

    导读:什么时候进行包体积优化?一般在app初创期时,由于业务代码较少,包体积也不大,相应这个时候对包体积的优化收益也较少.当业务逐渐成熟功能,迭代逐渐变多,包体积也会逐渐增加. 增加包体积主要影响如下 ...

  3. Android项目打包开启proguard的混淆优化带来的问题

    1.引入一个sdk以后.打包报错: [INFO] Unexpected error while evaluating instruction: [INFO]   Class       = [com/ ...

  4. Android性能优化-App后台优化

    原文链接 Background Optimizations 前言 后台进程是内存和电池敏感的.一个隐式的broadcast可能会启动很多监听它的后台进程,即使这些进程可能做得工作不多.这可能丢设备性能 ...

  5. Android性能优化-App启动优化

    原文地址:https://developer.android.com/topic/performance/launch-time.html#common 通常用户期望app响应和加载速度越快越好.一个 ...

  6. android 电池容量检测,电池容量检测优化app

    电池容量检测优化app是一款功能十分强大的手机电池优化服务软件,使用这款软件可以快速的对电池容量进行检测,同时还可以对手机内存进行一键清理,只需要轻松点击一下就可以节省高达50%的电池寿命,需要的朋友 ...

  7. android 常用混淆,Android常用的代码混淆整理【原创】

    android里的代码混淆是比不可少的东西,下面就贴一些常用的代码混淆. #指定代码的压缩级别 -optimizationpasses 5 #包明不混合大小写 -dontusemixedcasecla ...

  8. [转]Android 项目的代码混淆,Android proguard 使用说明

    简介 Java代码是非常容易反编译的.为了很好的保护Java源代码,我们往往会对编译好的class文件进行混淆处理. ProGuard是一个混淆代码的开源项目.它的主要作用就是混淆,当然它还能对字节码 ...

  9. 读懂Android中的代码混淆

    本文为本人的一些实践总结,介绍一些混淆的知识和注意事项.希望可以帮助大家更好的学习和使用代码混淆. 什么是混淆 关于混淆维基百科上该词条的解释为 代码混淆(Obfuscated code)亦称花指令, ...

最新文章

  1. Android图片轮播
  2. leetcode算法题--二叉树的前序遍历
  3. rdbms mysql_RDBMS-mysql初步
  4. python boxplot pvalue_1.1.1数据质量分析Python boxplot,111,箱,线图
  5. aop+注解 实现对实体类的字段校验_SpringBoot实现通用的接口参数校验
  6. 机动车c1科三考试语言灯光,c1科目三灯光模拟考试
  7. C语言输出九九乘法表
  8. 原子变量, 无锁定且无等待算法
  9. 关于j2ee工程发布到was上后,部分更新,例修改web.xml配置文件不起作用的原因解析【转】...
  10. 抢椅子游戏java_抢椅子游戏作文(精选10篇)
  11. 聊聊图标和MBE图标
  12. C++IO流文件指针
  13. HDU - 4565 So Easy!
  14. 个人备案网站不能做博客了?
  15. 吃鸡是python写的吗_用Python来P图,分析怎么吃鸡?只有想不到,没有做不到
  16. 整理的java基础知识点笔记
  17. 哲理故事300篇(上)
  18. 自我健康检测及产品应用方案
  19. 中信soeasy网络硬盘 瑞星杀毒软件升级包
  20. 怎么把一个网页设置快捷方式弄到桌面上去

热门文章

  1. Charles修改请求和返回
  2. 关于Spark默认并行度spark.default.parallelism的理解
  3. excel转json对象工具推荐
  4. FFmpeg之视频封装格式、流媒体协议、视频编解码协议和传输流格式、时间戳和时间基、视频像素数据
  5. Inno setup 安装卸载前校验工作
  6. python设计模式 韦塞尔 pdf下载_《Python设计模式》 [美] 韦塞尔. 巴登霍斯特(Wessel Badenhorst)著 蒲成 译 【正版电子纸书阅读_PDF下载】- 书问...
  7. 【Python教你一招】用Python实现童年小游戏俄罗斯方块
  8. mysql dal层_MySQL读写分离的DAL层策略设计
  9. 20180908考试
  10. Egret 5.3 正式发布,为重度小游戏开发带来新技能