【问题标题】:Using MessagePack with Android在 Android 中使用 MessagePack
【发布时间】:2011-11-23 16:16:10
【问题描述】:

是否有人尝试在 Android 应用中使用 MessagePack
可能吗?我尝试使用 msgpack-java 的 Jar 并收到以下异常:

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();

我的lib 目录中有javassist.jarmsgpack-0.5.2.jarslf4j-api-1.6.2.jarslf4j-jdk14-1.6.2.jar

在我的服务器应用程序中,此代码适用于相同的库。

【问题讨论】:

  • 这是您获得的完整堆栈跟踪吗? ExceptionInInitializerError 是由加载类期间发生的一些异常引起的,因此必须有其他原因,因为堆栈跟踪中没有发生任何类加载。
  • 不,我编辑了我的帖子,所以它几乎是完整的堆栈(使用 java.lang.IllegalStateException 删除的部分:无法执行活动的方法,信息量不大)
  • 请发布整个堆栈跟踪
  • 我希望这可能会有所帮助,:),github.com/chzyer/msgpack-for-android

标签: java android msgpack messagepack


【解决方案1】:

(希望)最终更新

msgpack : 0.6.8 在 Android 上运行没有任何问题

msgpack-rpc0.7.0 在 Android 上工作,但有一点需要注意。

具体来说,对于 API 级别 8 (Android 2.2.1),您需要将以下内容添加到 onCreate,并且可能更低:

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

由于this bug

如果你想看一个简单的例子,这里有一对为此目的设置的项目:


以前的版本

更新:从 0.6.7 msgpack should be compatible with Android 开始(存在一个小的依赖排除问题)。查看下面的文本以获取 msgpack-rpc(也可能在未来进行调整)。

注意:如果您还使用 msgpack-rpc,则需要执行以下步骤:

  1. git://github.com/msgpack/msgpack-rpc.git(特别是 "java" 文件夹)下载 msgpack-rpc 源。
  2. 将主 msgpack 工件版本更改为您已构建的版本。
  3. org.msgpack.rpc.loop.netty.NettyEventLoop中,将NioClientSocketChannelFactory改为OioClientSocketChannelFactory(getWorkerExecutor())。李>
  4. 以与主 MessagePack JAR 相同的方式构建 MessagePack-RPC(参见上面的步骤 11)。

NettyEventLoop 替换是由于这个问题: http://markmail.org/message/ypa3nrr64kzsyfsa .

重要提示:我只测试了同步通信。异步可能不起作用。


这就是在 0.6.7 之前 msgpack 无法在 Android 上工作的原因:

错误的原因是 MessagePack 使用了几个未包含在 Android SDK 中的 java.beans 类。您可能正在使用 MessagePackBeans 注释。

这与here 描述的问题类似,其一般解决方案在here 中概述。不幸的是,在我们的例子中,它需要重新构建 msgpack。这是我所做的(您几乎可以肯定跳过第 5 步和第 8 步,但我还没有尝试过):

  1. https://github.com/msgpack/msgpack-java.git 下载 MessagePack 源代码。
  2. 将 MessagePack 源作为项目导入 IDE。
  3. http://svn.apache.org/repos/asf/harmony/enhanced/java/trunk/classlib/modules/beans/src/main/java 下载相关软件包的 Apache Harmony 源代码。
  4. 将这些包复制到 MessagePack 项目的 src/main/java 文件夹中:
    • java.beans
    • java.beans.beancontext
    • org.apache.harmony.beans
    • org.apache.harmony.beans.internal.nls
  5. 在您的 MessagePack 项目中,删除以下类:
    • PropertyChangeListener
    • IndexedPropertyChangeEvent
    • PropertyChangeEvent
    • PropertyChangeListenerProxy
    • PropertyChangeSupport
  6. java.beans 包重命名为不同的名称,例如custom.beans .
  7. all java.beans 引用更改为重命名的 ID,因此再次例如custom.beans。这尤其适用于BeansFieldEntryReader(这个类是原始错误的原因)。
  8. 将您在步骤 5 中删除的五个类的 custom.beans 引用更改回 java.beans
  9. org.apache.harmony.beans.internal.nls.Messages 类中,注释掉方法 setLocale,并删除与之关联的导入。李>
  10. 删除所有仍然有错误的类,除了 编码器。在该类中,注释掉对您已删除的类的所有引用。您现在应该有一个没有错误的项目。
  11. 构建 MessagePack JAR:
    • 如果您使用的是 Maven,请将 pom.xml 中的版本更改为唯一的版本,使用 install 目标运行 Maven 构建,然后在您的 Android 项目中添加依赖项版本
    • 如果您使用 Maven,则必须使用包含的 build.xml 为 Ant 运行 jar 目标。用这个替换你 Android 项目中的 msgpack JAR。
  12. 如果您要发布应用程序,请记住包含 Apache Harmony 的相关法律声明。它是一个 Apache 许可证,就像 MessagePack。

