Flutter 的 Multidex 问题

Posted

技术标签:

【中文标题】Flutter 的 Multidex 问题【英文标题】:Multidex issue with Flutter 【发布时间】:2018-09-27 22:07:33 【问题描述】:

我在 android Studio 中使用 Flutter 编译 gradle 时遇到以下错误:

Dex: Error converting bytecode to dex:
Cause: com.android.dex.DexException: Multiple dex files define Lcom/google/android/gms/internal/zzcew;
UNEXPECTED TOP-LEVEL EXCEPTION:
com.android.dex.DexException: Multiple dex files define Lcom/google/android/gms/internal/zzcew;

[... stacktrace omitted for brevity ...]

* What went wrong:
Execution failed for task ':app:transformDexArchiveWithDexMergerForDebug'.
> com.android.build.api.transform.TransformException: com.android.dex.DexException: Multiple dex files define Lcom/google/android/gms/internal/zzcew;

短版

这仅在我添加足够的依赖项时才会发生,正如预期的那样。我已启用 multidex 并按照说明 (https://developer.android.com/studio/build/multidex.html) 在 Android 项目 build.gradle 文件中添加了 multidex 依赖项,但不确定如何处理 Flutter 应用程序的“为 multidex 配置应用程序”中的第 2 步, 甚至是那一步的遗漏是否是问题所在。

重建步骤:

    从工具栏中选择File/New/New Flutter Project 选择“Flutter 应用程序” 包括 Kotlin 和 Swift 支持 检查应用的编译和运行情况

    pubspec.yaml中添加以下依赖:

    dependencies:
      flutter_google_place_picker: "^0.0.1"
      location: "^1.2.0"
    
    在 Android Studio 中点击 Packages Get 或在项目目录中运行 flutter packages get

    修改android/app/build.gradle,在适当的地方添加以下部分:

    dependencies 
      compile 'com.android.support:multidex:1.0.1'
    
    android 
        defaultConfig 
            multiDexEnabled true
        
    
    
    从工具栏中选择Run/Run

我尝试过的其他事情

    build.gradle 中的“编译”依赖项替换为以下各项:

    compile 'com.android.support:multidex:1.0.3'
    implementation 'com.android.support:multidex:1.0.1'
    implementation 'com.android.support:multidex:1.0.3'
    

    按照我的每个依赖项的 multidex 步骤进行操作;即修改他们的build.gradle文件,启用multidex并添加multidex依赖。

    在我的项目及其依赖项的每个 build.gradle 文件中将 minSdkVersion 分别修改为 21 和 27,并为它们启用 multidex。 为我的项目启用缩小功能。 将location: "^1.2.0" 替换为geolocation: "^0.2.1"

    根本不启用 multidex(即跳过重新创建的第 7 步)。这会导致以下错误:

    FAILURE: Build failed with an exception.
    
    * What went wrong:
    Execution failed for task ':app:transformDexArchiveWithExternalLibsDexMergerForDebug'.
    > java.lang.RuntimeException: java.lang.RuntimeException: com.android.builder.dexing.DexArchiveMergerException: Unable to merge dex
    

颤振医生输出

$ flutter doctor -v
[√] Flutter (Channel beta, v0.2.8, on Microsoft Windows [Version 10.0.16299.371], locale en-GB)
    • Flutter version 0.2.8 at D:\flutter
    • Framework revision b397406561 (2 weeks ago), 2018-04-02 13:53:20 -0700
    • Engine revision c903c217a1
    • Dart version 2.0.0-dev.43.0.flutter-52afcba357

[√] Android toolchain - develop for Android devices (Android SDK 27.0.3)
    • Android SDK at C:\Users\Dave\AppData\Local\Android\sdk
    • Android NDK location not configured (optional; useful for native profiling support)
    • Platform android-27, build-tools 27.0.3
    • Java binary at: D:\AndroidDev\jre\bin\java
    • Java version OpenJDK Runtime Environment (build 1.8.0_152-release-1024-b02)
    • All Android licenses accepted.

[√] Android Studio (version 3.1)
    • Android Studio at D:\AndroidDev
    • Java version OpenJDK Runtime Environment (build 1.8.0_152-release-1024-b02)

[√] Connected devices (1 available)
    • Android SDK built for x86 64 • emulator-5554 • android-x64 • Android 5.1.1 (API 22) (emulator)

• No issues found!

【问题讨论】:

【参考方案1】:

您的两个包似乎在传递依赖方面存在分歧。一个想要 11.6.+,另一个想要 11.+ 的一些播放服务依赖项。由于 11.6.2 和 11.8.0 都在那里,这将导致冲突。

如果您在android/ 文件夹中运行./gradlew androidDependencies,您将获得依赖关系解析结果的列表,其中包含以下内容:

+--- :flutter_google_place_picker (variant: release)
+--- com.google.android.gms:play-services-location:11.8.0@aar
+--- com.google.android.gms:play-services-places:11.6.2@aar
+--- com.google.android.gms:play-services-maps:11.6.2@aar
+--- com.google.android.gms:play-services-base:11.8.0@aar
+--- com.google.android.gms:play-services-tasks:11.8.0@aar
+--- com.google.android.gms:play-services-basement:11.8.0@aar

这些 11.6.2 和 11.8.0 包不能一起工作。要解决此问题,您需要修补依赖项以使其彼此一致,或者在 android/app/build.gradle 文件的顶层添加依赖项覆盖并希望最好:

configurations.all 
    resolutionStrategy 
        force 'com.google.android.gms:play-services-places:11.8.0'
        force 'com.google.android.gms:play-services-location:11.8.0'
    

【讨论】:

嗨,米克尔。非常感谢您花时间回答。我已经稍微修改了您的答案,以更好地反映对我有用的内容,如果不正确,请告诉我。公平地说,如果我强制解析到可以满足所有插件要求的播放服务版本,应该没有问题吗? 是的,11.8.0 应该向后兼容 11.6.x。 酷。感谢您解释并向我提供工具 (./gradlew androidDependencies),以便将来更好地调查相关问题。【参考方案2】:

如果您没有开发 Android 应用程序的经验,此信息可能会有所帮助,否则您将找不到任何新内容。


在大多数情况下,第一步就足够了

如何为flutter项目启用multidex。

    启用多索引。

打开[project_folder]/app/build.gradle 并添加以下行。

defaultConfig 
    ...

    multiDexEnabled true

dependencies 
    ...

    implementation 'com.android.support:multidex:1.0.3'

    启用Jetifier。

打开[project_folder]/android/app/gradle.properties 并添加以下行。

android.useAndroidX=true
android.enableJetifier=true

注意:从 Flutter 1.7 开始,不再需要以下步骤。


3) **创建自定义应用程序类。**

如果您不知道在哪里创建文件,请在 MainActivity 附近创建文件,例如 [project_folder]/android/app/src/main/kotlin(or java if you didn't enable kotlin)/your/great/pakage/appname/

kotlin 示例:App.kt

    package your.great.pakage.appname
    
    import io.flutter.app.FlutterApplication
    import android.content.Context
    import androidx.multidex.MultiDex
    
    class App : FlutterApplication() 
    
        override fun attachBaseContext(base: Context) 
            super.attachBaseContext(base)
            MultiDex.install(this)
        
    
    

java 示例:App.java

    package your.great.pakage.appname;
    
    import io.flutter.app.FlutterApplication;
    import android.content.Context;
    import androidx.multidex.MultiDex;

    public class App extends FlutterApplication 

        @Override
        protected void attachBaseContext(Context base) 
            super.attachBaseContext(base);
            MultiDex.install(this);
        

    
    将默认应用程序文件更改为新的。

打开[project_folder]/android/app/src/main/AndroidManifest.xml

android:name="io.flutter.app.FlutterApplication" 更改为android:name=".App"

【讨论】:

我添加了 extends FlutterApplication 而不是 extends SomeOtherApplication 我在 Java 中实现它,但我也在使用 FacebookLogin 插件,当我实现你的答案时,它说“SDK 尚未初始化,请确保首先调用 FacebookSdk.sdkInitialize()。 " @BarbaricGamester 你在CustomApplicationClassonCreate() 方法中添加了FacebookSdk.sdkInitialize() 吗? @YuriMisyac 我正在使用 java 将 FlutterApplication() 更改为 FlutterApplication 解决我的问题,请更新您的代码。它的工作谢谢, 感谢您的精彩回答!但是在 Flutter 1.7 中,我需要步骤 1 和 2 来让 multi-dex 工作。如果我应用第 3 步和第 4 步,应用程序实际上会崩溃!【参考方案3】:

2021 年及以后的初学者开发者更新:

如果您可以将所需的最低 Android API 级别设置为 21(在撰写本文时,您的应用仍将在 98% 的设备上运行),那么您所要做的就是:

    打开位于 [您的项目]\android\app\build.gradle 的“应用程序级 build.gradle 文件”

    将 16(或任何适合您的数字)更改为至少 21:

     defaultConfig 
     // ...
     minSdkVersion 16
     // ...
     
    

...到:

defaultConfig 
    // ...
    minSdkVersion 21
    // ...

无需进行任何其他修改即可让 multidex 正常工作。

显然,新 Flutter 项目的默认 minSDK 设置仍然是 16,所以在 pubspec.yaml 中添加足够多的依赖项后,许多新开发人员会遇到 multidex 错误并上网搜索,可能会陷入混乱的信息中,这些信息只有适用于最低级别设置为低于 21 的项目。

【讨论】:

之所以有效,是因为:“如果您的应用仅针对 Android 21 或更高版本 (minSdkVersion),则默认情况下已启用 multidex,您不需要 multidex 支持库。”【参考方案4】:

在你的应用程序文件夹中的 android

defaultConfig 
    ...

    multiDexEnabled true

另请查看:Enable multidex for apps with over 64K methods

【讨论】:

【参考方案5】:

在您的应用级 build.gradle 文件中

    将 minSdkVersion 从 16 增加到 20。

    启用 multiDex。

    defaultConfig 
         ...
    
         minSdkVersion 20   //Copy this
         multiDexEnabled true //Copy this  
     
    

【讨论】:

【参考方案6】:

只需更改 app\build.gradle 中的行

defaultConfig
multiDexEnabled true

不要添加任何依赖 我首先添加了 multidex 依赖项,但程序说找不到它 然后我将 maven 添加到 build.gradle 但没有做任何更改

其实你只需要把 false 改成 true 就行了 Android studio 会休息

【讨论】:

【参考方案7】:

如果您通过 USB 安装,请务必在设备请求许可时单击安装按钮,这就是我的解决方案。

【讨论】:

【参考方案8】:

<projectName>\android\app\build.gradle 确保将minSdkVersion 设置为 21

 defaultConfig 
        ...
        minSdkVersion 21 // or 20 may be fine
        ...
    

无需将multiDexEnabled 设置为true,就好像该应用仅针对Android 21 或更高版本(minSdkVersion)然后multidex 默认已启用。

【讨论】:

以上是关于Flutter 的 Multidex 问题的主要内容,如果未能解决你的问题,请参考以下文章

如何在颤振中向 multiDexKeepFile 添加类?

Flutter 在启动时崩溃:在路径 DexPathList 上找不到类 .MainActivity

VM 有 multidex 支持,MultiDex 支持库被禁用。问题

android MultiDex multidex原理原理下遇见的N个深坑

android MultiDex multidex原理下超出方法数的限制问题

我在颤振中正确运行 multi_select_flutter 小部件时遇到问题