📅  最后修改于: 2023-12-03 15:26:16.593000             🧑  作者: Mango
在 Android 开发中,当我们引入过多的依赖库,使用过多的第三方 SDK (比如 Google Play Services、Facebook SDK等)以及自己写的代码都会被打包到一个 APK 文件中,因此一个 APK 文件中存在非常多的代码。为了便于管理和加快应用的启动速度, Google 提供了一个工具 ProGuard,可以帮助我们去掉无用的代码以及缩小 APK 的大小,同时保证其功能不受影响。
然而,当我们的 APK 文件中数量达到一定级别的方法数(65536 个方法),ProGuard 在混淆后会出现“无法将请求的类放在单个 dex 文件中”错误,无法继续混淆并生成 APK 。而实际开发中,有些软件库或者自己编写的代码可能方法达到这个级别,这就需要我们采取一些措施来解决这个问题。
这个错误主要发生在应用构建时,编译器无法将所有的方法编译进一个 DEX 文件中。
Execution failed for task ':app:transformDexArchiveWithDexMergerForDebug'.
com.android.build.api.transform.TransformException: com.android.dex.DexException: Multiple dex files define Lxxxxx;
一种解决方法是分离 Dex 文件。分离 Dex 使得大于 65536 的应用程序能够放置在多个 Dex 文件中,从而避免将所有类打包到一个 Dex 文件中。
在 Gradle 3.0 或更高版本中支持将 Dex 分为多个 Dex。这需要在 build.gradle 文件中启用 MultiDex。
android {
defaultConfig {
...
minSdkVersion 21
targetSdkVersion 29
multiDexEnabled true
}
...
}
dependencies {
implementation 'androidx.multidex:multidex:2.0.1'
}
另一种解决方法是使用Shrink学习库,该库包含在 Android Gradle 插件 3.4.0 中。
android {
defaultConfig {
...
minSdkVersion 21
targetSdkVersion 29
// Enables Gradle scaling to reduce the number of methods
// required for the chosen set of configuration options.
// For more information, go to
// https://developer.android.com/studio/build/shrink-code.
shrinkResources true
}
}
还可以通过优化 Build Variants 的 ProGuard 编译过程压缩代码,并通过使用基于类的保护和压缩来减少 APK 大小以及方法 数量,示例代码如下:
# Basic Android ProGuard configuration file.
# http://developer.android.com/guide/developing/tools/proguard.html
## optimize the code for each Build Variant
# For more information, see https://developer.android.com/studio/build/shrink-code
-optimizationpasses 5
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-dontpreverify
-verbose
-dontwarn android.support.**
-dontwarn android.arch.**
# Obfuscation
-keepattributes Signature
# Optimization
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
# Keep classes with the @Keep attribute
-keepclassmembers class ** {
@com.google.android.gms.common.annotation.Keep class *;
}
# Don't remove certain classes that are required for GSON parsing.
-keep public class com.google.gson.**
-keep class * implements com.google.gson.**
-keep class * extends com.google.gson.**
-keepclassmembers enum * { *; }
-keepattributes Signature
在安卓开发中处理超出限制的问题很常见。所以,我们正在努力优化和设计我们的应用以处理此类问题。升级组件、缩小构建变量,可以减少在应用中包含的方法数量并做优化。为了避免遇到这种限制而无法安装应用的情况,选择一个更好的解决方案,如 dex 分离。通过这种方法,我们可以避免在 DEX 文件中有太多方法导致无法安装问题, 同时也可以保证我们的应用为最优的。