Flutter中的Multidex问题

164

在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;

简短版

只有当我添加足够的依赖项时才会发生这种情况,这是可以预料的。我已经按照说明在Android项目的build.gradle文件中启用了multidex并添加了multidex依赖项(https://developer.android.com/studio/build/multidex.html),但不确定如何处理"为您的应用程序配置multidex"中的步骤2以用于Flutter应用,甚至是否省略了该步骤是问题的原因。

重现步骤:

  1. 从工具栏中选择文件/新建/新的Flutter项目
  2. 选择"Flutter应用程序"
  3. 包括Kotlin和Swift支持
  4. 检查应用程序能够编译和运行
  5. 将以下内容添加到pubspec.yaml文件中的依赖项中:

    dependencies:
      flutter_google_place_picker: "^0.0.1"
      location: "^1.2.0"
    
  6. 在Android Studio中点击Packages Get 或者在项目目录下运行flutter packages get
  7. 修改android/app/build.gradle文件,在适当的位置添加以下部分:

    dependencies {
      compile 'com.android.support:multidex:1.0.1'
    }
    android {
        defaultConfig {
            multiDexEnabled true
        }
    }
    
  8. 从工具栏中选择运行/运行

我尝试过的其他方法

  1. build.gradle中,将"compile"依赖项替换为以下每个依赖项:

    compile 'com.android.support:multidex:1.0.3'
    implementation 'com.android.support:multidex:1.0.1'
    implementation 'com.android.support:multidex:1.0.3'
    
  2. 按照多dex步骤处理我的每个依赖项;即修改它们的build.gradle文件,启用multidex并添加multidex依赖。

  3. 修改项目及其依赖项中每个build.gradle文件的minSdkVersion为21和27,并为它们启用multidex。
  4. 为我的项目启用代码混淆。
  5. location: "^1.2.0"替换为geolocation: "^0.2.1"
  6. 完全不启用multidex(即跳过重新创建的第7步)。这会导致以下错误:

  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 输出

    $ 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!
    
17个回答

271

如果你没有开发安卓应用的经验,这些信息可能会对你有所帮助,否则你不会发现任何新东西。


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

如何为Flutter项目启用multidex

  1. 启用multidex。

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

defaultConfig {
    ...

    multiDexEnabled true
}

并且

dependencies {
    ...

    implementation 'androidx.multidex:multidex:2.0.1'
}
  1. 启用Jetifier

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

android.useAndroidX=true
android.enableJetifier=true

1
我将“extends SomeOtherApplication”替换为“extends FlutterApplication”。 - temirbek
1
@YuriMisyac 我正在使用Java,将 FlutterApplication() { 更改为 FlutterApplication { 解决了我的问题,请更新你的代码。它现在可以工作了,谢谢。 - Ujang Karnadi
4
谢谢您的优秀回答!但是在Flutter 1.7中,我只需要执行步骤1和2就可以使多dex工作。如果我执行步骤3和4,应用程序实际上会崩溃! - Karsten Silz
在1.17.0中,我不需要为Q执行第二步。这两个选项已经在gradle.properties中启用了。 - tyirvine
谢谢,第一步修复了我的错误! - federico__
显示剩余5条评论

223

2023年及以后初级开发者的更新:

如果您的项目最低Android API级别为21(它将在99.3%的Android设备上运行),您所需要做的只是:

使用文本编辑器打开位于[your project]\android\app\build.gradle的“应用级 build.gradle 文件”。

有一行以“minSdkVersion”开头。

将其更改为:

defaultConfig {
        // ...
        minSdkVersion [whatever it says here, even if it is not a number]
        // ...
        }

至:

defaultConfig {
            // ...
            minSdkVersion 21
            // ...
            }

显然,如果您希望,21可以更高,但不能更低。

你做完了。

为使multidex正常工作,您无需进行任何其他修改

显然,新的Flutter项目的默认minSDK设置仍然是16,因此在pubspec.yaml中添加足够的依赖项后,许多新开发人员将遇到multidex错误并上网搜索,可能会陷入仅适用于最低级别小于21的旧且令人困惑的信息中。

那是最简单的解决方案,但还有其他方法:

Jahidul Islam的答案在这里, 以及Francis Nduba Numbi的答案在这里

它们各有优缺点,请务必阅读其答案下面的评论。


12
这种做法的原因是:“如果您的应用程序只针对 Android 21 或更高版本 (minSdkVersion),那么多 Dex 已经默认启用,您不需要使用 multidex 支持库。” - bvamos
5
巨大的时间节省者!这是最好的解决方案。 - Owen
1
确实,你节省了我的时间!感谢分享这个解决方案。 - Zujaj Misbah Khan
1
在我的解决方案中,我将19更改为21,现在工作正常! - user_odoo
1
刚接触Flutter..还是一团糟..我没用multidex..不管那是什么..只是又一个pub..然后在设置min sdk为21之后,出现了一堆重复类的问题..清理、删除android文件夹后还是毫无头绪,不知道发生了什么。 - Piotr Kula
显示剩余3条评论

18

你的两个软件包似乎在它们的传递依赖关系上存在分歧。其中一个想要11.6.+版本,而另一个想要某些play-services依赖的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'
    }
}

嗨,Mikkel。非常感谢你抽出时间来回答我的问题。我稍微修改了你的答案,以更好地反映对我有用的内容。如果有不正确的地方,请告诉我。如果我强制分辨率到一个可以满足所有插件要求的播放服务版本,这样说是否公平呢? - SpoonerNZ
是的,11.8.0 应该向后兼容 11.6.x。 - Mikkel Ravn
太棒了。感谢您的解释并提供给我工具(./gradlew androidDependencies),以便将来更好地调查相关问题。 - SpoonerNZ

6

从Flutter 2.10开始

multidex支持被自动启用。如果你的应用程序支持Android SDK版本低于21,且超过64K方法限制,请简单地在flutter build appbundleflutter build apk命令中传递--multidex标志,你的应用程序将支持multidex。


6

2

如果您的minSdkVersion设置为21或更高版本,则默认启用multidex功能,无需使用multidex库。

但是,如果您的minSdkVersion设置为20或更低版本,则必须使用multidex库,并对应用程序项目进行以下修改:

修改模块级别的build.gradle文件以启用multidex并将multidex库添加为依赖项,如下所示:

android {
    defaultConfig {
        ...
        minSdk = 15 
        targetSdk = 28
        multiDexEnabled = true
    }
    ...
}

dependencies {
    implementation("androidx.multidex:multidex:2.0.1")
}

根据您是否覆盖Application类,执行以下操作之一: 如果您没有覆盖Application类,请编辑清单文件并在application标签中设置android:name如下:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.myapp">
    <application
            android:name="androidx.multidex.MultiDexApplication" >
        ...
    </application>
</manifest>

如果你要覆盖Application类,请按照以下方式将其更改为扩展MultiDexApplication(如果可能):
public class MyApplication extends MultiDexApplication { ... }

如果您覆盖了 Application 类,但无法更改基类,则可以覆盖 attachBaseContext() 方法并调用 MultiDex.install(this) 以启用 Multidex:

public class MyApplication extends SomeOtherApplication {
  @Override
  protected void attachBaseContext(Context base) {
     super.attachBaseContext(base);
     MultiDex.install(this);
  }
}

更多信息请访问此博客

该应用程序需要支持Flutter的Multidex。

2
在你的应用级别的build.gradle文件中
change your minSdkVersion flutter.minSdk to 19, then enable multiDex


defaultConfig {
     ...

     minSdkVersion 19   //Copy this

     multiDexEnabled true //Copy this  
 }

在FlutterFire上工作过~Macbook M2 Pro - USB调试。谢谢! - undefined

1

我只想调试我的应用程序,对我有效的最简单解决方案是:

1- 在 Android Studio 终端中键入:

 flutter run --multidex 

然后你会看到一些错误,最后会有一个建议,类似于这样:

BUILD FAILED in 40s
Running Gradle task 'assembleDebug'...                             41.8s
[!] App requires Multidex support
    Multidex support is required for your android app to build since the number of methods has exceeded 64k. You may pass the --no-multidex flag
    to skip Flutter's multidex support to use a manual solution.

    Flutter tool can add multidex support. The following file will be added by flutter:

        android/app/src/main/java/io/flutter/app/FlutterMultiDexApplication.java

Do you want to continue with adding multidex support for Android? [y|n]:

2 - 在这里输入 y 并按回车键以允许添加 multidex 支持。

通过这种方式,我可以在 API 19 上调试我的应用程序。因此,不需要增加 minSdkVersion 到 21。


1
<projectName>\android\app\build.gradle文件中,确保将minSdkVersion设置为21。
 defaultConfig {
        ...
        minSdkVersion 21 // or 20 may be fine
        ...
    }

如果应用程序的目标为 Android 21 或更高版本(minSdkVersion),则无需将 multiDexEnabled 设置为 true,因为 multidex 已默认启用。


1

我只是通过运行flutter run --multidex来解决这个问题,然后回复y以自动启用它。如果它没有起作用,请尝试删除任何你添加的旨在解决此问题的内容,然后再次尝试。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接