Невозможно выполнить dex: ID метода не в [0, 0xffff]: 65536

Я уже видел разные версии dex erros, но эта нова. очистка / перезапуск и т. д. не поможет. Библиотечные проекты кажутся неповрежденными, а зависимость, похоже, правильно связана.

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

или же

Cannot merge new index 65950 into a non-jumbo instruction

или же

java.util.concurrent.ExecutionException: com.android.dex.DexIndexOverflowException: method ID not in [0, 0xffff]: 65536

tl; dr: Официальное решение от Google наконец-то здесь!

http://developer.android.com/tools/building/multidex.html

Только один маленький совет, вам, вероятно, придется сделать это, чтобы предотвратить нехватку памяти при выполнении дексинга.

dexOptions {
        javaMaxHeapSize "4g"
}

Есть также гигантский режим, который может исправить это менее надежным способом:

dexOptions {
        jumboMode true
}

Обновление: если ваше приложение толстое и у вас слишком много методов внутри основного приложения, вам может потребоваться переорганизовать ваше приложение согласно

http://blog.osom.info/2014/12/too-many-methods-in-main-dex.html

12 ответов

Решение

Обновление 3 (03.11.2014)
Google наконец-то выпустил официальное описание.


Обновление 2 (31.10.2014)
Плагин Gradle v0.14.0 для Android добавляет поддержку multi-dex. Чтобы включить, вы просто должны объявить это в build.gradle:

android {
   defaultConfig {
      ...
      multiDexEnabled  true
   }
}

Если ваше приложение поддерживает Android до 5.0 (то есть, если ваш minSdkVersion равно 20 или ниже) вам также необходимо динамически исправлять приложение ClassLoader, чтобы оно могло загружать классы из вторичных приставок. К счастью, есть библиотека, которая сделает это за вас. Добавьте его в зависимости вашего приложения:

dependencies {
  ...
  compile 'com.android.support:multidex:1.0.0'
} 

Вы должны вызвать код исправления ClassLoader как можно скорее. MultiDexApplication Документация класса предлагает три способа сделать это (выберите один из них, наиболее удобный для вас):

1 - объявить MultiDexApplication класс как приложение в вашем AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.android.multidex.myapplication">
    <application
        ...
        android:name="android.support.multidex.MultiDexApplication">
        ...
    </application>
</manifest>

2 - есть ваш Application класс расширяет класс MultiDexApplication:

public class MyApplication extends MultiDexApplication { .. }

3 - Позвонить MultiDex#install от твоего Application#attachBaseContext метод:

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

Обновление 1 (17.10.2014):
Как и ожидалось, поддержка multidex поставляется в редакции 21 библиотеки поддержки Android. Вы можете найти android-support-multidex.jar в папке /sdk/extras/android/support/multidex/library/libs.


Поддержка Multi-Dex решает эту проблему. dx 1.8 уже позволяет создавать несколько файлов dex.
Android L будет поддерживать multi-dex изначально, и следующая версия библиотеки поддержки будет охватывать более старые выпуски назад к API 4.

Об этом заявил Анвар Гулум в этом эпизоде ​​подкастов для разработчиков Android за кулисами. Я разместил стенограмму (и общее объяснение мульти-декс) соответствующей части.

Как уже говорилось, у вас слишком много методов (более 65 тыс.) В вашем проекте и библиотеках.

Предотвратите проблему: уменьшите количество методов с помощью Play Services 6.5+ и support-v4 24.2+

Поскольку сервисы Google Play часто являются одними из основных подозреваемых в "потере" методов с помощью методов 20k+. Сервисы Google Play версии 6.5 или выше, вы можете включить сервисы Google Play в свое приложение, используя несколько небольших клиентских библиотек. Например, если вам нужны только GCM и карты, вы можете использовать только эти зависимости:

dependencies {
    compile 'com.google.android.gms:play-services-base:6.5.+'
    compile 'com.google.android.gms:play-services-maps:6.5.+'
}

Полный список библиотек и их обязанности можно найти в официальном документе Google.

