Использование MessagePack с Android

Кто-нибудь пытался использовать MessagePack с Android-приложением?
Является ли это возможным? Я попытался использовать Jar из msgpack-java и получил следующее исключение:

Caused by: java.lang.ExceptionInInitializerError
  at org.msgpack.Packer.pack(Packer.java:532)
  at org.msgpack.MessagePack.pack(MessagePack.java:31)
  ... 15 more
  Caused by: java.lang.ExceptionInInitializerError
  at org.msgpack.template.TemplateRegistry.<clinit>(TemplateRegistry.java:38)
  ... 17 more
  Caused by: java.lang.VerifyError: org.msgpack.template.BeansFieldEntryReader
  at org.msgpack.template.builder.BeansTemplateBuilder.<init (BeansTemplateBuilder.java:42)
  at org.msgpack.template.builder.BuilderSelectorRegistry.initForJava(BuilderSelectorRegistry.java:73)
  at org.msgpack.template.builder.BuilderSelectorRegistry.<clinit>(BuilderSelectorRegistry.java:38)
  ... 18 more

Код, который я использую, очень прост

PrintWriter out = new PrintWriter(socket.getOutputStream());
Message msg = new Message();
msg.body = "asdasdasd";
msg.from = "qwe";
msg.to = "ttt";
byte[] bytes = MessagePack.pack(msg);
out.print(bytes);
out.flush();

У меня javassist.jar, msgpack-0.5.2.jar, slf4j-api-1.6.2.jar и slf4j-jdk14-1.6.2.jar в моем каталоге lib.

В моем серверном приложении этот код отлично работает с теми же библиотеками.

Ответ 1

(Надеюсь) ЗАКЛЮЧИТЕЛЬНОЕ ОБНОВЛЕНИЕ

msgpack: 0.6.8 работает без проблем на Android.

msgpack-rpc: 0.7.0 работает на Android с одной оговоркой.

В частности, вам нужно добавить следующее в onCreate для уровня API 8 (Android 2.2.1) и, возможно, ниже:

java.lang.System.setProperty("java.net.preferIPv4Stack", "true");
java.lang.System.setProperty("java.net.preferIPv6Addresses", "false");

из-за этой ошибки.

Если вы хотите увидеть простой пример, вот пара проектов, созданных для этой цели:


Предыдущие версии

UPDATE: с 0.6.7 msgpack должен быть совместим с Android (есть небольшая проблема исключения зависимостей). Проверьте текст ниже для msgpack-rpc (который также может быть адаптирован в будущем).

ПРИМЕЧАНИЕ. Если вы также используете msgpack-rpc, вам необходимо выполнить следующие действия:

  • Загрузите источник msgpack-rpc из git://github.com/msgpack/msgpack-rpc.git(в частности, папку "java" ).
  • Измените основную версию артефакта msgpack на тот, который вы создали.
  • В org.msgpack.rpc.loop.netty.NettyEventLoop измените NioClientSocketChannelFactory на OioClientSocketChannelFactory (getWorkerExecutor()).
  • Создайте MessagePack-RPC так же, как и в случае основного MessagePack JAR (см. шаг 11 выше).

Замена NettyEventLoop связана с этой проблемой: http://markmail.org/message/ypa3nrr64kzsyfsa.

Важно: Я тестировал только синхронную связь. Асинхронный может не работать.


И вот причина, по которой msgpack не работает с Android до 0.6.7:

Причиной ошибки является то, что MessagePack использует несколько классов java.beans, которые не включены в Android SDK. Вероятно, вы используете аннотацию MessagePackBeans.

Это аналогичная проблема для описанной здесь, для которой описано общее решение здесь, К сожалению, в нашем случае это требует восстановления msgpack. Вот что я сделал (вы почти наверняка можете пропустить шаги 5 и 8, но я так не пробовал):

  • Загрузите источник MessagePack из https://github.com/msgpack/msgpack-java.git.
  • Импортируйте источник MessagePack как проект в вашу среду IDE.
  • Загрузите источник Apache Harmony для соответствующих пакетов из http://svn.apache.org/repos/asf/harmony/enhanced/java/trunk/classlib/modules/beans/src/main/java.
  • Скопируйте эти пакеты в папку spc/main/java в MessagePack:
    • java.beans
    • java.beans.beancontext
    • org.apache.harmony.beans
    • org.apache.harmony.beans.internal.nls
  • В своем проекте MessagePack удалите следующие классы:
    • PropertyChangeListener
    • IndexedPropertyChangeEvent
    • PropertyChangeEvent
    • PropertyChangeListenerProxy
    • PropertyChangeSupport
  • Переименуйте пакеты java.beans на что-то другое, например. custom.beans.
  • Измените все ссылки java.beans на переименованный идентификатор, так что снова, например, custom.beans. Это относится к особенно для BeansFieldEntryReader (этот класс является причиной исходной ошибки).
  • Измените ссылки custom.beans для пяти классов, которые вы удалили в Шаг 5, назад к java.beans.
  • В классе org.apache.harmony.beans.internal.nls.Messages закомментируйте метод setLocale и удалите связанные с ним импорт.
  • Удалите все классы, у которых все еще есть ошибки, кроме Encoder. В этом классе закомментируйте все ссылки на классы, которые вы удалили. Теперь у вас должен быть проект без ошибок.
  • Создайте MessagePack JAR:
    • Если вы используете Maven, измените версию в pom.xml на нечто уникальное, запустите Maven build с целью установки, а затем добавьте зависимость в проект Android с этой версией.
    • Если вы используете не, используя Maven, вам нужно запустить цель jar для Ant с включенным build.xml. Замените JAR-приложение msgpack в своем проекте Android этим.
  • Если вы публикуете свое приложение, не забудьте указать соответствующее юридическое уведомление для Apache Harmony. Это лицензия Apache, как и MessagePack.

Это должно сделать это. Используя ваш примерный код и собственный класс данных, я смог успешно упаковать и распаковать данные.

Весь ритуал переименования связан с тем, что компилятор DEX жалуется на java. * Именование пакетов.

Ответ 2

Существует критическая ошибка msgpack, в которой данные, упакованные с помощью msgpack, будут повреждены на VM Dalvik. http://jira.msgpack.org/browse/MSGPACK-51

Ответ 3

Постоянная работа @TheTerribleSwiftTomato и основной команды MessagePack, чтобы заставить MessagePack работать на Android, см. связанную проблему GitHub. Исправление, упомянутое в ответе @TheTerribleSwiftTomato, можно найти здесь.

Обновление

Мне удалось получить хотя бы его работу на Android (кропотливо), добавив все необходимые классы javassist, которые в настоящее время необходимы для успешной сборки. Дополнительный 600KB выигрыш в размере, но по крайней мере, похоже, он работает. В целом, похоже, он работает в какой-то степени на Android, в конце концов проверяет менее известные ресурсы об Message Pack, такие как Группа пользователей и Wiki для получения дополнительной информации.

В боковом примечании обязательно используйте библиотеку запросов HTTP (например, LoopJ Android Async HTTP или Apache HttpClient), который может обрабатывать двоичные данные.

И последнее, но не менее важное: вы можете рассказать мне, если есть интерес к этому jar, который делает MessagePack, похоже, работать на Android - кредиты, конечно же, выходят на @TheTerribleSwiftTomato, который предоставил исправление выше!

Ответ 4

Я предлагаю вам написать это в главном файле proguard-rules -

-dontwarn org.msgpack.**
-keep class org.msgpack.** { *; }