Ошибка MultiDex NoClassDefFound
Я конвертировал свое приложение в MultiDex, чтобы иметь ограничение 64k dex. Теперь это выглядит так:
public class App extends MultiDexApplication {
private AppWrapper instance;
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
MultiDex.install(base);
}
@Override
public void onCreate() {
super.onCreate();
if (instance == null) {
instance = new AppWrapper(this);
}
}
}
Я вытащил всю обычную логику из приложения в AppWidget
, чтобы сделать работу MultiDex
. И он работает нормально на компьютерах других товарищей по команде. Но не со мной. Он продолжает метать java.lang.NoClassDefFoundError
при создании приложения:
I/dalvikvm﹕ Failed resolving Lcom/playday/app/core/AppWrapper; interface 8940 'Lretrofit/ErrorHandler;'
W/dalvikvm﹕ Link of class 'Lcom/playday/app/core/AppWrapper;' failed
I/dalvikvm﹕ Failed resolving Lcom/playday/app/core/AppWrapper; interface 8940 'Lretrofit/ErrorHandler;'
W/dalvikvm﹕ Link of class 'Lcom/playday/app/core/AppWrapper;' failed
E/dalvikvm﹕ Could not find class 'com.playday.app.core.AppWrapper', referenced from method com.playday.app.core.App.onCreate
W/dalvikvm﹕ VFY: unable to resolve new-instance 7076 (Lcom/playday/app/core/AppWrapper;) in Lcom/playday/app/core/App;
D/dalvikvm﹕ VFY: replacing opcode 0x22 at 0x0007
I/dalvikvm﹕ Failed resolving Lcom/playday/app/core/AppWrapper; interface 8940 'Lretrofit/ErrorHandler;'
W/dalvikvm﹕ Link of class 'Lcom/playday/app/core/AppWrapper;' failed
D/dalvikvm﹕ DexOpt: unable to opt direct call 0xc21b at 0x09 in Lcom/playday/app/core/App;.onCreate
I/MultiDex﹕ VM with version 1.6.0 does not have multidex support
I/MultiDex﹕ install
I/MultiDex﹕ MultiDexExtractor.load( /data/app/com.playdayteam.playday.debug-1.apk, false)
I/MultiDex﹕ Detected that extraction must be performed.
I/MultiDex﹕ Trying to delete old file /data/data/com.playdayteam.playday.debug/code_cache/secondary-dexes/com.playdayteam.playday. debug-2.apk.classes2.dex of size 1484912
I/MultiDex﹕ Deleted old file /data/data/com.playdayteam.playday.debug/code_cache/secondary-dexes/com.playdayteam.playday.debug-2 .apk.classes2.dex
I/MultiDex﹕ Trying to delete old file /data/data/com.playdayteam.playday.debug/code_cache/secondary-dexes/com.playdayteam.playday. debug-2.apk.classes2.zip of size 540964
I/MultiDex﹕ Deleted old file /data/data/com.playdayteam.playday.debug/code_cache/secondary-dexes/com.playdayteam.playday.debug-2 .apk.classes2.zip
D/dalvikvm﹕ GC_CONCURRENT freed 186K, 11% free 3245K/3640K, paused 2ms+4ms, total 28ms
D/dalvikvm﹕ WAIT_FOR_CONCURRENT_GC blocked 5ms
D/dalvikvm﹕ GC_CONCURRENT freed 156K, 8% free 3593K/3904K, paused 3ms+2ms, total 22ms
I/MultiDex﹕ Extraction is needed for file /data/data/com.playdayteam.playday.debug/code_cache/secondary-dexes/com.playdayteam. playday.debug-1.apk.classes2.zip
I/MultiDex﹕ Extracting /data/data/com.playdayteam.playday.debug/code_cache/secondary-dexes/com.playdayteam.playday.debug-1 .apk.classes576886388.zip
I/MultiDex﹕ Renaming to /data/data/com.playdayteam.playday.debug/code_cache/secondary-dexes/com.playdayteam.playday.debug-1 .apk.classes2.zip
I/MultiDex﹕ Extraction success - length /data/data/com.playdayteam.playday.debug/code_cache/secondary-dexes/com.playdayteam.playday. debug-1.apk.classes2.zip: 540964
I/MultiDex﹕ load found 1 secondary dex files
D/dalvikvm﹕ DexOpt: --- BEGIN 'com. playdayteam.playday.debug-1.apk.classes2.zip' (bootstrap=0) ---
D/dalvikvm﹕ DexOpt: --- END 'com. playdayteam.playday.debug-1.apk.classes2.zip' (success) ---
D/dalvikvm﹕ DEX prep '/data/data/com .playdayteam.playday.debug/code_cache/secondary-dexes/com.playdayteam.playday.debug-1.apk.classes2. zip': unzip in 28ms, rewrite 387ms
I/MultiDex﹕ install done
I/MultiDex﹕ install
D/AndroidRuntime﹕ Shutting down VM
W/dalvikvm﹕ threadid=1: thread exiting with uncaught exception (group=0x41c1d930)
E/AndroidRuntime﹕ FATAL EXCEPTION: main
java.lang.NoClassDefFoundError: com.playday.app.core.AppWrapper
at com.playday.app.core.App.onCreate(App.java:22)
at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1006)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4457)
at android.app.ActivityThread.access$1300(ActivityThread.java:142)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1332)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5105)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
at dalvik.system.NativeStart.main(Native Method)
У меня есть те же версии Android Studio, gradle, sdk, jdk, тот же код. Я даже пытался отформатировать жесткий диск и переустановить ОС, чтобы убедиться, что среда такая же. Что может быть причиной этой странной проблемы?
Это мой build.gradle
:
apply plugin: 'com.android.application'
repositories {
maven { url 'http://dl.bintray.com/populov/maven' }
mavenCentral()
maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' }
}
android {
compileSdkVersion project.api_level
buildToolsVersion project.build_tools_version
defaultConfig {
minSdkVersion 14
targetSdkVersion project.api_level
}
sourceSets {
instrumentTest.setRoot('src/test')
}
packagingOptions {
exclude 'META-INF/LICENSE.txt'
exclude 'META-INF/LICENSE'
exclude 'META-INF/NOTICE.txt'
exclude 'META-INF/NOTICE'
exclude 'META-INF/ASL2.0'
exclude 'AndroidManifest.xml'
}
defaultConfig {
versionName "0.3.2"
versionCode 23
}
buildTypes {
debug {
debuggable true
applicationIdSuffix ".debug"
}
beta {
debuggable true
signingConfig signingConfigs.release
applicationIdSuffix ".beta"
}
release {
signingConfig signingConfigs.release
runProguard false
proguardFile file('proguard-rules.txt')
proguardFile getDefaultProguardFile('proguard-android-optimize.txt')
}
}
dexOptions {
incremental false
preDexLibraries false
}
}
dependencies {
compile "com.android.support:support-v13:$project.support_lib_version"
compile "com.android.support:support-v4:$project.support_lib_version"
compile "com.android.support:appcompat-v7:$project.support_lib_version"
compile 'com.google.android.gms:play-services:6.1.11'
compile('de.keyboardsurfer.android.widget:crouton:[email protected]') {
exclude group: 'com.google.android', module: 'support-v4'
}
compile('com.octo.android.robospice:robospice:1.4.14'){
exclude group: 'commons-io', module: 'commons-io'
}
compile('com.octo.android.robospice:robospice-retrofit:1.4.14'){
exclude group: 'commons-io', module: 'commons-io'
}
compile 'com.squareup.retrofit:retrofit:1.6.1'
compile 'com.google.code.gson:gson:2.3'
compile 'com.viewpagerindicator:library:[email protected]'
compile 'com.squareup.picasso:picasso:2.3.3'
compile 'com.squareup.okhttp:okhttp:2.0.0'
compile 'com.squareup.okhttp:okhttp-urlconnection:2.0.0'
compile 'com.etsy.android.grid:library:1.0.5'
compile 'com.squareup:otto:1.3.4'
compile 'com.darwinsys:hirondelle-date4j:1.5.1'
compile 'com.github.chrisbanes.photoview:library:1.2.3'
compile 'me.grantland:autofittextview:0.2.0'
compile 'it.sephiroth.android.library.horizontallistview:library:1.2.1'
compile 'org.ocpsoft.prettytime:prettytime:3.2.4.Final'
compile 'com.google.guava:guava:18.0'
compile 'com.github.castorflex.smoothprogressbar:library:0.5.2'
compile 'com.makeramen:roundedimageview:1.3.0'
compile 'org.lucasr.twowayview:twowayview:0.1.1'
compile 'com.michaelpardo:activeandroid:3.1.0-SNAPSHOT'
compile project(':libs:LoopingViewPager')
compile project(':libs:PhotoView-2.2.1')
compile files('libs/localytics.jar')
compile files('libs/android-support-multidex.jar')
compile 'net.hockeyapp.android:HockeySDK:3.0.2'
}
afterEvaluate {
tasks.matching {
it.name.startsWith('dex')
}.each { dx ->
if (dx.additionalParameters == null) {
dx.additionalParameters = []
}
dx.additionalParameters += '--multi-dex' // enable multidex
dx.additionalParameters += "--main-dex-list=$projectDir/multidex.keep".toString()
}
}
Update. Мой multidex.keep
файл:
android/support/multidex/BuildConfig.class
android/support/multidex/MultiDex$V14.class
android/support/multidex/MultiDex$V19.class
android/support/multidex/MultiDex$V4.class
android/support/multidex/MultiDex.class
android/support/multidex/MultiDexApplication.class
android/support/multidex/MultiDexExtractor$1.class
android/support/multidex/MultiDexExtractor.class
android/support/multidex/ZipUtil$CentralDirectory.class
android/support/multidex/ZipUtil.class
com/playday/app/models/notification/Badge.class
com/playday/app/models/User.class
com/playday/app/core/AppWrapper.class
com/playday/app/core/App.class
Ответы
Ответ 1
Класс AppWrapper не загружается, потому что интерфейс retrofit.ErrorHandler не включен в основной файл dex.
Как вы вычисляете, какие классы помещать в ваш файл файл-dex-list?
Там script, который может сгенерировать его для вас. Я написал blogpost, в котором показано, как его использовать.
Обновление (10/31/2014):
Gradle плагин v0.14.0 теперь делает это автоматически. См. Мой ответ здесь.
Обновление (24/04/2017):
В руководстве объясняется, как выбрать определенные классы с опцией gradle, если он не выбирает все правильные автоматически.
Ответ 2
если все выглядит нормально, но появляется эта ошибка,
попробуйте отключить мгновенный запуск!!!
когда я отключил его, все классы были загружены правильно.
Ответ 3
Если вы расширяете MultiDexApplication, вам не нужно делать вызов MultiDex.install(контекст), как это уже происходит (см. ссылку источника). Если вам нужно использовать attachBaseContext, просто убедитесь, что вы вызываете super.attachBaseContext(контекст).
https://android.googlesource.com/platform/frameworks/multidex/+/1bb1ab007f6b9405227ea4ce07d2061e4dbb6fe0/library/src/android/support/multidex/MultiDexApplication.java
Мы только что обновили developers.android.com с инструкциями о том, как использовать библиотеку поддержки с плагином Android gradle, включая оптимизацию разработки для быстрого цикла сборки разработки.
https://developer.android.com/tools/building/multidex.html
Ответ 4
Если кто-то попадет сюда, потому что их класс Application не найден на устройствах до Lollipop, но приложение отлично работает на Lollipop и выше, это, похоже, известная проблема с Jack и Multidex.
Ссылка: Jack Issue 213484
Ссылка: Jack Issue 224026
Ответ 5
NoClassDefFound
может произойти с любым произвольным классом, который не загружался на устройстве с API раньше Lollipop и с поддержкой multidex. Если вы правильно настроили ProGuard, вы можете легко обойтись без дополнительных накладных расходов MultiDex, чтобы приложение медленно запускалось для ваших выпусков, особенно на старых устройствах. Однако вы не хотите, чтобы ProGuard замедлял работу, когда вы разрабатываете приложение в режиме отладки. Если вы попытаетесь запустить сборку отладки с отключенным ProGuard, вы начнете получать ошибки сборки, например, com.android.dex.DexIndexOverflowException: не может объединить новый индекс 72118 в инструкцию, отличную от jumbo!
Итак, что вы действительно хотите, это ProGuard enabled и multidex отключены только в сборках релизов, в то время как отладочные сборки должны быть противоположны с отключением Proguard и поддержкой multidex. Вы также должны быть разборчивы и использовать меньше зависимостей, конечно, потому что ваша версия release будет подвержена пределу 64K.
Для этого требуется установить build.gradle для конфигурации buildTypes
и компиляции зависимостей библиотеки поддержки нескольких приложений только для отладки.
Подкласс приложения также должен быть установлен для другого подкласса в зависимости от того, находитесь ли вы в режиме мультидетекса или нет. Это может быть достигнуто с помощью принципа слияния манифеста градиента, путем определения манифеста переопределения для вашей сборки отладки и последующего указания вашего класса приложения по-разному.
Вот соответствующий модуль приложения build.gradle:
android {
... buildTypes { debug { minifyEnabled false//Отключено Proguard multiDexEnabled true//Включение поддержки multi-dex. } выпуск { minifyEnabled true//Enabled Proguard proguardFiles getDefaultProguardFile ('proguard-android.txt'), 'proguard-rules.pro' multiDexEnabled false//Отключить поддержку multi-dex. } } зависимостей { debugCompile 'com.android.support:multidex:1.0.1'//debugCompile делает его включенным только для отладочных сборников ... }
}
Код>
Если вы не используете подкласс приложения, все, что вам нужно сделать, это указать имя подкласса Application android.support.multidex.MultiDexApplication
, как указано в https://developer.android.com/studio/build/multidex.html, но вы хотите сделать это только для вашей сборки отладки.
Для этого вам нужно указать переопределение файлов в иерархии папок версии отладки и версии, например:
<Предварительно > <код > ЦСИ - главный - AndroidManifest.xml - java/com/yourcompany/MyApplication.java(распространяется от BaseApplication) - выпуск - java/com/yourcompany/BaseApplication.java(распространяется от приложения) - отладка - AndroidManifest.xml - java/com/yourcompany/BaseApplication.java(распространяется от MultiDexApplication)
Код > Да, вы создаете папки debug
и release
рядом с папкой вашего основного модуля. Добавьте следующие файлы:
отлаживать /AndroidManifest.xml
<? xml version = "1.0" encoding = "utf-8"? >
< manifest xmlns: android = "http://schemas.android.com/apk/res/android" XMLNS: инструменты = "http://schemas.android.com/tools" > & Л; приложение Android: name= "com.yourcompany.MyApplication" Инструменты: заменить = "Android: имя" />
& Л; /& манифеста GT;
Код>
Этот манифест будет включен только в сборку отладки и будет проигнорирован для вашей версии.
релиз /Java/COM/yourcompany/BaseApplication.java
Открытый класс BaseApplication расширяет Приложение {
}
Код>
отлаживать /Java/COM/yourcompany/BaseApplication.java
Открытый класс BaseApplication расширяет MultiDexApplication {
}
Код>
главная /Java/COM/yourcompany/MyApplication.java
открытый класс MyApplication расширяет BaseApplication { @Override public void onCreate() { super.onCreate(); // Инициализация базы данных и т.д.; }
}
Код>
Таким образом, вы можете добавить функциональность вашего приложения в MyApplication.java
, имея разные базовые классы.
Ответ 6
У меня также возникла такая проблема. Решение в моем случае было:
В моем файле build.gradle в зависимостях было несколько записей compile 'com.android.support:multidex:1.0.0'
. как:
dependencies {
compile 'com.android.support:multidex:1.0.0'
compile 'com.android.support:multidex:1.0.0'
// other dependencies ........
}
просто поместите только один компилятор 'com.android.support:multidex:1.0.0' как:
dependencies {
compile 'com.android.support:multidex:1.0.0'
// other dependencies ........
}
Ответ 7
Я, наконец, решил! Причина не в методе onCreate()
. Эта линия от logcat, которая привлекла мое внимание:
I/dalvikvm﹕ Failed resolving Lcom/playday/app/core/AppWrapper; interface 8940 'Lretrofit/ErrorHandler;'
W/dalvikvm﹕ Link of class 'Lcom/playday/app/core/AppWrapper;' failed
Эта строка запускается перед всем журналом MultiDex. Источником проблемы был интерфейс Retrofit ErrorHandler
, который реализуется AppWrapper
.
Как сказал @AlexLipov в своем ответе, Dalvik просто не смог найти класс ErrorHandler
и не смог загрузить AppWrapper
.
В любом случае решение не реализовать ErrorHandler
напрямую AppWrapper
и вместо этого вставить его в закрытую переменную.
Ответ 8
Я пробовал много решений, но у меня никто не работал. Наконец я нашел это:
public class MyApplication extends Application {
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
MultiDex.install(this);
}
}
И был единственным решением для моей проблемы. Может быть, у кого-то такая же проблема, и это может помочь :)