zoukankan      html  css  js  c++  java
  • android apk瘦身(2) R8编译器:压缩代码、压缩资源、优化代码

    1.官方文档

      https://developer.android.com/studio/build/shrink-code

      当您使用 Android Studio 3.4 或 Android Gradle 插件 3.4.0 及更高版本时,R8 是默认编译器,用于将项目的 Java 字节码转换为在 Android 平台上运行的 DEX 格式。同时还提供以下功能(默认关闭):

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

    2.压缩代码

    2.1 开启

      R8 首先会根据组合的配置文件集确定应用代码的所有入口点。这些入口点包括 Android 平台可用来打开应用的 Activity 或服务的所有类。从每个入口点开始,R8 会检查应用的代码来构建一张图表,列出应用在运行时可能会访问的所有方法、成员变量和其他类。系统会将与该图表没有关联的代码视为执行不到的代码,并可能会从应用中移除该代码。

    在对应模块的build.gradle内  minifyEnabled true  开启。

     1 android {
     2     compileSdkVersion 30
     3     buildToolsVersion '30.0.2'
     4     ...
     5     buildTypes {
     6         debug {
     7             minifyEnabled false
     8         }
     9         release {
    10             minifyEnabled true
    11   
    12         }
    13     }
    14 }

    2.2 保留代码

      在项目的Proguard配置文件中使用  -keep 可保留不被压缩或混淆的代码。如:

     1 # Prevent proguard from stripping interface information from TypeAdapter, TypeAdapterFactory,
     2 # JsonSerializer, JsonDeserializer instances (so they can be used in @JsonAdapter)
     3 -keep class * extends com.google.gson.TypeAdapter
     4 -keep class * implements com.google.gson.TypeAdapterFactory
     5 -keep class * implements com.google.gson.JsonSerializer
     6 -keep class * implements com.google.gson.JsonDeserializer
     7 
     8 # Prevent R8 from leaving Data object members always null
     9 -keepclassmembers,allowobfuscation class * {
    10   @com.google.gson.annotations.SerializedName <fields>;
    11 }

    3.压缩资源

    3.1 开启

    在对应模块的build.gradle内 shrinkResources true 开启。

    压缩资源必需在与压缩代码 开启后,才有效。只有在移除所有不使用的代码后,才能准确定位所有未使用的资源。

     1 android {
     2     compileSdkVersion 30
     3     buildToolsVersion '30.0.2'
     4     ...
     5     buildTypes {
     6         debug {
     7             minifyEnabled false
     8             shrinkResources false
     9         }
    10         release {
    11             minifyEnabled true
    12             shrinkResources true
    13 
    14         }
    15     }
    16 }

    开启后,构建apk时,编译器移除不使用的资源,包括应用库依赖项中不使用的资源。

    3.2 保留资源

    res/raw/下新建xml文件,其中可定义要保留或者丢弃的资源文件。如下:

    1 <?xml version="1.0" encoding="utf-8"?>
    2 <resources xmlns:tools="http://schemas.android.com/tools"
    3     tools:keep="@layout/l_used*_c,@color/svg_color_selector"
    4     tools:shrinkMode="strict"
    5     tools:discard="@layout/unused2"
    6     />
    • tools:keep 属性中指定要保留的资源
    • tools:discard 属性中指定要舍弃的资源 
    • tools:shrinkMode 压缩模式,可取值为[ strict ,safe ] :
      • scrict 严格按照keep和discard指定的资源留或舍。
      • safe:保守的删除未引用资源,如代码中用  Resources.getIdentifier()  引用的资源,会保留。如下:
        1    val name = String.format("img_%1d", angle + 1)
        2    val res = resources.getIdentifier(name, "drawable", packageName)
    • 多个资源文件中 以逗号分隔
    • 可以使用通配符*。
    • 这个xml文件可以有多份

    3.3 优化记录文件

      Gradle 会在 <module-name>/build/outputs/mapping/release/(ProGuard 输出文件所在的文件夹)中创建一个名为 resources.txt 的诊断文件。此文件包含一些详细信息,比如,哪些资源引用了其他资源,哪些资源在使用,哪些资源被移除。

    3.4 在项目源码中删除无用资源

      这个要谨慎

    在android studio中选择菜单项  

    • Refactor  -> Remove unused Resources...
    • Preveiew 查看有哪些未使用
    • Do Refactor 确认删除 

    4.去掉多余语言资源文件

    android studio 工具默认会为@strings/xxx 内的字符资源 生成116个版本。

    使用 resConfigs 可指定只用到的版本,去掉其它的。

     1 android {
     2     compileSdkVersion 30
     3     buildToolsVersion '30.0.2'
     4     defaultConfig {
     5         applicationId "com.jiankangyangfan.nurse"
     6         minSdkVersion 19
     7         targetSdkVersion 30
     8         ...
     9         resConfigs "zh-rCH","zh-rHK","zh-rTW"
    10     }
    11     ...
    12 }

    resConfigs 的取值可以通过一个未压缩的包中查看(上图中红色框内),然后选择目标版本。(并没有发现一个叫"en"的版本)

    5.混淆代码:缩小dex文件

      混淆处理不会从应用中移除代码,但如果应用的 DEX 文件将许多类、方法和字段编入索引,那么混淆处理将可以显著缩减应用的大小。

      R8 在每次运行时都会创建一个 mapping.txt 文件,其中列出了经过混淆处理的类、方法和字段的名称与原始名称的映射关系。

      此映射文件还包含用于将行号映射回原始源文件行号的信息。此文件保存在 <module-name>/build/outputs/mapping/<build-type>/ 目录中。每次发布新版本时都要注意保存一个该文件的副本.

       在 proguard-rules.pro 中加入以下代码可以还原行号 、 输出R8优化记录、输出混淆时被保留的入口类。

    1   -keepattributes LineNumberTable,SourceFile
    2   -printconfiguration ./build/tmp/full-r8-config.txt
    3   -printseeds ./build/tmp/seeds.txt
    • -keepattributes LineNumberTable,SourceFile 用来保留源文件和行号信息。可用来还原混淆。
    • -printconfiguration ./build/tmp/full-r8-config.txt  把混淆记录写入到文件full-r8-config.txt中。
    • -printseeds ./build/tmp/seeds.txt   把混淆入口类输出到seeds.txt中。

      

    6.优化代码

      R8 可深层次优化代码,在项目的 gradle.properties 文件中添加以下代码来启用深度优化功能:

    android.enableR8.fullMode=true

      开启后可能引起不确定bug或者崩溃,谨慎开启。

    具体的优化选项在: 

      https://jakewharton.com/blog

    7.R8配置文件

    R8根据ProGuard配置文件决定优化策略,一个项目中可能有多个模块,每个模块都可以自定义对应的R8配置文件。它们是累加的。一个模块中的配置可能影响到其它模块。

     来源 位置
    Android Studio <module-dir>/proguard-rules.pro
    Android Gradle 插件

    proguard-android-optimize.txt    由 Android Gradle 插件在编译时生成。

    库依赖项

    AAR 库:

    • <library-dir>/proguard.txt

    JAR 库:

    • <library-dir>/META-INF/proguard/
    Android 资源打包工具 2 (AAPT2)

    使用 minifyEnabled true 构建项目后:

      <module-dir>/build/intermediates/proguard-rules/debug/aapt_rules.txt

    自定义配置文件

    默认情况下,当您使用 Android Studio 创建新模块时,IDE 会创建 

      <module-dir>/proguard-rules.pro,以便您添加自己的规则。

    8.资源混淆

      微信的资源混淆参考 : 

      https://mp.weixin.qq.com/s?__biz=MzAwNDY1ODY2OQ==&mid=208135658&idx=1&sn=ac9bd6b4927e9e82f9fa14e396183a8f#rd

  • 相关阅读:
    Vue.js 学习报告
    Javascript 巩固:阮一峰javascript教程 (2017-1-17)
    2017-1-17
    my-Life项目开发流程-02
    《Javascript 权威指南 第六版》
    2017-1-11
    2017-1-10
    2017-1-9
    前端知识解惑: 响应式 兼容性 不错的知识链接
    2017-1-3
  • 原文地址:https://www.cnblogs.com/mhbs/p/11947117.html
Copyright © 2011-2022 走看看