Firebase, AndroidX, .dex file issue in Flutter

I’ve been making mobile games for some time now. Ready to take my games to the next level, I’ve been researching about and playing with Firebase.

Firebase is great and I highly recommend it. It’s a set of services provided by Google that offers those common features that a developer usually needs to write repeatedly for every app. Features like authentication, real-time data storage with automatic sync, and others that I never had the pleasure of using yet are all in there.

Aside from giving back developers, time to work on the features that are unique to their project, it makes doing so really easy.

As I went on developing my game, barely finishing the authentication part, I decided to add in the [cloud_firestore](https://pub.dev/packages/cloud_firestore) package.

Right after the flutter pub get finished, I ran my game to prepare it for the next set of awesome features I was about to write.

But reality decided to challenge me with an error I’ve never encountered before.

Launching lib\main.dart on Android SDK built for x86 in debug mode...
D8: Cannot fit requested classes in a single dex file (# methods: 74380 > 65536)

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':app:transformDexArchiveWithExternalLibsDexMergerForDebug'.
> com.android.builder.dexing.DexArchiveMergerException: Error while merging dex archives: D:\Projects\awesome-game\build\app\intermediates\transforms\dexBuilder\debug\0.jar, D:\Projects\awesome-game\build\app\intermediates\transforms\dexBuilder\debug\1.jar, D:\Projects\awesome-game\build\app\intermediates\transforms\dexBuilder\debug\2.jar, D:\Projects\awesome-game\build\app\intermediates\transforms\dexBuilder\debug\3.jar, D:\Projects\awesome-game\build\app\intermediates\transforms\dexBuilder\debug\13.jar, D:\Projects\awesome-game\build\app\intermediates\transforms\dexBuilder\debug\14.jar, D:\Projects\awesome-game\build\app\intermediates\transforms\dexBuilder\debug\15.jar, ---------------------- this is a really confusing and really long line ---------------------- D:\Projects\awesome-game\build\app\intermediates\transforms\dexBuilder\debug\235.jar, D:\Projects\awesome-game\build\app\intermediates\transforms\dexBuilder\debug\236.jar, D:\Projects\awesome-game\build\app\intermediates\transforms\dexBuilder\debug\237.jar, D:\Projects\awesome-game\build\app\intermediates\transforms\dexBuilder\debug\243.jar, D:\Projects\awesome-game\build\app\intermediates\transforms\dexBuilder\debug\248.jar, D:\Projects\awesome-game\build\app\intermediates\transforms\dexBuilder\debug\254.jar, D:\Projects\awesome-game\build\app\intermediates\transforms\dexBuilder\debug\255.jar, D:\Projects\awesome-game\build\app\intermediates\transforms\dexBuilder\debug\256.jar, D:\Projects\awesome-game\build\app\intermediates\transforms\dexBuilder\debug\257.jar, D:\Projects\awesome-game\build\app\intermediates\transforms\dexBuilder\debug\264.jar, D:\Projects\awesome-game\build\app\intermediates\transforms\dexBuilder\debug\265.jar, D:\Projects\awesome-game\build\app\intermediates\transforms\dexBuilder\debug\266.jar, D:\Projects\awesome-game\build\app\intermediates\transforms\dexBuilder\debug\267.jar
Gradle task assembleDebug failed with exit code 1
  The number of method references in a .dex file cannot exceed 64K.
  Learn how to resolve this issue at https://developer.android.com/tools/building/multidex.html

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 4s
*******************************************************************************************
The Gradle failure may have been because of AndroidX incompatibilities in this Flutter app.
See https://goo.gl/CP92wY for more information on the problem and how to fix it.
*******************************************************************************************
Exited (sigterm)

I confirmed that this issue is caused by the cloud_firestore by repeatedly trying to run the game after removing the package and adding it back.

Recreating the problem

Here’s a sample recreation of the same issue. Right from creating a starter Flutter app, up to the problem itself.

First, create the app by going into your projects directory in a terminal and typing the following:

flutter create firebase_androidx

That should create the classic Flutter starter app in a folder called firebase_androidx. You can use any other name you want but

Next, open up the folder in your favorite IDE or code editor. I use Visual Studio Code, but you can use whatever you’re used to.

Try and run the app.

Add the Cloud Firestore package

Open up ./pubspec.yaml and add cloud_firestore in the dependencies section.

The file section should look like this:

dependencies:
  flutter:
    sdk: flutter
  cloud_firestore: ^0.12.9

Every time you make a change to this file (especially when pub packages are involved), you should always run flutter pub get in the terminal.

Pro tip: Visual Studio Code automatically runs this command for you every time it detects a change on the file.

Next, you need to open ./android/build.gradle and add the following line in the buildscript -> dependencies section.

classpath 'com.google.gms:google-services:4.2.0'

So the top of the file should now look like this:

buildscript {
    repositories {
        google()
        jcenter()
    }

    dependencies {
        classpath 'com.android.tools.build:gradle:3.2.1'
        classpath 'com.google.gms:google-services:4.2.0'
    }
}

And lastly, open ./android/app/build.gradle and at the bottom of the file add the following line under the dependencies section:

implementation 'com.google.firebase:firebase-core:17.0.0'

At the very bottom of the file, add the following as the last line:

apply plugin: 'com.google.gms.google-services'

The bottom of the file should now look like this:

flutter {
    source '../..'
}

dependencies {
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
    implementation 'com.google.firebase:firebase-core:17.0.0'
}

apply plugin: 'com.google.gms.google-services'

Now that cloud_firestore is added, an error like the one above would pop-up when you try to run the app.

Looking for help

The next logical step for me was to seek help from the internet (as I always do when I encounter problems like these).

I tried a lot of search phrases on Google to look for an article or a discussion that is about the same problem. Here’s some that I can recall:

  • D8: Cannot fit requested classes in a single dex file
  • The number of method references in a .dex file cannot exceed 64K
  • AndroidX incompatibilities in this Flutter app
  • flutter enable androidx
  • flutter enable support-v4
  • and more I believe.

Most (if not all) of the results only mentioned a fix but assumed that readers know exactly what they were looking for, what to do when they find it, and how to properly implement it.

This has been hard for me as I have minimal native mobile app development experience. I only became comfortable with it when Flutter came out.

Digging a little deeper

So upon further research, I realized that the developers of Android decided to deprecate the Android Support Library and totally replace it with AndroidX.

I won’t go into much detail about what those are because, to be honest, I barely scratch the surface when it comes to understanding what those two are. All I know is that they enable backward-compatibility for Android-related software across different (especially older) Android versions.

Fix and conclusion

Finally, the fix to the issue is to enable AndroidX and Jetifier. An explanation for what these two are (and why they need to be added together) can be found here.

To apply the fix, open up ./android/gradle.properties in your editor and add the following lines just below the last line:

android.enableJetifier=true
android.useAndroidX=true

If those two lines are already there but have a different value (false for example), it would make sense to just change them to true.

Note: You probably need to delete the _./build_ folder to destroy any cached versions of the wrong build from the previous error messages.

That’s it! I hope this helps anyone who encounters this problem and maybe save a few minutes of their time.

If you need help with Flutter, game development, and software development in general, please send me an email or join my discord server.