Обновление: Начиная с версии v4.2.0 библиотеки поддержки v4.2.0 она была разделена на следующие модули:

support-compat, support-core-utils, support-core-ui, support-media-compat а также support-fragment

dependencies {
    compile 'com.android.support:support-fragment:24.2.+'
}

Обратите внимание, однако, если вы используете support-fragment, он будет иметь зависимости от всех других модулей (т. е. если вы используете android.support.v4.app.Fragment нет пользы)

Смотрите здесь официальные заметки о выпуске для support-v4 lib


Включить MultiDexing

С Lollipop (он же инструменты для сборки 21+) с ним очень легко работать. Подход заключается в том, чтобы обойти проблему 65k методов на файл dex, чтобы создать несколько файлов dex для вашего приложения. Добавьте следующее в ваш файл сборки Gradle ( это взято из официального документа Google по приложениям с более чем 65k методами):

android {
    compileSdkVersion 21
    buildToolsVersion "21.1.0"

    defaultConfig {
        ...
        // Enabling multidex support.
        multiDexEnabled true
    }
    ...
}

dependencies {
  compile 'com.android.support:multidex:1.0.1'
}

Вторым шагом является либо подготовка вашего класса приложения, либо, если вы не расширяете приложение, используйте MultiDexApplication в вашем манифесте Android:

Либо добавьте это в ваш Application.java

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

или используйте предоставленное приложение от mutlidex lib

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.android.myapplication">
    <application
        ...
        android:name="android.support.multidex.MultiDexApplication">
        ...
    </application>
</manifest>

Предотвратить OutOfMemory с MultiDex

Как дальнейший совет, если вы столкнетесь с OutOfMemory исключения на этапе сборки вы можете увеличить кучу с

android {
    ...
    dexOptions {
        javaMaxHeapSize "4g"
    }
}

что бы установить кучу до 4 гигабайт.

Смотрите этот вопрос для более подробной информации о проблеме памяти кучи dex.


Проанализируйте источник проблемы

Для анализа источника методов плагин gradle https://github.com/KeepSafe/dexcount-gradle-plugin может помочь в сочетании с деревом зависимостей, предоставляемым gradle, например:

.\gradlew app:dependencies

Смотрите этот ответ и вопрос для получения дополнительной информации о методе подсчета в Android

Ваш проект слишком велик. У тебя слишком много методов. В одном приложении может быть только 65536 методов. см. здесь https://code.google.com/p/android/issues/detail?id=7147

Приведенный ниже код помогает, если вы используете Gradle. Позволяет легко удалить ненужные службы Google (если вы используете их), чтобы вернуться к порогу ниже 65 КБ. Все кредиты на этот пост: https://gist.github.com/dmarcato/d7c91b94214acd936e42

Редактировать 2014-10-22: Было много интересных обсуждений по теме, упомянутой выше. TLDR? посмотрите на это: https://gist.github.com/Takhion/10a37046b9e6d259bb31

Вставьте этот код внизу файла build.gradle и настройте список ненужных вам служб Google:

def toCamelCase(String string) {
    String result = ""
    string.findAll("[^\\W]+") { String word ->
        result += word.capitalize()
    }
    return result
}