应该这样做。使用您的示例代码和我自己的数据类,我成功地打包和解包数据。

整个重命名仪式是因为 DEX 编译器抱怨 java.* 包命名。

【讨论】:

  • 不客气 - 这有点像 PITA,但它确实有效 :)。仅供参考,我在 MessagePack 的用户组中添加了相关帖子:groups.google.com/group/msgpack/browse_thread/thread/…
  • @TheTerribleSwiftTomato 你认为同样可以将javax.xml.bind.JAXBElement 移植到Android 吗?我的问题是here
  • @mikołak 看起来它仍然使用非 Android 包。林特说:Invalid package reference in library; not included in Android: java.applet. Referenced from javassist.tools.rmi.ObjectImporter.Invalid package reference in library; not included in Android: javax.tools. Referenced from org.msgpack.util.TemplatePrecompiler.
【解决方案2】:

有一个严重的 msgpack 错误,说使用 msgpack 打包的数据会在 Dalvik VM 上损坏。 http://jira.msgpack.org/browse/MSGPACK-51

【讨论】:

  • 我有理由确定您可以改用@MessagePackBeans 来解决它。这就是我在测试中使用的。
【解决方案3】:

@TheTerribleSwiftTomato 和 MessagePack 核心团队一直在努力让 MessagePack 在 Android 上运行,请参阅相关的 GitHub issue。 @TheTerribleSwiftTomato 的答案中提到的修复程序可以在 here 找到。

更新

通过(煞费苦心地)添加当前构建成功所需的所有必要的javassist 类,我已经设法让它至少在 Android 上运行。额外的600KB 大小增加,但至少它似乎有效。总而言之,它似乎在某种程度上可以在 Android 上运行,最终查看有关 Message Pack 的鲜为人知的资源,例如其 User GroupWiki 以获取更多信息。

另外,请务必使用可以处理二进制数据的 HTTP 请求库(例如 LoopJ 的 Android Async HTTP 或 Apache 的 HttpClient)。

最后但并非最不重要的一点是,如果您对这个 jar 感兴趣,您可以联系我,这使得 MessagePack 似乎可以在 Android 上运行 - 当然要感谢提供上述修复的 @TheTerribleSwiftTomato!

【讨论】:

  • 还有同样的问题,有什么帮助吗?
  • 谷歌我并写一封电子邮件,我今晚会回复你,并把对我有用的 .jar 邮寄给你。虽然问题似乎在 MessagePack 中得到解决,但请参阅 github.com/msgpack/msgpack-java/issues/15
  • 它给了我 java.lang.NoClassDefFoundError: org.msgpack.MessagePack
  • 好的,您是否忘记在您的 Classpath 中添加 MessagePack .jar? (在 Eclipse 中,使用 Project Properties » Libraries and Code » External Libraries » Add External JAR [from the top of my head])
【解决方案4】:

我建议你把这个写在主要的 proguard-rules 文件中-

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

【讨论】:

    猜你喜欢
    • 2013-03-28
    • 1970-01-01
    • 2014-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多