在 Android 中使用 MessagePack

发布于 2024-12-06 07:18:01 字数 1364 浏览 1 评论 0原文

有人尝试过在 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();

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

在我的服务器应用程序中,此代码可以与相同的库配合使用。

Has someone tried to use MessagePack with an Android app?
Is it possible? I have tried to use the Jar from msgpack-java and received the following Exception:

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

The code that I use is very simple

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

I have javassist.jar, msgpack-0.5.2.jar, slf4j-api-1.6.2.jar and slf4j-jdk14-1.6.2.jar in my lib directory.

In my server application this code works fine with the same libraries.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

自找没趣 2024-12-13 07:18:01

(希望)最终更新

msgpack0.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");

由于 此错误

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


以前的版本

更新:截至 0.6.7 msgpack 应该与 Android 兼容(存在一个小的依赖排除问题)。检查下面的 msgpack-rpc 文本(将来也可能会进行调整)。

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

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

NettyEventLoop 替换是由于以下问题造成的:
http://markmail.org/message/ypa3nrr64kzsyfsa

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


以下是 msgpack 无法在 0.6.7 之前的 Android 上运行的原因:

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

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

  1. https://github.com/msgpack/msgpack-java.git
  2. 将 MessagePack 源导入为 IDE 中的项目。
  3. http://svn.apache.org/repos/asf/harmony/enhanced/java/trunk/classlib/modules/beans/src/main/java
  4. 将这些包复制到 MessagePack 项目的 src/main/java 文件夹中:
    • java.bean
    • java.beans.beancontext
    • org.apache.harmony.beans
    • org.apache.harmony.beans.internal.nls
  5. 在您的 MessagePack 项目中,删除以下类:
    • PropertyChangeListener
    • IndexedPropertyChangeEvent
    • PropertyChangeEvent
    • PropertyChangeListenerProxy
    • 属性更改支持
  6. java.beans 包重命名为不同的名称,例如 custom.beans
  7. 所有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 中的版本更改为唯一的版本,使用安装目标运行 Maven 构建,然后在 Android 项目中添加依赖项版本
    • 如果您使用 Maven,则必须使用包含的 build.xml 运行 Ant 的 jar 目标。将 Android 项目中的 msgpack JAR 替换为此 JAR。
  12. 如果您要发布应用程序,请记住包含 Apache Harmony 的相关法律声明。它是一个 Apache 许可证,就像 MessagePack 一样。

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

整个重命名仪式是由于 DEX 编译器抱怨 java.* 包命名这一事实造成的。

(Hopefully) FINAL UPDATE

msgpack : 0.6.8 works on Android without any problems

msgpack-rpc : 0.7.0 works on Android with one caveat.

Specifically, you need to add the following to onCreate for API Level 8 (Android 2.2.1), and possibly lower:

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

due to this bug.

If you want to see a simple example, here's a pair of projects set up for this purpose:


Previous Versions

UPDATE: as of 0.6.7 msgpack should be compatible with Android (there is a small dependency exclusion issue). Check the text below for msgpack-rpc (which also might be adapted in the future).

NOTE: If you're also using msgpack-rpc, you need to do the following steps:

  1. Download the msgpack-rpc source from git://github.com/msgpack/msgpack-rpc.git (specifically, the "java" folder).
  2. Change the main msgpack artifact version to the one you've built.
  3. In org.msgpack.rpc.loop.netty.NettyEventLoop, change the NioClientSocketChannelFactory to OioClientSocketChannelFactory(getWorkerExecutor()).
  4. Build the MessagePack-RPC in the same way as in the case of the main MessagePack JAR (see Step 11 above).

The NettyEventLoop replacement is due to this issue:
http://markmail.org/message/ypa3nrr64kzsyfsa .

Important: I've only tested synchronous communication. Asynchronous might not work.


And here's the reason for msgpack not working with Android prior to 0.6.7:

The reason for the error is that MessagePack uses several java.beans classes that are not included in the Android SDK. You're probably using the MessagePackBeans annotation.

