admin管理员组文章数量:1180493
I have been working on a PhoneGap plugin to enable WebGL, intended for publishing HTML5 games to mobile. It's called WebGLGap. However, PhoneGap's way of calling plugin code (via exec) typically involves stringifying all the parameters to JSON, then parsing it on the other side again. According to this question, this has not changed even in PhoneGap 2.2 which was advertised as having a faster bridge. For something like WebGL, this is absolutely untenable and kills performance (<10 FPS) even for simple demos. This is because in many cases, especially 2D games, every frame must transmit a large block of JSON data representing all the WebGL commands to run. This includes all vertex data - imagine a huge string of "0.959455, 0.959595, 0.588575, 0.585858..." etc every frame.
Obviously stringifying and parsing is an unnecessary and inefficient step, but I'm struggling to find a way to pass the JSON data from JS to native which avoids that. Ideally this should work on both Android and iOS, but I'm happy to stick to an Android-only solution for now. Does anyone have any ideas about the most efficient way to do this?
I have been working on a PhoneGap plugin to enable WebGL, intended for publishing HTML5 games to mobile. It's called WebGLGap. However, PhoneGap's way of calling plugin code (via exec) typically involves stringifying all the parameters to JSON, then parsing it on the other side again. According to this question, this has not changed even in PhoneGap 2.2 which was advertised as having a faster bridge. For something like WebGL, this is absolutely untenable and kills performance (<10 FPS) even for simple demos. This is because in many cases, especially 2D games, every frame must transmit a large block of JSON data representing all the WebGL commands to run. This includes all vertex data - imagine a huge string of "0.959455, 0.959595, 0.588575, 0.585858..." etc every frame.
Obviously stringifying and parsing is an unnecessary and inefficient step, but I'm struggling to find a way to pass the JSON data from JS to native which avoids that. Ideally this should work on both Android and iOS, but I'm happy to stick to an Android-only solution for now. Does anyone have any ideas about the most efficient way to do this?
Share Improve this question edited May 23, 2017 at 10:27 CommunityBot 11 silver badge asked Nov 19, 2012 at 18:40 AshleysBrainAshleysBrain 22.6k16 gold badges91 silver badges125 bronze badges 4- Are you looking for a pratical solution? I wanted to give this a shot, but today I might not be able to, only tomorrow ... – fableal Commented Nov 27, 2012 at 18:06
- "pratical" as in, with working code :) – fableal Commented Nov 27, 2012 at 18:11
- Only have a sugestion, wondered if there was a way to create a websocket connection between the two, webql, js to the natvie app. – Emile Commented Nov 27, 2012 at 18:12
- did you consider just wrapping the data in json-p callback functions? – technosaurus Commented Nov 28, 2012 at 1:26
6 Answers
Reset to default 12 +500Linkedin use Web Sockets for their iPad app. Might be worth looking into: http://engineering.linkedin.com/mobile/linkedin-ipad-nativeweb-messaging-bridge-and-websockets
Some of the benefits that you're looking for
- WebSockets can communicate asynchronously from JavaScript to native.
- WebSockets don't have a payload limit
- WebSockets don't require us to encode our JSON strings as URL parameters
- WebSockets should be faster than URL scheme navigation
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
.
I'm not sure what exactly you want to do but I notice that in your project you are converting the JSON to String and then you will pass it through the PhoneGap plugin , convert it to JSON and then convert it to Matrix!
what if you keep your data in a string and convert the string straight to Matrix? this way you can skip the converting to and from JSON part
On android, you can try to use the addJavascriptInterface
(link to WebView's documentation) method of the WebView
to "inject Java objects into the WebView", which is the approach PhoneGap uses to add the apis for geolocation, filesystem, etc.
I guess this will be faster than using the plugin approach (didn't test this yet).
Check the code of the PhoneGapView
, which extends WebView
:
https://github.com/phonegap/phonegap/blob/3c7324ea8b3944b6e5d3d91e9e328c9c3939464b/android/framework/src/com/phonegap/PhoneGapView.java#L42
UPDATE
After all, this only works for simple types such as int
or String
, like you said in a comment below.
Passing a JavaScript object using addJavascriptInterface() on Android
Trying to do otherwise will result in exceptions from within the android.webkit.WebViewCore
and android.webkit.JWebCoreJavaBridge
classes.
UPDATE 2
Well, the best code you'll achieve using this approach will be something like this (from 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());
}
and most likely, all parameters should be string'fied (or JSON'fied...)
This might help you if you have a performance hit when triying to create strings from javascript side: http://www.javascripture.com/ArrayBuffer
I've read about encoding data in png. Here is the original article: http://cg.alexandra.dk/2012/11/26/webgl-tutorial-optimizing-data-transfer-for-webgl-applications/
Might be useful.
Given that json is very inefficient, you may gain a lot of performance if you take this route:
server side: data model -> protobuf (build() to binary) -> encode base64 (binary to string) -> add as one json field or payload (best is to pass binary blob as a payload, but I'm not sure if PhoneGap allow this)
client side: decode from base64 (string to binary) -> protobuf (parse from binary) -> use the protobuf objects directly as deep as you can in your code - it's extremely efficient data model
本文标签: javascriptPhoneGap plugin fastest way to transfer JSON data to nativeStack Overflow
版权声明:本文标题:javascript - PhoneGap plugin: fastest way to transfer JSON data to native - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1738138220a2065562.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论