📌  相关文章
📜  无法将请求的类放在单个 dex 文件中(# methods: 65710 > 65536) (1)

📅  最后修改于: 2023-12-03 15:26:16.593000             🧑  作者: Mango

大坑:无法将请求的类放在单个 dex 文件中(# methods: 65710 > 65536)

在 Android 开发中,当我们引入过多的依赖库,使用过多的第三方 SDK (比如 Google Play Services、Facebook SDK等)以及自己写的代码都会被打包到一个 APK 文件中,因此一个 APK 文件中存在非常多的代码。为了便于管理和加快应用的启动速度, Google 提供了一个工具 ProGuard,可以帮助我们去掉无用的代码以及缩小 APK 的大小,同时保证其功能不受影响。

然而,当我们的 APK 文件中数量达到一定级别的方法数(65536 个方法),ProGuard 在混淆后会出现“无法将请求的类放在单个 dex 文件中”错误,无法继续混淆并生成 APK 。而实际开发中,有些软件库或者自己编写的代码可能方法达到这个级别,这就需要我们采取一些措施来解决这个问题。

问题及解决方案
问题一:出现“无法将请求的类放在单个 dex 文件中"错误

这个错误主要发生在应用构建时,编译器无法将所有的方法编译进一个 DEX 文件中。

Execution failed for task ':app:transformDexArchiveWithDexMergerForDebug'.
com.android.build.api.transform.TransformException: com.android.dex.DexException: Multiple dex files define Lxxxxx;
解决方案一:分离 Dex

一种解决方法是分离 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学习库

另一种解决方法是使用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
  }
}
解决方案三:使用 ProGuard 参数优化

还可以通过优化 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 文件中有太多方法导致无法安装问题, 同时也可以保证我们的应用为最优的。