1

It only happened once on a Galaxy Nexus with Android 4.3. Is there some known issue in Active Android with enum fields? Google didn't help and I'm not even sure where to look at.

I must mention that I have multiDexEnabled=true, and that's probably the reason why ActiveAndroid searches class in this weird spot (my_app_name-1.apk)

java.lang.NoClassDefFoundError: .../models/QuickAction$ActionType
at java.lang.Class.getDeclaredFields(Native Method)
at java.lang.Class.getDeclaredFields(Class.java:560)
at com.activeandroid.util.ReflectionUtils.getDeclaredColumnFields(ReflectionUtils.java:73)
at com.activeandroid.TableInfo.<init>(TableInfo.java:66)
at com.activeandroid.ModelInfo.loadModelFromMetaData(ModelInfo.java:101)
at com.activeandroid.ModelInfo.<init>(ModelInfo.java:61)
at com.activeandroid.Cache.initialize(Cache.java:66)
at com.activeandroid.ActiveAndroid.initialize(ActiveAndroid.java:44)
at com.activeandroid.ActiveAndroid.initialize(ActiveAndroid.java:34)
at com.activeandroid.ActiveAndroid.initialize(ActiveAndroid.java:30)
at com.activeandroid.app.Application.onCreate(Application.java:25)
at ...MyApplication.onCreate(MyApplication.java:12)
at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1007)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4444)
at android.app.ActivityThread.access$1300(ActivityThread.java:141)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1316)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5103)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:525)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.ClassNotFoundException: Didn't find class "...models.QuickAction$ActionType" on path: DexPathList[[zip file "/data/app/...-1.apk"],nativeLibraryDirectories=[/data/app-lib/...-1, /vendor/lib, /system/lib]]
    at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:53)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:501)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:461)
    ... 24 more
JaLoveAst1k
  • 512
  • 3
  • 14
  • are you using signed APK? – Andy Developer Jul 11 '17 at 12:18
  • 1
    Are you using proguard, and have you called `MultiDex.install(this);` in your Application? – Adam S Jul 11 '17 at 12:19
  • check https://stackoverflow.com/a/33430306/3395198 – IntelliJ Amiya Jul 11 '17 at 12:19
  • yes, app is signed, I got this crash report from googleplay console – JaLoveAst1k Jul 11 '17 at 12:34
  • no, I am not using proguard, atleast I think so. here is code in my gradle, the default one - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'. And no, I have not even heard about MultiDex.install(this); – JaLoveAst1k Jul 11 '17 at 12:35
  • @AdamS According to documentation: "Do not execute MultiDex.install() or any other code through reflection or JNI before MultiDex.install() is complete. Multidex tracing will not follow those calls, causing ClassNotFoundException or verify errors due to a bad class partition between DEX files." So I guess that's my case, I just need to add MultiDex.install in attachBaseContext? But the question is - why app works on all other devices and this crash happened only once? – JaLoveAst1k Jul 11 '17 at 12:42
  • I went into some detail in my answer :) – Adam S Jul 11 '17 at 14:32

1 Answers1

1

As per the MultiDex documentation you need to call MultiDex.install(this) from your application:

Patches the application context class loader by appending extra dex files loaded from the application apk.

You can do this either by extending the MultiDexApplication class:

public class MyApplication extends MultiDexApplication { ... }

Or, if you have your own custom Application class which extends something else already, by calling install directly:

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

Why do we only need to do this for 4.4 and below? If we look at the docs again we can see that MultiDex support is built-in to Android 5.0 (L) and higher:

Android 5.0 (API level 21) and higher uses a runtime called ART which natively supports loading multiple DEX files from APK files.

Indeed, if we step into the MultiDex support library we can see that it no-ops if the device VM is considered "multi dex capable":

public static void install(Context context) {
    Log.i("MultiDex", "install");
    if(IS_VM_MULTIDEX_CAPABLE) {
        Log.i("MultiDex", "VM has multidex support, MultiDex support library is disabled.");
    } else if(VERSION.SDK_INT < 4) {
        throw new RuntimeException("Multi dex installation failed. SDK " + VERSION.SDK_INT + " is unsupported. Min SDK version is " + 4 + ".");
    } else {
        // Set up multidex
        ...
    }
}
Adam S
  • 16,144
  • 6
  • 54
  • 81