Android 4.4.4 上的 FlexJson ClassNotFound 异常

FlexJson ClassNotFound Exception on Android 4.4.4

我有一个 Android 设备的 multidex 项目。我使用 Flexjson。我已经使用 flexjson 3.3 和 2.x 对其进行了测试。

它与 android 5.x 完美配合,但在 Android 4.4.4 中崩溃。

Dex 支持库似乎无法与旧的 Android 版本一起正常工作,但我无法判断。

这是我的堆栈跟踪:

 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.bound(ServiceFragment.java:52)
            at com.pigdroid.gameboard.view.ServiceFragment.bound(ServiceFragment.java:48)
            at com.pigdroid.android.hateaidl.HateAIDLConnection.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.bound(ServiceFragment.java:52)
            at com.pigdroid.gameboard.view.ServiceFragment.bound(ServiceFragment.java:48)
            at com.pigdroid.android.hateaidl.HateAIDLConnection.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)

编辑: 我向 Android 开发团队提出了一个问题,他们将这个错误作为一个功能记录下来,即使它在后来的版本。如果有人觉得这很烦人,请尝试投票支持重新开放:https://code.google.com/p/android/issues/detail?id=178607

我查看了失败的方法 ObjectBinder.findClassInMap 他们得到了这样的 Class 加载器:ClassLoader classLoader = Thread.currentThread().getContextClassLoader();

我想 multi dex class 加载器的安装有点不对,因为我在反序列化发生之前自己设置了加载器,它解决了问题。

修复我在加载游戏模型之前添加的错误的行如下所示:

    Thread.currentThread().setContextClassLoader(owner.getActivity().getBaseContext().getClassLoader());