9

I´ve got a multidex project for Android devices. I use Flexjson. I´ve already tested it with flexjson 3.3 and 2.x.

It works perfectly well with android 5.x but crashes in Android 4.4.4.

It looks like the Dex support library is not working propperly with older Android versions but I cannot tell.

Here´s my stacktrace:

 06-29 03:50:44.763  11884-11884/com.pigdroid.gameboard E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: com.pigdroid.gameboard, PID: 11884
    flexjson.JSONException: [ layers.values ]:  Could not load com.pigdroid.game.board.tile.model.IntTileLayer
            at flexjson.ObjectBinder.findClassInMap(ObjectBinder.java:250)
            at flexjson.ObjectBinder.findClassName(ObjectBinder.java:213)
            at flexjson.ObjectBinder.bind(ObjectBinder.java:92)
            at flexjson.ObjectBinder.bindIntoCollection(ObjectBinder.java:110)
            at flexjson.factories.ListObjectFactory.instantiate(ListObjectFactory.java:13)
            at flexjson.ObjectBinder.bind(ObjectBinder.java:95)
            at flexjson.ObjectBinder.bindIntoObject(ObjectBinder.java:149)
            at flexjson.factories.ExistingObjectFactory.instantiate(ExistingObjectFactory.java:25)
            at flexjson.ObjectBinder.bind(ObjectBinder.java:95)
            at flexjson.ObjectBinder.bind(ObjectBinder.java:74)
            at flexjson.JSONDeserializer.deserialize(JSONDeserializer.java:241)
            at flexjson.JSONDeserializer.deserializeInto(JSONDeserializer.java:301)
            at com.pigdroid.game.model.memento.UndoableObject.from(UndoableObject.java:35)
            at com.pigdroid.game.controller.GameController.loadModelFromSerialized(GameController.java:108)
            at com.pigdroid.gameboard.view.detail.game.tile.TileBoardGameFragmentController.setGame(TileBoardGameFragmentController.java:692)
            at com.pigdroid.gameboard.view.detail.game.GameDetailFragment.onKickOff(GameDetailFragment.java:168)
            at com.pigdroid.gameboard.view.ServiceFragment.kickOffIf(ServiceFragment.java:71)
            at com.pigdroid.gameboard.view.detail.game.GameDetailFragment.kickOffIf(GameDetailFragment.java:159)
            at com.pigdroid.gameboard.view.ServiceFragment$3.bound(ServiceFragment.java:52)
            at com.pigdroid.gameboard.view.ServiceFragment$3.bound(ServiceFragment.java:48)
            at com.pigdroid.android.hateaidl.HateAIDLConnection$3.onServiceConnected(HateAIDLConnection.java:118)
            at android.app.LoadedApk$ServiceDispatcher.doConnected(LoadedApk.java:1101)
            at android.app.LoadedApk$ServiceDispatcher$RunConnection.run(LoadedApk.java:1118)
            at android.os.Handler.handleCallback(Handler.java:733)
            at android.os.Handler.dispatchMessage(Handler.java:95)
            at android.os.Looper.loop(Looper.java:136)
            at android.app.ActivityThread.main(ActivityThread.java:5001)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
            at dalvik.system.NativeStart.main(Native Method)
     Caused by: java.lang.ClassNotFoundException: Didn't find class "com.pigdroid.game.board.tile.model.IntTileLayer" on path: DexPathList[[directory "."],nativeLibraryDirectories=[/system/lib]]
            at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
            at java.lang.ClassLoader.loadClass(ClassLoader.java:497)
            at java.lang.ClassLoader.loadClass(ClassLoader.java:457)
            at android.app.LoadedApk$WarningContextClassLoader.loadClass(LoadedApk.java:430)
            at flexjson.ObjectBinder.findClassInMap(ObjectBinder.java:243)
            at flexjson.ObjectBinder.findClassName(ObjectBinder.java:213)
            at flexjson.ObjectBinder.bind(ObjectBinder.java:92)
            at flexjson.ObjectBinder.bindIntoCollection(ObjectBinder.java:110)
            at flexjson.factories.ListObjectFactory.instantiate(ListObjectFactory.java:13)
            at flexjson.ObjectBinder.bind(ObjectBinder.java:95)
            at flexjson.ObjectBinder.bindIntoObject(ObjectBinder.java:149)
            at flexjson.factories.ExistingObjectFactory.instantiate(ExistingObjectFactory.java:25)
            at flexjson.ObjectBinder.bind(ObjectBinder.java:95)
            at flexjson.ObjectBinder.bind(ObjectBinder.java:74)
            at flexjson.JSONDeserializer.deserialize(JSONDeserializer.java:241)
            at flexjson.JSONDeserializer.deserializeInto(JSONDeserializer.java:301)
            at com.pigdroid.game.model.memento.UndoableObject.from(UndoableObject.java:35)
            at com.pigdroid.game.controller.GameController.loadModelFromSerialized(GameController.java:108)
            at com.pigdroid.gameboard.view.detail.game.tile.TileBoardGameFragmentController.setGame(TileBoardGameFragmentController.java:692)
            at com.pigdroid.gameboard.view.detail.game.GameDetailFragment.onKickOff(GameDetailFragment.java:168)
            at com.pigdroid.gameboard.view.ServiceFragment.kickOffIf(ServiceFragment.java:71)
            at com.pigdroid.gameboard.view.detail.game.GameDetailFragment.kickOffIf(GameDetailFragment.java:159)
            at com.pigdroid.gameboard.view.ServiceFragment$3.bound(ServiceFragment.java:52)
            at com.pigdroid.gameboard.view.ServiceFragment$3.bound(ServiceFragment.java:48)
            at com.pigdroid.android.hateaidl.HateAIDLConnection$3.onServiceConnected(HateAIDLConnection.java:118)
            at android.app.LoadedApk$ServiceDispatcher.doConnected(LoadedApk.java:1101)
            at android.app.LoadedApk$ServiceDispatcher$RunConnection.run(LoadedApk.java:1118)
            at android.os.Handler.handleCallback(Handler.java:733)
            at android.os.Handler.dispatchMessage(Handler.java:95)
            at android.os.Looper.loop(Looper.java:136)
            at android.app.ActivityThread.main(ActivityThread.java:5001)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
            at dalvik.system.NativeStart.main(Native Method)

EDIT: I´ve filled an issue to the Android dev team and they´ve noted the bug as a feature, even when it works perfectly well on latter versions. If any found this anoying, please try to vote for reopening: https://code.google.com/p/android/issues/detail?id=178607

eduyayo
  • 2,020
  • 2
  • 15
  • 35
  • When exactly this code gets executed? Could you expand the stack trace (show who calls ObjectBinder#bindIntoObject, etc)? – Alex Lipov Jun 27 '15 at 10:38
  • @Alex Lipov, I´ve added the full stacktrace. `ObjectBinder#bindIntoObject` is called internally by flex deserializer – eduyayo Jun 29 '15 at 07:56
  • Great. To understand better what's happening - which component establishing a connection to a service (who calls bindService with the instance of HateAIDLConnection$3 class)? Is it Application? Activity? BroadcastReceiver? – Alex Lipov Jun 29 '15 at 08:11
  • A fragment is binding to a service. the method `onServiceConnected` is invoked after the service is bound. It does not matter at all, that is why I removed the rest of the stacktrace the first time I posted it. Because the bind-unbind and listener stuff seem to be working perfectly. I say more: Before I used services for data loading, flex was failing also in Android 4.4.4 – eduyayo Jun 29 '15 at 08:15
  • There seems to be some inconsistencies in the the package name as per the logs. Is your package name `com.pigdroid.gameboard` or `com.pigdroid.game` ? have you recently changed the package name but forgot to update the package names of referenced classes? – Abhishek V Jun 30 '15 at 05:26
  • Nothing to do. You can use whatever the package. You´ll be using `android.` package or `java.lang` or `java.util`. I´ve included several libraries including couchdb, each of them have their own declared package and, of course, several other packages, even with different root names. That is not the reason of the class not found – eduyayo Jun 30 '15 at 10:09
  • any reason why your doubt is on the compatability library, also can you provide more detail like have you used progaurd. have you configured the multidex properly what i meant was have you put it in your application – Aniruddha K.M Jul 01 '15 at 04:59
  • In android 5.1 it works. No proguard config was applied yet. – eduyayo Jul 01 '15 at 05:42
  • I think I´ve found a fix for this, I´m deploying a new APK for Alpha testers. In Emulators it works with the dirty patch I´ve done. – eduyayo Jul 01 '15 at 11:03

1 Answers1

1

I´ve taken a look to the method failing ObjectBinder.findClassInMap they get the Class loader like this: ClassLoader classLoader = Thread.currentThread().getContextClassLoader();

I suppose there´s kind of a bad install of the multi dex class loader because I´ve set the loader myself before my deserialization occurs and it fixed the problem.

The line fixin' the error I´ve added just before loading my game model goes like this:

    Thread.currentThread().setContextClassLoader(owner.getActivity().getBaseContext().getClassLoader());
eduyayo
  • 2,020
  • 2
  • 15
  • 35