Исключение FlexJson ClassNotFound на Android 4.4.4

У меня есть проект multidex для устройств Android. Я использую 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$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)

РЕДАКТИРОВАТЬ: я сообщил о проблеме команде разработчиков Android, и они отметили ошибку как функцию, даже если она отлично работает в последних версиях. Если кого-то это раздражает, попробуйте проголосовать за повторное открытие: https://code.google.com/p/android/issues/detail?id=178607


person eduyayo    schedule 26.06.2015    source источник
comment
Когда именно этот код выполняется? Не могли бы вы развернуть трассировку стека (показать, кто вызывает ObjectBinder#bindIntoObject и т. д.)?   -  person Alex Lipov    schedule 27.06.2015
comment
@ Алекс Липов, я добавил полную трассировку стека. ObjectBinder#bindIntoObject вызывается внутренне гибким десериализатором   -  person eduyayo    schedule 29.06.2015
comment
Большой. Чтобы лучше понять, что происходит - какой компонент устанавливает соединение с сервисом (кто вызывает bindService с экземпляром класса HateAIDLConnection$3)? Приложение? Мероприятия? Широковещательный приемник?   -  person Alex Lipov    schedule 29.06.2015
comment
Фрагмент привязывается к службе. метод onServiceConnected вызывается после привязки службы. Это вообще не имеет значения, поэтому я удалил остальную часть трассировки стека при первом размещении. Потому что вещи с привязкой-развязкой и слушателем, похоже, работают отлично. Скажу больше: до того, как я использовал сервисы для загрузки данных, flex не работал и в Android 4.4.4.   -  person eduyayo    schedule 29.06.2015
comment
Судя по журналам, в имени пакета есть некоторые несоответствия. Имя вашего пакета com.pigdroid.gameboard или com.pigdroid.game? вы недавно изменили имя пакета, но забыли обновить имена пакетов классов, на которые ссылаются?   -  person Abhishek V    schedule 30.06.2015
comment
Нечего делать. Вы можете использовать любой пакет. Вы будете использовать пакет android. или java.lang или java.util. Я включил несколько библиотек, в том числе CouchDB, у каждой из них есть свой объявленный пакет и, конечно же, несколько других пакетов, даже с разными корневыми именами. Это не причина того, что класс не найден   -  person eduyayo    schedule 30.06.2015
comment
любая причина, по которой вы сомневаетесь в библиотеке совместимости, также можете ли вы предоставить более подробную информацию, например, использовали ли вы progaurd. правильно ли вы настроили мультидекс, я имел в виду, поместили ли вы его в свое приложение?   -  person Mightian    schedule 01.07.2015
comment
В андроиде 5.1 работает. Конфигурация proguard еще не применялась.   -  person eduyayo    schedule 01.07.2015
comment
Я думаю, что нашел исправление для этого, я развертываю новый APK для альфа-тестеров. В эмуляторах это работает с грязным патчем, который я сделал.   -  person eduyayo    schedule 01.07.2015


Ответы (1)


Я взглянул на метод, который не работает ObjectBinder.findClassInMap, они получают загрузчик классов следующим образом: ClassLoader classLoader = Thread.currentThread().getContextClassLoader();

Я полагаю, что произошла неправильная установка загрузчика классов multi dex, потому что я сам установил загрузчик до того, как произошла десериализация, и это устранило проблему.

Строка, исправляющая ошибку, которую я добавил непосредственно перед загрузкой моей игровой модели, выглядит так:

    Thread.currentThread().setContextClassLoader(owner.getActivity().getBaseContext().getClassLoader());
person eduyayo    schedule 02.07.2015