在Android中使用MessagePack

12

有人尝试过在 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是由于在加载类时发生的某些异常引起的,因此必须有其他原因,因为在您的堆栈跟踪中没有任何类加载发生。 - HefferWolf
不,我编辑了我的帖子,所以它几乎是全栈的(删除了一部分包含java.lang.IllegalStateException: Could not execute method of the activity的信息,它并不那么有用)。 - arbuzz
请发布完整的堆栈跟踪。 - slayton
希望这对你有所帮助,:), https://github.com/chzyer/msgpack-for-android - YulCheney
4个回答

14

(希望)最终更新

msgpack0.6.8在Android上没有任何问题。

msgpack-rpc0.7.0 在Android上有一个注意事项。

具体来说,对于API Level 8(Android 2.2.1)及更低版本,您需要在onCreate中添加以下内容:

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

由于此错误,MessagePack在Android上无法正常工作。

如果您想查看一个简单的示例,这是为此目的设置的一对项目:


以前的版本

更新:自0.6.7版本开始,msgpack应与Android兼容(存在小的依赖项排除问题)。请参考以下文本中的msgpack-rpc(也可能在将来进行适配)。

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

  1. git://github.com/msgpack/msgpack-rpc.git下载msgpack-rpc源代码(具体来说,是“java”文件夹)。
  2. 更改主消息包artifact版本为您构建的版本。
  3. org.msgpack.rpc.loop.netty.NettyEventLoop中,将NioClientSocketChannelFactory更改为OioClientSocketChannelFactory(getWorkerExecutor())
  4. 以与主消息包JAR相同的方式构建MessagePack-RPC(请参见上面的第11步)。

NettyEventLoop替换是由于此问题:

http://markmail.org/message/ypa3nrr64kzsyfsa

重要提示:我只测试了同步通信。异步可能无法工作。


以下是msgpack在0.6.7之前不适用于Android的原因:

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

这与此处所描述的问题类似,其一般解决方法在此处概述。不幸的是,在我们的情况下,它需要重建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

1
不用谢 - 这有点麻烦,但绝对有效 :). 顺便说一下,我在MessagePack的用户组中添加了一个相关的帖子: http://groups.google.com/group/msgpack/browse_thread/thread/89a2c47f8031f956 。 - mikołak
@TheTerribleSwiftTomato,您认为将javax.xml.bind.JAXBElement移植到Android上是否可能?我的问题在这里 - JJD
@mikołak 看起来它仍然使用非Android包。Lint指出: “库中的无效包引用;未包含在Android中: java.applet. 从javassist.tools.rmi.ObjectImporter引用。”和“库中的无效包引用;未包含在Android中: javax.tools. 从org.msgpack.util.TemplatePrecompiler引用。” - ddmytrenko

0

目前@TheTerribleSwiftTomato和MessagePack核心团队正在努力使MessagePack在Android上运行,请参见相关GitHub issue。 @ TheTerribleSwiftTomato回答中提到的修复程序可在here找到。

更新

我已经设法通过(费力地)添加所有必要javassist类来让它至少在Android上运行,这些类目前需要构建以成功。额外增加了600KB的大小,但至少似乎可以工作。总的来说,在Android上似乎在某种程度上有效,最终可以查看Message Pack的一些较少知名的资源,例如其User Group和其Wiki获取更多信息。

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

最后,如果对这个jar有兴趣,可以联系我,它使得似乎在Android上工作的MessagePack - 当然要感谢@TheTerribleSwiftTomato提供了上面的修复!


1
仍然存在同样的问题,需要帮助吗? - Anwar Mohamed
谷歌一下我的名字并写封电子邮件,我今晚会回复你并发送给你那个对我有效的.jar文件。虽然这个问题似乎已经在MessagePack中得到解决,请参考https://github.com/msgpack/msgpack-java/issues/15。 - Dr1Ku
它给了我java.lang.NoClassDefFoundError: org.msgpack.MessagePack。 - Anwar Mohamed
好的,你可能忘记将MessagePack .jar添加到你的类路径中了吗?(在Eclipse中,使用项目属性»库和代码»外部库»添加外部JAR[从我的头顶上]) - Dr1Ku

0

我相当确定你可以通过使用@MessagePackBeans来解决它。这就是我在测试中使用的方法。 - mikołak

0
我建议你将这个写在主要的proguard-rules文件中。
-dontwarn org.msgpack.**
-keep class org.msgpack.** { *; }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接