Невозможно разместить запрошенные классы в одном файле dex, даже для более ранних коммитов, которые скомпилировались ранее

6

Итак, я только что установил максимальный предел количества методов для моего проекта Android, который не может быть собран со следующим сообщением об ошибке:

Ошибка: ноль, невозможно разместить запрошенные классы в одном файле dex (# методы: 117407> 65536)

Я понимаю, что означает сообщение, и как его разрешить (запустить proguard, включить multidex и т.д.). Моя проблема в том, что я не понимаю, почему я внезапно получаю это сообщение - я делал, удалял некоторые старые фрагменты кода, которые были избыточными, выполнял сборку, и теперь я получаю это сообщение.

Вопрос 1: Как может быть так, что число моих методов (117407 согласно сообщению об ошибке) внезапно значительно превысило предел (65536), даже если я не добавил никаких библиотечных зависимостей? Я на самом деле удалил код, и вдруг у меня как 50 тысяч методов слишком много?

Вот где это становится действительно странным: я хотел проанализировать APK, чтобы выяснить причину проблемы, но, конечно, я не могу ее построить. Поэтому вместо того, чтобы включить multidex, я решил вернуть свой код на вчерашний день (который, безусловно, отлично сработал вчера - у меня есть приложение на телефоне, чтобы доказать это!), Но я все еще получаю это сообщение об ошибке сборки. Я не понимаю, как это возможно. Я попытался вернуться к тому же несколько дней назад (клонирование нового репо и проверка более раннего коммита).

Итак, вопрос 2: Как я получаю эту ошибку сборки для точно такого же кода, который только вчера был построен без ошибок?

Единственное, о чем я могу думать, это то, что библиотека, которую я использую как зависимость, внезапно увеличилась в размере - но я объявляю конкретные версии всего, что есть в моей сборке Gradle, например:

// RxJava
implementation 'io.reactivex.rxjava2:rxandroid:2.1.0'
implementation 'io.reactivex.rxjava2:rxjava:2.2.4'

// Retrofit
implementation 'com.squareup.retrofit2:retrofit:2.5.0'
implementation 'com.squareup.retrofit2:converter-gson:2.5.0'

Так что, конечно, мои зависимости не должны были измениться?

Любые идеи, что я могу сделать, чтобы понять это, с благодарностью. Я попытался очистить свой проект и сделать недействительными кэши/перезапустить в Android Studio. Я действительно не хочу включать multidex или запускать proguard в моей отладочной сборке.

Вот полный build.gradle:

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'

android {
    compileSdkVersion 28
    defaultConfig {
    applicationId "XXXXXXXXX"
    minSdkVersion 19
    targetSdkVersion 28
    versionCode 1
    versionName "0.1"
    testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    vectorDrawables.useSupportLibrary = true  // see https://developer.android.com/studio/write/vector-asset-studio#sloption
}
buildTypes {
    release {
        minifyEnabled false
        // Do code shrinking!
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
}
}

dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])

// Core stuff
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support:recyclerview-v7:28.0.0'
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 'android.arch.lifecycle:extensions:1.1.1'
implementation 'com.android.support:design:28.0.0'
implementation 'com.android.support:support-vector-drawable:28.0.0'
implementation 'com.google.android.gms:play-services-wearable:16.0.1'

// Dagger
implementation 'com.google.dagger:dagger:2.21'
kapt 'com.google.dagger:dagger-compiler:2.21'
// Dagger for Android
implementation 'com.google.dagger:dagger-android:2.21'
implementation 'com.google.dagger:dagger-android-support:2.21' // if you use the support libraries
kapt 'com.google.dagger:dagger-android-processor:2.21'

// Constraint layout
implementation 'com.android.support.constraint:constraint-layout:1.1.3'

// Associated WearOS project
wearApp project(':wear')

// Common library project
implementation project(':common')

// These were added to resolve gradle error on the 'com.android.support:appcompat-v7:28.0.0' implementation:
// All com.android.support libraries must use the exact same version specification (mixing versions can lead to
// runtime crashes). Found versions 28.0.0, 26.1.0. Examples include com.android.support:animated-vector-drawable:28.0.0
// and com.android.support:support-media-compat:26.1.0
// This seems to be related to linking the wear project. If the wear project was not linked, the error went away.
implementation 'com.android.support:support-media-compat:28.0.0'
implementation 'com.android.support:support-v4:28.0.0'

// RxJava
implementation 'io.reactivex.rxjava2:rxandroid:2.1.0'
implementation 'io.reactivex.rxjava2:rxjava:2.2.4'

// Retrofit
implementation 'com.squareup.retrofit2:retrofit:2.5.0'
implementation 'com.squareup.retrofit2:converter-gson:2.5.0'
// Retrofit RxJava
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.5.0'
// Retrofit logging:
implementation 'com.squareup.okhttp3:logging-interceptor:3.12.1'

// Room
def room_version = "1.1.1"
implementation "android.arch.persistence.room:runtime:$room_version"
implementation "android.arch.persistence.room:common:$room_version"
implementation "android.arch.persistence.room:rxjava2:$room_version"
kapt "android.arch.persistence.room:compiler:$room_version"

