How does phoneGap (Cordova) work internally, iOS specific
Asked Answered
V

2

11

I have started developing html applications for mutliple platforms. I recently heard about Cordova 2.0(PhoneGap) and ever since I have been curious to know how the bridge works. After lot of code walking, i saw that the Exec.js is the code where call from JS -> Native happens

execXhr = execXhr || new XMLHttpRequest();
        // Changeing this to a GET will make the XHR reach the URIProtocol on 4.2.
        // For some reason it still doesn't work though...
        execXhr.open('HEAD', "file:///!gap_exec", true);
        execXhr.setRequestHeader('vc', cordova.iOSVCAddr);
        if (shouldBundleCommandJson()) {
            execXhr.setRequestHeader('cmds', nativecomm());
        }
        execXhr.send(null);
    } else {
        execIframe = execIframe || createExecIframe();
        execIframe.src = "gap://ready";

But want to understand how that works, what is the concept here, what does file:///!gap_exec or gap://ready do? and how does the call propgate to the lower layers (native code layers)

thanks a bunch in advance.

Voussoir answered 12/10, 2012 at 10:52 Comment(0)
A
13

The trick is easy:

There is a webview. This displays your app. The webview will handle all navigation events.

If the browser navigates to:

file:///!gap_exec 

or

gap://

the webview will cancel the navigation. Everything behind these strings is re-used as an identifier, to get the concrete plugin/plugin-method and parameter:

pseudo-url example:

gap://echoplugin/echothistext?Hello World

This will cause phonegap to look for an echoplugin and call the echothistext method to send the text "Hello World" to the (native) plugin.

update

The way back from native to javascript is (or may be) loading a javascript: url into the webview.

The concrete implementation is a little bit more complex, because the javascript has to send a callback-id to native code. There could be more than one native call are running at the same time. But in fact this is no magic at all. Just a number to get the correct JSON to the right javascript-callback.

There are different ways to communicate between the platform and javascript. For Android there are three or four different bridges.

Aindrea answered 9/11, 2012 at 21:52 Comment(3)
I figured this out long time back. But your answer is correct. ThanksVoussoir
could you update your response, if you're still following cordova? It looks like exec injects an iframe with src="gap://ready" and that's the only js... then CDVViewController.m intercepts all requests to 'gap' with shouldStartLoadWithRequest then CDVCommandQueue.m uses stringByEvaluatingJavaScriptFromString to grab the js command queue.Capitulation
@Christian Kuetbach: You said like "There could be more than one native call are running at the same time". My situation is exactly the same. I need to call one native plugin method more than once simultaneously. I also want to pass a response from native plugin (as plugin result using callback ID) for each plugin call from JavaScript. I am not sure how does Cordova behave in this context. I have asked a separate question for this purpose. If possible, could you please look into this https://mcmap.net/q/1016772/-ios-cordova-does-cordova-create-multiple-instances-of-an-objective-c-plugin-when-called-more-than-once/2035845.Labialized
T
3

I am trying to figure this out in more detail, too. Basically there are 2 Methods on the iOS side that can help ...

From the sources it seems cordova sends a "READY" message using webView:shouldStartLoadWithRequest:... and then picks up results with the second message, but I am not sure.

Cordova Sources iOSExec

There is much to learn there.

Thorton answered 3/1, 2013 at 11:38 Comment(1)
I believe you're right, and seeing your answer saved me from going down the wrong rabbit hole for too many more hours. Check out my response to @Christian-kuetbach above for a 10,000 ft perspectiveCapitulation

© 2022 - 2024 — McMap. All rights reserved.