This is a similar problem to the one described here, for which the general solution is outlined here. Unfortunately, in our case it requires a rebuild of msgpack. Here's what I did (you can almost certainly skip Steps 5 and 8, but I haven't tried it that way) :

  1. Download the MessagePack source from https://github.com/msgpack/msgpack-java.git.
  2. Import the MessagePack source as a project in your IDE.
  3. Download the Apache Harmony source for the relevant packages from http://svn.apache.org/repos/asf/harmony/enhanced/java/trunk/classlib/modules/beans/src/main/java .
  4. Copy these packages into your MessagePack project's src/main/java folder:
    • java.beans
    • java.beans.beancontext
    • org.apache.harmony.beans
    • org.apache.harmony.beans.internal.nls
  5. In your MessagePack project, remove the following classes:
    • PropertyChangeListener
    • IndexedPropertyChangeEvent
    • PropertyChangeEvent
    • PropertyChangeListenerProxy
    • PropertyChangeSupport
  6. Rename the java.beans packages to something different, e.g. custom.beans .
  7. Change all java.beans references to the renamed ID, so again e.g. custom.beans. This applies especially to BeansFieldEntryReader (this class is the reason for the original error).
  8. Change the custom.beans references for the five classes you removed in Step 5 back to java.beans.
  9. In the org.apache.harmony.beans.internal.nls.Messages class, comment out the method setLocale, and remove the imports associated with it.
  10. Remove all classes that still have errors, except Encoder. In that class, comment out all references to the classes you've removed. You should now have an error-free project.
  11. Build the MessagePack JAR:
    • If you're using Maven, change the version in the pom.xml to something unique, run Maven build with the install goal, then add the dependency in your Android project with that version.
    • If you're not using Maven, you have to run the jar goal for Ant with the included build.xml. Replace the msgpack JAR in your Android project with this one.
  12. If you're publishing your app, remember to include the relevant legal notice for Apache Harmony. It's an Apache License, just like MessagePack.

That should do it. Using your example code, and my own data class, I was successfully able to pack and unpack data.

The entire renaming ritual is due to the fact that the DEX compiler complains about java.* package naming.

神仙妹妹 2024-12-13 07:18:01

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

There is a critical msgpack bug saying data packed with msgpack will get corrupted on the Dalvik VM. http://jira.msgpack.org/browse/MSGPACK-51

ら栖息 2024-12-13 07:18:01

@TheTerribleSwiftTomato 和 MessagePack 核心团队正在不断努力让 MessagePack 在 Android 上运行,请参阅相关的 GitHub 问题。 @TheTerribleSwiftTomato 的答案中提到的修复可以在此处找到。

更新

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

顺便说一句,请务必使用 HTTP 请求库(例如 LoopJ 的 Android Async HTTP 或 Apache 的 HttpClient),它可以处理二进制数据

最后但并非最不重要的一点是,如果您对这个 jar 感兴趣,您可以联系我,它使 MessagePack 看起来可以在 Android 上运行 - 当然,感谢 @TheTerribleSwiftTomato,他提供了上面的修复程序!

There is an ongoing effort by @TheTerribleSwiftTomato and the MessagePack core team to get MessagePack working on Android, please see the related GitHub issue. The fix mentioned in @TheTerribleSwiftTomato's answer is to be found here.

Update

I've managed to get it at least running on Android by (painstakingly) adding all the necessary javassist Classes which are currently required for the build to succeed. An extra 600KB gain in size, yet at least it seems to work. All in all, it appears to be working to some extent on Android, eventually check out the lesser-known resources about Message Pack such as its User Group and its Wiki for more information.

On a side-note, be sure to use a HTTP Request Library (such as LoopJ's Android Async HTTP or Apache's HttpClient) which can handle binary data.

Last but not least you can ping me if there is interest in this jar which makes MessagePack seemingly work on Android – credits go out of course to @TheTerribleSwiftTomato who supplied the fix above!

记忆之渊 2024-12-13 07:18:01

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

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

I suggest you write this in the main proguard-rules file-

-dontwarn org.msgpack.**
-keep class org.msgpack.** { *; }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文