javaandroidjava-8

java.lang.NoClassDefFoundError: Failed resolution of: Ljava/time/Instant;


Currenty, I am unable to resolve the crash that is java.lang.NoClassDefFoundError: Failed resolution of: Ljava/time/Instant; Such crash happens with Android 7.1.1 (Nougat) and below. But my Oreo emulator runs Instant.parse(...) just fine.

Stacktrace:

java.lang.NoClassDefFoundError: Failed resolution of: Ljava/time/Instant;
                  at (application class)
                  at retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall$1$1.run(ExecutorCallAdapterFactory.java:70)
                  at android.os.Handler.handleCallback(Handler.java:751)
                  at android.os.Handler.dispatchMessage(Handler.java:95)
                  at android.os.Looper.loop(Looper.java:154)
                  at android.app.ActivityThread.main(ActivityThread.java:6119)
                  at java.lang.reflect.Method.invoke(Native Method)
                  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
                  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
               Caused by: java.lang.ClassNotFoundException: Didn't find class "java.time.Instant" on path: DexPathList[[zip file "/data/app/(app-domain)/base.apk", zip file "/data/app/(app-domain)/split_lib_dependencies_apk.apk", zip file "/data/app/(app-domain)/split_lib_slice_0_apk.apk", zip file "/data/app/(app-domain)/split_lib_slice_1_apk.apk", zip file "/data/app/(app-domain)/split_lib_slice_2_apk.apk", zip file "/data/app/(app-domain)/split_lib_slice_3_apk.apk", zip file "/data/app/(app-domain)/split_lib_slice_4_apk.apk", zip file "/data/app/(app-domain)/split_lib_slice_5_apk.apk", zip file "/data/app/(app-domain)/split_lib_slice_6_apk.apk", zip file "/data/app/(app-domain)/split_lib_slice_7_apk.apk", zip file "/data/app/(app-domain)/split_lib_slice_8_apk.apk", zip file "/data/app/(app-domain)/split_lib_slice_9_apk.apk"],nativeLibraryDirectories=[/data/app/(app-domain)/lib/arm64, /data/app/(app-domain)/base.apk!/lib/arm64-v8a, /data/app/(app-domain)/split_lib_dependencies_apk.apk!/lib/arm64-v8a, /data/app/(app-domain)/split_lib_slice_0_apk.apk!/lib/arm64-v8a, /data/app/(app-domain)/split_lib_slice_1_apk.apk!/lib/arm64-v8a, /data/app/(app-domain)/split_lib_slice_2_apk.apk!/lib/arm64-v8a, /data/app/(app-domain)/split_lib_slice_3_apk.apk!/lib/arm64-v8a, /data/app/(app-domain)/split_lib_slice_4_apk.apk!/lib/arm64-v8a, /data/app/(app-domain)/split_lib_slice_5_apk.apk!/lib/arm64-v8a, /data/app/(app-domain)/split_lib_slice_6_apk.apk!/lib/arm64-v8a, /data/app/(app-domain)/split_lib_slice_7_apk.apk!/lib/arm64-v8a, /data/app/(app-domain)/split_lib_slice_8_apk.apk!/lib/arm64-v8a, /data/app/(app-domain)/split_lib_slice_9_apk.apk!/lib/arm64-v8a, /system/lib64, /vendor/lib64]]
                  at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
                  at java.lang.ClassLoader.loadClass(ClassLoader.java:380)
                  at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
                  at (application class)
                  at retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall$1$1.run(ExecutorCallAdapterFactory.java:70) 
                  at android.os.Handler.handleCallback(Handler.java:751) 
                  at android.os.Handler.dispatchMessage(Handler.java:95) 
                  at android.os.Looper.loop(Looper.java:154) 
                  at android.app.ActivityThread.main(ActivityThread.java:6119) 
                  at java.lang.reflect.Method.invoke(Native Method) 
                  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886) 
                  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)

Offending code:

Date parseDate = Date.from(Instant.parse(model.getDate() + "Z"));

Where model is a date String with format "yyyy-mm-ddTkk:mm:ss"

My JDK version is at 1.8 now. I understand that I should indicate backport functionality, thus in my build.gradle:

android {
compileSdkVersion 26
defaultConfig {
    ...
    minSdkVersion 19
    targetSdkVersion 26
    versionCode 1
    versionName "0.2-2018-04-16"
    testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
...

compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
    }
}

dependencies {
     implementation "com.jakewharton.threetenabp:threetenabp:1.0.5"
}

And based on what I have read here, apparently Instant.parse(...) isn't included in the supported APIs: https://developer.android.com/studio/write/java8-support.html#supported_features

What could I be missing? I might as well use the "ailing Date and Calendar APIs in both Java and Android" instead, but that would be the last resort. I would like to stick to what JDK 1.8 has to offer whenever possible.

Besides, I am not comfortable using Joda Time, since it's too big for such a small app that I am developing, and that I only need a couple of functions in such a case.

Any input would be appreciated!

Nota bene: Contract explicitly wants me to use Java instead of Kotlin.


Solution

  • If you open the sdk documentation https://developer.android.com/reference/java/time/Instant.html you see in the upper right corner "added in API level 26" which means the class is not available on older android devices.

    Your manifest contains minSdkVersion 19. This means i promise that my app will run on api-19 and newer. The exception tells you that the promise is broken.

    How to solve: