Avoiding Compile Errors When Submitting Your App

If you submit an app to the Amazon Appstore that references close to 65,000 methods, you may receive the following error message via email or on your Review Status tab after submission:

Unable to execute dex: method ID not in [0, 0xffff]: 65536

Conversion to Dalvik format failed: Unable to execute dex: method ID not in [0, 0xffff]: 65536

This error is caused by Android’s limit of 65,535 method references for Dalvik executable (dex) bytecode files. For more information, see the Android documentation, Building Apps with Over 65K Methods.

Amazon Wrapper

Amazon wraps every app in the Amazon Appstore with code to provide developers with various reports, analytics, DRM, and app updates. This wrapper adds 1627 additional referenced methods for the Amazon library and 9 additional methods per activity. Because of these additional referenced methods, your app could be pushed over the method limit if it references close to 65,000 methods.

Although this limit has always existed, exceeding the method-reference limit has become more common with the release of Android 5.0 (Lollipop), which includes new features that often increases the number of method references an app might make. 

To avoid this limit, considering counting the number of method references and reducing the number of references in your app.

Counting the Number of Method References

To count the number of the methods that your app references and what part of the app references them, you can use the dex-method-counts tool available from GitHub: https://github.com/mihaip/dex-method-counts.

Reducing the Number of Method References

To reduce the number of method references, try removing as many extra libraries and methods as possible. Alternately, you can use ProGuard with -dontoptimize –dontobfuscate in the configuration, which will remove unused methods from the dex file at build time.

If the these approaches do not work for your app, try using the multi-dex approach, which splits up classes.dex into multiple dex files.

You can use the multidex library with the Android Gradle plugin. For more information, see Building Apps with Over 65K Methods.

This approach has several caveats:

  • You must use Gradle for your Android development.
  • You might find that Multidex does not remove enough methods without performing a few extra steps which are outlined in the next section.

You can use the dex-method-counts tool referenced above to check the method count of your resulting classes.dex file.

Using the Multidex Library

With the Android 5.0 Lollipop release, a new support library (android-support-multidex.jar) appeared in Android SDK ver 21.1.x and Android Support library 21.0.3. You can find this support library in \android-sdk\extras\android\support\multidex\library\libs. It contains two new classes: MultiDex andMultiDexApplication and simplifies the multidex loading process.

You do not need to use this library if your app targets Android 5.0 exclusively because Android 5.0 has built-in support for secondary dex files. On previous versions of Android, however, it adds additional .dex files from the APK archive to the classloader. The library allows the archive to become part of the primary DEX file of your app and manages access to the additional DEX files. As a result, you should use this library if your app targets any Android releases before Android 5.0.

To implement this solution for pre–Android 5.0 apps:

  1. Make sure you have updated your Android build Tools to the latest version. You will need at least version 21.1.x. The current version as of this writing is 21.1.2.
  2. Add the android-support-multidex.jar library into your project. You can find it in \android-sdk\extras\android\support\multidex\library\libs.
  3. Add multiDexEnabled true and a Multidex dependency to your buildConfig in the build.gradle file, as shown in the following example.

    android {
        compileSdkVersion 21
        buildToolsVersion "21.1.2"
    
        defaultConfig {
            ...
            minSdkVersion 14
            targetSdkVersion 21
            ...
            // Enabling multidex support.
            multiDexEnabled true
    }
     ...
    }
    dependencies {
        compile 'com.android.support:multidex:1.0.0'
    } 
    
  4. Either override the android.app.Application class, or declare the MultiDexApplication class in theAndroidManifest.xml file, as shown in the following code:

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme"
        android:name="android.support.multidex.MultiDexApplication">
        ...
    </application>
    
  5. If you have any additional libraries in your project, be sure that you disable pre-dexing on them. Unfortunately the --multi-dex option is not compatible with pre-dexed libs. 

    You can disable pre-dexing by adding the code below to your app/build.gradle file. 

    android {
    //  ...
        dexOptions {
            preDexLibraries = false
            additionalParameters = ["--set-max-idx-number=55000"] // default 60000
        }
    }
    
  6. Configure your build instructions to ensure that your multidex app is optimized for the Amazon Appstore and the submission process. You have three options:

    1. Manually create the main-dex-list file. In app/build.gradle file, add the following:

      afterEvaluate {
          tasks.matching {
              it.name.startsWith('dex')
          }.each { dx ->
              if (dx.additionalParameters == null) {
                  dx.additionalParameters = []
              }
              dx.additionalParameters += '--multi-dex'
              dx.additionalParameters += "--main-dex-list=$projectDir/<filename>".toString()
          }
      }
      

      This code uses two parameters:

      • --multi-dex — enables splitting mechanism in build process.
      • --main-dex-list — file with list of classes which have to be attached in main dex file. 

      To ensure that your multidex app will go through submission and be published properly in the Amazon Appstore you should use the --main-dex-list parameter to put the following in the main .dex file:

      • Custom Applications
      • Activities
      • Services
      • Receivers
      • Providers
      • Instrumentations
      • Annotations
    2. Ignore the multi-dex and multi-dex-list parameters if you are using studio 0.9.0+ gradle 0.14.2 and use the dx.additionalParameters to manually set the maximum number of referenced methods in your main classes.dex file – the main-dex-list will be auto-generated. It will look similar to the following:

      afterEvaluate {
          tasks.matching {
              it.name.startsWith('dex')
          }.each { dx ->
              if (dx.additionalParameters == null) {
                  dx.additionalParameters = []
              }
              dx.additionalParameters += "--set-max-idx-number=55000" // default 60000
          }
      }
      
    3. Ignore the multi-dex and multi-dex-list parameters if you are using studio 0.9.0+ gradle 0.14.2 and let the build tools automatically limit the dx.additionalParameters parameter to 60,000. This should work for most applications, however if you have a very large number of classes in your app you may find that you will need to manually set your max number to something less than 60,000 to have your app pass submission to the Amazon Appstore properly.

Additional Resources

For generating the main-dex-list, the following assistance is available: