21

我一直在开发一个启用 WebGL 的 PhoneGap 插件,旨在将 HTML5 游戏发布到移动设备上。它被称为WebGLGap。但是,PhoneGap 调用插件代码的方式(通过 exec)通常涉及将所有参数字符串化为 JSON,然后在另一端再次对其进行解析。根据this question,即使在PhoneGap 2.2中也没有改变,它被宣传为具有更快的网桥。对于像 WebGL 这样的东西,这绝对是站不住脚的,即使是简单的演示也会降低性能(<10 FPS)。这是因为在许多情况下,尤其是 2D 游戏,每一帧都必须传输一大块 JSON 数据,表示要运行的所有 WebGL 命令。这包括所有顶点数据 - 想象每帧都有一个巨大的字符串“0.959455、0.959595、0.588575、0.585858...”等。

显然,字符串化和解析是一个不必要且低效的步骤,但我正在努力寻找一种方法将 JSON 数据从 JS 传递到本机,从而避免这种情况。理想情况下,这应该适用于 Android 和 iOS,但我很高兴现在坚持使用仅限 Android 的解决方案。有没有人对最有效的方法有任何想法?

4

6 回答 6

12

Linkedin 将 Web Sockets 用于他们的 iPad 应用程序。可能值得研究:http ://engineering.linkedin.com/mobile/linkedin-ipad-nativeweb-messaging-bridge-and-websockets

您正在寻找的一些好处

  • WebSockets 可以从 JavaScript 异步通信到本机。
  • WebSockets 没有负载限制
  • WebSockets 不需要我们将 JSON 字符串编码为 URL 参数
  • WebSockets 应该比 URL 方案导航更快
于 2012-11-27T22:58:40.217 回答
3

Addressing performance

Looking at CordovaPlugin.java, as you mentioned, everything is a String:

public boolean execute(String action, String rawArgs, CallbackContext callbackContext) throws JSONException {
    JSONArray args = new JSONArray(rawArgs);
    return execute(action, args, callbackContext);
}

If, for example, the conversion from String to JSONArray is the only bottleneck, then you could override this method in your plugin and perform your own deserialization. It's a small performance improvement, but it might be worth investigating.

Creating an alternate bridge

As for creating an alternative bridge, that's trickier. I don't know much about Cordova / PhoneGap, but from what research I've gathered, Cordova exposes a specific Javascript interface via addJavascriptInterface. If you could implement your own NativetoJSMessageQueue, you might be able to wire it all together.

EDIT
After conducting a bit more research, I can provide a bit more direction. The really relevant part of the NativetoJSMessageQueue is the various BridgeModes it implements (see line 92). You could look at the other bridge modes as an example.

Unfortunately, the NativetoJSMessageQueue has exactly four bridge modes registered; assuming that you could implement your own bridge mode, you would still need to some how register it as a new mode for the NativetoJSMessageQueue.

于 2012-11-24T22:15:48.247 回答
2

我不确定您到底想做什么,但我注意到在您的项目中您将 JSON 转换为 String,然后您将通过 PhoneGap 插件将其传递,将其转换为 JSON,然后将其转换为 Matrix!

如果您将数据保存在字符串中并将字符串直接转换为矩阵会怎样?这样您就可以跳过与 JSON 之间的转换部分

于 2012-11-27T22:54:35.213 回答
2

在 android 上,您可以尝试使用addJavascriptInterface( link to WebView's documentation ) 方法WebView“将 Java 对象注入 WebView”,这是 PhoneGap 用来添加用于地理定位、文件系统等的 api 的方法。

我想这会比使用插件方法更快(还没有测试过)。

检查PhoneGapView扩展的代码WebViewhttps ://github.com/phonegap/phonegap/blob/3c7324ea8b3944b6e5d3d91e9e328c9c3939464b/android/framework/src/com/phonegap/PhoneGapView.java#L42

更新

毕竟,这仅适用于简单类型,例如intor String,就像您在下面的评论中所说的那样。

在 Android 上使用 addJavascriptInterface() 传递 JavaScript 对象

尝试不这样做将导致android.webkit.WebViewCoreandroid.webkit.JWebCoreJavaBridge类中的异常。

更新 2

好吧,您将使用这种方法实现的最佳代码将是这样的(来自https://github.com/commonsguy/cw-advandroid/blob/master/WebView/GeoWeb1/src/com/commonsware/android/geoweb /GeoWebOne.java#L80):

public String getLocation() throws JSONException {
  Location loc=myLocationManager.getLastKnownLocation(PROVIDER);

  if (loc==null) {
    return(null);
  }

  JSONObject json=new JSONObject();

  json.put("lat", loc.getLatitude());
  json.put("lon", loc.getLongitude());

  return(json.toString());
}

最有可能的是,所有参数都应该是 string'fied(或 JSON'fied...)

如果您在尝试从 javascript 端创建字符串时遇到性能问题,这可能会对您有所帮助:http ://www.javascripture.com/ArrayBuffer

于 2012-11-28T17:11:22.123 回答
1

鉴于 json 的效率非常低,如果您采用这条路线,您可能会获得很多性能:

服务器端:数据模型-> protobuf(构建()到二进制)-> 编码 base64(二进制到字符串)-> 添加为一个 json 字段或有效负载(最好是将二进制 blob 作为有效负载传递,但我不确定如果 PhoneGap 允许这样做)

客户端:从 base64 解码(字符串到二进制)-> protobuf(从二进制解析)-> 在代码中尽可能深入地直接使用 protobuf 对象 - 这是非常有效的数据模型

于 2012-11-29T18:32:26.817 回答
1

我已经阅读了有关在 png 中编码数据的信息。这是原始文章:http ://cg.alexandra.dk/2012/11/26/webgl-tutorial-optimizing-data-transfer-for-webgl-applications/

可能有用。

于 2012-11-29T16:14:30.933 回答