afterEvaluate { project ->
    Configuration runtimeConfiguration = project.configurations.getByName('compile')
    ResolutionResult resolution = runtimeConfiguration.incoming.resolutionResult
    // Forces resolve of configuration
    ModuleVersionIdentifier module = resolution.getAllComponents().find { it.moduleVersion.name.equals("play-services") }.moduleVersion

    String prepareTaskName = "prepare${toCamelCase("${module.group} ${module.name} ${module.version}")}Library"
    File playServiceRootFolder = project.tasks.find { it.name.equals(prepareTaskName) }.explodedDir

    Task stripPlayServices = project.tasks.create(name: 'stripPlayServices', group: "Strip") {
        inputs.files new File(playServiceRootFolder, "classes.jar")
        outputs.dir playServiceRootFolder
        description 'Strip useless packages from Google Play Services library to avoid reaching dex limit'

        doLast {
            copy {
                from(file(new File(playServiceRootFolder, "classes.jar")))
                into(file(playServiceRootFolder))
                rename { fileName ->
                    fileName = "classes_orig.jar"
                }
            }
            tasks.create(name: "stripPlayServices" + module.version, type: Jar) {
                destinationDir = playServiceRootFolder
                archiveName = "classes.jar"
                from(zipTree(new File(playServiceRootFolder, "classes_orig.jar"))) {
                    exclude "com/google/ads/**"
                    exclude "com/google/android/gms/analytics/**"
                    exclude "com/google/android/gms/games/**"
                    exclude "com/google/android/gms/plus/**"
                    exclude "com/google/android/gms/drive/**"
                    exclude "com/google/android/gms/ads/**"
                }
            }.execute()
            delete file(new File(playServiceRootFolder, "classes_orig.jar"))
        }
    }

    project.tasks.findAll { it.name.startsWith('prepare') && it.name.endsWith('Dependencies') }.each { Task task ->
        task.dependsOn stripPlayServices
    }
}

Я поделился примером проекта, который решает эту проблему, используя скрипт сборки custom_rules.xml и несколько строк кода.

Я использовал его в своем собственном проекте, и он работает безупречно на устройствах 1M+ (от Android-8 до последней Android-19). Надеюсь, поможет.

https://github.com/mmin18/Dex65536

Столкнулся с той же проблемой и решил ее, отредактировав мой файл build.gradle в разделе зависимостей, удалив:

compile 'com.google.android.gms:play-services:7.8.0'

И заменить его на:

compile 'com.google.android.gms:play-services-location:7.8.0'
compile 'com.google.android.gms:play-services-analytics:7.8.0' 

Попробуйте добавить код ниже в build.gradle, у меня это сработало -

compileSdkVersion 23
buildToolsVersion '23.0.1'
defaultConfig {
    multiDexEnabled true
}

Вы можете проанализировать проблему (ссылки на файлы dex) с помощью Android Studio:

Построить -> Анализировать APK ..

На панели результатов нажмите на файл classes.dex

И вы увидите:

введите описание изображения здесь

Идеальным решением для этого было бы работать с Proguard. как упомянуто в комментарии. Это уменьшит размер файла dex вдвое.

Gradle + Proguard решение:

afterEvaluate {
  tasks.each {
    if (it.name.startsWith('proguard')) {
        it.getInJarFilters().each { filter ->
            if (filter && filter['filter']) {
                filter['filter'] = filter['filter'] +
                        ',!.readme' +
                        ',!META-INF/LICENSE' +
                        ',!META-INF/LICENSE.txt' +
                        ',!META-INF/NOTICE' +
                        ',!META-INF/NOTICE.txt' +
                        ',!com/google/android/gms/ads/**' +
                        ',!com/google/android/gms/cast/**' +
                        ',!com/google/android/gms/games/**' +
                        ',!com/google/android/gms/drive/**' +
                        ',!com/google/android/gms/wallet/**' +
                        ',!com/google/android/gms/wearable/**' +
                        ',!com/google/android/gms/plus/**' +
                        ',!com/google/android/gms/topmanager/**'
            }
        }
    }
  }
}

Я столкнулся с той же проблемой сегодня, что работало ниже

Для ANDROID STUDIO... Включить мгновенный запуск

В File->Preferences->Build, Execution, Deployment->Instant Run-> Check Enable Instant run для горячей замены...

Надеюсь, поможет

Удалите файл JAR из папки Libs и скопируйте в другую папку. И перейдите в _Project Properties > Выберите Java Build Path, выберите "Библиотеки", выберите "Добавить внешний JAR", выберите "Удаленный JAR-файл" в свой проект, нажмите "Сохранить", это будет добавлено в разделе "Ссылки". Библиотека вместо папки Libs. Теперь очистите и запустите ваш проект. Вам не нужно добавлять любой код для MultDex. Это просто сработало для меня.

Другие вопросы по тегам