R8 的编译和使用

微信扫一扫,分享到朋友圈

R8 的编译和使用

项目上需要使用 R8 来对 Java 代码进行压缩、混淆,并转换为多个 dex 的形式。由于种种原因,需要从头编译源码,并通过 jar 包引用。考虑到可重复过程的问题,我决定写一篇文章记录一下这个过程。

编译 R8

R8 的编译还是蛮简单的,主要步骤在源码上有: https://r8.googlesource.com/r8

但是呢,上面少了一个步骤,即安装 depot_tools

  1. 安装 depot_tools
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
  1. 添加到环境变量
export PATH=$HOME/android/depot_tools:"$PATH"
  1. 进行编译
tools/gradle.py d8 r8

这样一来就能得到我们想要的包:

build/libs
├── d8.jar
├── d8.jar.zip
├── deps_all.jar
├── r8-src.jar
├── r8.jar
├── r8.jar.zip
├── r8_with_deps.jar
├── r8_with_relocated_deps.jar
└── sources_main.jar

有了 jar 包以后,我们要使用就比较简单。

R8 使用

R8 的使用也相当的简单,只需要 java -jar build/libs/d8.jar
,从中我们就可以看到对应的参数:

Usage: d8 [options] [@<argfile>] <input-files>
where <input-files> are any combination of dex, class, zip, jar, or apk files
and each <argfile> is a file containing additional arguments (one per line)
and options are:
--debug                 # Compile with debugging information (default).
--release               # Compile without debugging information.
--output <file>         # Output result in <outfile>.
# <file> must be an existing directory or a zip file.
--lib <file|jdk-home>   # Add <file|jdk-home> as a library resource.
--classpath <file>      # Add <file> as a classpath resource.
--min-api <number>      # Minimum Android API level compatibility, default: 1.
--pg-map <file>         # Use <file> as a mapping file for distribution.
--intermediate          # Compile an intermediate result intended for later
# merging.
--file-per-class        # Produce a separate dex file per class.
# Synthetic classes are in their own file.
--file-per-class-file   # Produce a separate dex file per input .class file.
# Synthetic classes are with their originating class.
--no-desugaring         # Force disable desugaring.
--desugared-lib <file>  # Specify desugared library configuration.
# <file> is a desugared library configuration (json).
--main-dex-list <file>  # List of classes to place in the primary dex file.
--main-dex-list-output <file>
# Output resulting main dex list in <file>.
--force-enable-assertions[:[<class name>|<package name>...]]
--force-ea[:[<class name>|<package name>...]]
# Forcefully enable javac generated assertion code.
--force-disable-assertions[:[<class name>|<package name>...]]
--force-da[:[<class name>|<package name>...]]
# Forcefully disable javac generated assertion code. This
# is the default handling of javac assertion code when
# generating DEX file format.
--force-passthrough-assertions[:[<class name>|<package name>...]]
--force-pa[:[<class name>|<package name>...]]
# Don't change javac generated assertion code. This
# is the default handling of javac assertion code when
# generating class file format.
--version               # Print the version of d8.
--help                  # Print this message.

转换 dex

接着,我们可以写一个 hello, world 进行测试:

java -jar build/libs/r8_with_deps.jar --output out.jar hello.jar --classpath ~/android/sdk/platforms/android-30/android.jar

看它是否能将其转换为我们所需要的 dex 格式。

混淆

为了正确地混淆,我们需要添加 --pg-conf proguard-common.txt
参数,并添加一些 keep
的规则,如:

-keep class Main {
static void main(java.lang.String[]);
}

以保留我们的类,生成可用的 dex 文件。

multiDex

除了这个场景,我们还需要考虑 multiDex 的场景,同样的也只需要一个参数 --main-dex-rules maindexclasses.txt

如下是 Android 的相关配置:

-keep public class * extends android.app.Instrumentation {
}
-keep public class * extends android.app.Application {
}
-keep public class * extends android.app.Activity {
}
-keep public class * extends android.app.Service {
}
-keep public class * extends android.content.ContentProvider {
}
-keep public class * extends android.content.BroadcastReceiver {
}
-keep public class * extends android.app.backup.BackupAgent {
}
-keep class android.support.multidex.** {
*;
}

嗯,就是这么简单。

DX 历史

顺便一提,在旧版本的 Android 开发环境中,是使用 dx 工具来使用 maindexlist.txt 文件的。

其通过 SDK 工具中的 mainDexClasses
对源码进行扫描,生成 main-dex-list

会生成一个类似如下的文件,包含所有需要包含在主 dex 的文件:

rx/android/concurrency/AndroidSchedulers.class
rx/android/concurrency/HandlerThreadScheduler.class
android/support/v4/view/GravityCompat.class
android/support/v4/view/ViewCompat$AccessibilityLiveRegion.class
android/support/v4/view/MenuCompat.class
android/support/v4/view/ViewCompat$ImportantForAccessibility.class
android/support/v4/view/ViewCompat$OverScroll.class
android/support/v4/view/ViewCompat.class
android/support/v4/view/ViewCompat$LayoutDirectionMode.class
android/support/v4/view/ViewCompat$LayerType.class
android/support/v4/view/ViewCompat$ResolvedLayoutDirectionMode.class
android/support/v4/content/ContextCompat.class
android/support/v4/util/LogWriter.class
android/support/v4/util/SimpleArrayMap.class
android/support/v4/util/DebugUtils.class
android/support/v4/app/ActivityCompat.class
android/support/v4/app/FragmentManagerImpl$2.class
android/support/v4/app/FragmentContainer.class
android/support/v4/app/FragmentTransaction$Transit.class
android/support/v4/app/FragmentManagerImpl$5.class
android/support/v4/app/FragmentActivity$2.class
android/support/v4/app/BackStackRecord$TransitionState.class
...

再把这个文件添加到参数中即可: --main-dex-list

同样的,对于旧的格式,我们也可以通过 --main-dex-list-output
来生成。只是呢,我们根本不需要这个过程。

微信扫一扫,分享到朋友圈

R8 的编译和使用

大神成功移植:任天堂Switch喜提《GTA3》

上一篇

“双星伴月”今明两天扮靓夜空:肉眼可见星月美景

下一篇

你也可能喜欢

R8 的编译和使用

长按储存图像,分享给朋友