// For modern time handling (java.time requires API 26 or higher)
implementation 'com.jakewharton.threetenabp:threetenabp:1.1.1'

// Graphing
implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0-alpha'

// Dropbox
implementation 'com.dropbox.core:dropbox-core-sdk:3.0.11'

// OpenCSV
implementation 'com.opencsv:opencsv:4.5'

}

РЕДАКТИРОВАТЬ

Таким образом, после включения мультидекса при анализе APK с помощью Android Studio появляются некоторые серьезные зависимости в следующих TLD (я не уверен, стоит ли мне смотреть на определенные или упоминаемые номера методов?):

  • com.dropbox: 26000 определенных методов, 34000 ссылочных методов
  • com.android (в основном поддерживаемые библиотеки): определено 18700, указано 24600
  • org.apache (общие, логи и т.д.): определено 15000, указано 15700

Только они доводят меня до предела. Я до сих пор не понимаю, почему это внезапно происходит :( Конечно, если бы я не добавил никаких библиотек, эти цифры не должны были измениться?

Теги:
android-studio
android-gradle
dex

6 ответов

3
Лучший ответ

После просмотра всего файла сборки сборки ваша проблема определенно проистекает из ваших зависимостей! Попытайтесь очистить их и удалить как можно больше, которые вы не используете. Скорее всего, вы были очень близки к пределу, и любая из этих зависимостей могла быть кэширована с использованием более старых версий. Вы можете попытаться удалить всю папку сборки (и очистить кеш-память), но я уверен, что проблема не исчезнет.

Если все эти зависимости требуются, к сожалению, вам придется идти по маршрутам, которые вы упомянули, либо мульти-декс, либо минифицированные отладочные сборки. Multi-dex должен быть в порядке и не должен вызывать непредвиденных проблем, в то время как минификация замедлит ваши сборки и потенциально может привести к нестабильной работе Android Studio (особенно мгновенному запуску/применению изменений!)

Удачи, одна вещь, которую можно извлечь из этого, это сохранить ваши зависимости чистыми и точными, добавлять только тогда, когда это абсолютно необходимо, а если ничего не помогает, multi-dex - ваш друг.

  • 0
    Спасибо за вашу помощь! Я просто пытаюсь понять, почему счетчик методов внезапно взорвался почти вдвое. Я очень заинтригован вашей строкой «любая из этих зависимостей могла быть кэширована с использованием более старых версий» - это звучит как возможный ответ, вы можете объяснить дальше?
  • 0
    Gradle / AS кэширует совсем немного. Вполне возможно, что кеширование пошло не так (или странно правильно) и не сообщало о методах (возможно, даже обрезании некоторых зависимостей), которые не влияли на ваш код. Когда кеш устарел, или вы принудительно перестроили, gradle «исправил» сам себя и вызвал проблемы. Вы могли бы попытаться очистить все (все папки сборки, все остатки gradle, от всех связанных проектов) и посмотреть, изменит ли это что-нибудь, но я не уверен в этом.
Показать ещё 2 комментария
0

Просто добавьте это в ваш gradle (Модуль: приложение) >> multiDexEnabled true

android {
    defaultConfig {
        ...
        minSdkVersion 21 
        targetSdkVersion 28
        multiDexEnabled true
    }
    ...
}

затем перестроить проект в меню, нажмите => построить> перестроить проект.

  • 0
    Спасибо за предложение, но я уже включил мультидекс. Это не мой вопрос. Как я уже сказал в начале, «я понимаю, что означает сообщение и как его решить (запустить proguard, включить multidex и т. Д.). Моя проблема в том, что я не понимаю, почему я вдруг получаю это сообщение»
0

Я столкнулся с той же проблемой, и решением было включить Мгновенный запуск в меню Файл → Настройка → Сборка, Выполнение, Развертывание → Мгновенный запуск, и это решило мою проблему. Надеюсь, что это полезно.

0

В качестве вашей проблемы мне пришлось удалить папку build и файлы *.iml (файлы проекта Android Studio). Y Мне пришлось заново создать проект, затем сборку и все снова работало нормально.

0

После прочтения вашего вопроса я могу только предложить попробовать аннулировать кеш и перезапустить после и принудительно обновить вашу зависимость, используя это.

./gradlew build --refresh-dependencies
  • 0
    Спасибо, к сожалению, это не решило проблему
0

Я бы порекомендовал построить приложение с помощью multidex, а затем извлечь идентификаторы методов из нескольких файлов dex из нового apk, а также извлечь идентификаторы методов из старого apk с одним дексом и сравнить два списка.

примерно, что-то вроде:

baksmali list dex new.apk
baksmali list method new.apk/classes.dex > new.list
baksmali list method new.apk/classes2.dex >> new.list
sort new.list > new.sorted.list

baksmali list method old.apk > old.list
diff new.sorted.list old.list

Хотя, если вы используете proguard, вам может понадобиться найти способ применить обратное искажение имени proguard перед сравнением списков.

  • 0
    Спасибо, хотя, к сожалению, у меня нет старого APK для сравнения, и я не могу построить более ранние версии своего кода, что является странной частью. В итоге я включил multidex, а затем проанализировал APK с помощью android studio - см. Обновленный вопрос :)

Ещё вопросы

Сообщество Overcoder
Наверх
Меню