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

344

Я уже видел разные версии 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

Эдисон
источник
1
Используете ли вы API, который недоступен на вашем устройстве Currient?
rekire
Это так, потому что другой проект прекрасно работает с той же версией API.
Эдисон
Так вы используете в какой-то момент API, который не доступен? Проверяете ли вы такой строкой, if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)что не вызываете эту функцию, если она недоступна?
rekire
Да, я делаю. Проект построен хорошо раньше. Кроме того, это должно быть ошибкой во время выполнения, даже если я пропустил строку.
Эдисон
Это, вероятно, одна из зависимостей испорчена. (сейчас делаю смесь из maven + project lib)
Edison

Ответы:

379

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


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

android {
   defaultConfig {
      ...
      multiDexEnabled  true
   }
}

Если ваше приложение поддерживает Android до 5.0 (т. Е. Если вам minSdkVersion20 или ниже), вы также должны динамически исправлять приложение 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 за кулисами. Я разместил стенограмму (и общее объяснение мульти-декс) соответствующей части.

Алекс Липов
источник
2
сообщение в блоге это заставка! : D
надавфима
39
Что-нибудь для пользователей затмения?
Мухаммед Бабар,
52
@MuhammadBabar Для пользователей Eclipse существует Android-студия.
VipulKumar
2
@ MohammedAli Конечно, не используйте его, если можете. Но то , что вы должны делать , если вы действительно слишком много методов в вашем приложении, и вы уже пробовали все приемы , как тот , который вы упомянули? Что касается времени сборки - есть решение для этого, по крайней мере, для сборок для разработки - смотрите мой ответ здесь: stackoverflow.com/a/30799491/1233652
Алекс Липов
2
На Qt для Android у меня были проблемы во время выполнения для моего приложения при интеграции вместе SDK Facebook + Twitter, даже после включения поддержки мультидекса (эта ошибка, в частности, вызывала у меня кошмары :) java.lang.ClassNotFoundException: Didn't find class "org.qtproject.qt5.android.QtActivityDelegate" on path: DexPathList[[],nativeLibraryDirectories=[/vendor/lib, /system/lib]]. Оказалось, что моя ошибка заключалась в том, что я не применял дополнительные шаги для поддержки Android до 5.0. С учетом сказанного, вариант № 3 решил это, и у меня больше не было ClassNotFoundExceptionпроблем. Спасибо, @ Алекс Липов!
ограбить
78

Как уже говорилось, у вас слишком много методов (более 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 .

Обновление : начиная с версии Support Library v4 v24.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

Патрик Фавр
источник
Я использовал решение Play Services 6.5+, и оно работало отлично. Невероятно полезный совет. Спасибо!
Хоанг Нгуен Хуу
Я бы поддержал больше, если бы мог - исключив все другие сервисы Play Services, которые мы не использовали, исправил эту проблему, не прибегая к мультидексам, что отрицательно сказывается на производительности при сборке.
Шон Барбо
1
Чем ты так со слезами на глазах. Вы спасли меня
бессонница
Я использовал клиентскую библиотеку для GCM, потому что я использую только сервис gcm из сервиса play, теперь это исправило мою проблему с этим. Спасибо! чтобы сэкономить мое время.
Анкит
57

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

blobbie
источник
Понимаю. У меня много зависимостей для этого проекта. Он прекрасно работает до того, как я перешел на использование maven, хотя, возможно, maven добавил ненужные зависимости. Буду перепроверять.
Эдисон
5
Точнее, в исполняемом (dex) файле Dalvik может быть только 65 536 методов. И приложение (APK) может иметь более одного файла dex с такими функциями, как пользовательская загрузка.
Деннис Шейл
7
Это действительно неловкая ошибка для Android! Во всяком случае, в моем случае я удалил Jar, который был в библиотеках и не использовался, и приложение скомпилировано
David
Время навести порядок в моем проекте: /
Decoy
1
Быстрое решение проблемы - использовать Proguard также с отладочными сборками
aleb
12

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

Edit 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
    }
}
тыс.куб.м
источник
Любить это! Требуется def, поскольку такие компании, как Google, продолжают раздувать пакеты.
Эдисон
1
Хорошо - это сделало работу на месте. Никаких хлопот и забот!
slott
Примечание: это удаленные баночки сервисов Google Play в моем Android SDK в Android Studio! Плохая идея, поскольку вернуться к оригинальным банкам нелегко. Автор должен изменить скрипт для изменения jar-файлов в каталоге сборки.
индекс
@inder: у меня не было этой проблемы. Однако мне приходилось делать cleanкаждый раз, когда я связывался с исключениями (мы используем аналитику).
JohnnyLambada
как исключить это из релизных сборок?
user1324936
6

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

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

https://github.com/mmin18/Dex65536

Mmin
источник
1
Спасибо за сценарии. Вы должны остерегаться АРТ. Устройство может конвертировать только ваши dex по умолчанию, а не второстепенные. Решения Proguard должны быть предпочтительными.
Эдисон
2
Когда я импортирую проекты в Eclipse и запускаю, это дает ошибку. Msgstr "Невозможно выполнить dex: ID метода не в [0, 0xffff]: 65536". Можете ли вы объяснить использование проекта
Каракаго
6

Столкнулся с той же проблемой и решил ее, отредактировав мой файл 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' 
Луис Мигель Бальестас
источник
Отлично! Я просто использую Google Drive API, и это работает.
Ведавис
5

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

compileSdkVersion 23
buildToolsVersion '23.0.1'
defaultConfig {
    multiDexEnabled true
}
Санита
источник
2

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

shimi_tap
источник
1
Согласился, с все более и более большим jar сервисов Google Play, особенно * (18k методов само по себе)
Эдисон
2

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

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

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

И вы увидите:

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

alexshr
источник
0

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/**'
            }
        }
    }
  }
}
Олег Халидов
источник
0

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

Лакшманан
источник
0

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

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

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

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

Абдул Вахид
источник
1
Это сработало для меня - я просто отключил Enable Run, нажал Apply, снова включил его, и он снова заработал.
Мистер Бигглсворт,