9

I was looking through the Phonegap sources for Android, and trying to verify that their notification.alert() method simply delegates to the native JavaScript alert() function. Their code does:

Notification.prototype.alert = function(message, completeCallback, title, buttonLabel) {
    var _title = (title || "Alert");
    var _buttonLabel = (buttonLabel || "OK");
    PhoneGap.exec(completeCallback, null, "Notification", "alert", [message,_title,_buttonLabel]);
};

Which looks to me like "alert" will be interpreted as the name of the function to invoke in exec(), but exec() is doing:

PhoneGap.exec = function(success, fail, service, action, args) {
    try {
        var callbackId = service + PhoneGap.callbackId++;
        if (success || fail) {
            PhoneGap.callbacks[callbackId] = {success:success, fail:fail};
        }

        //using:  ["Notification", "alert", callbackId, true]
        var r = prompt(PhoneGap.stringify(args), 
                       "gap:"+PhoneGap.stringify([service, action, callbackId, true]));

        //...
    } catch (e2) {
        console.log("Error: "+e2);
    }
}; 

Now PhoneGap.stringify() simply resolves to JSON.stringify(), so the Phonegap code is executing the notification.alert() API method by calling the prompt() function with two JSON objects/arrays. My assumption is that prompt() is the native JavaScript prompt() function (I've not found anything in their JavaScript code that would override this function). If that is the case, then how is this code working?

They make similar use of prompt() in various other places, as well:

PhoneGap.JSCallbackPort = prompt("getPort", "gap_callbackServer:"); 

Is there something special about the way they are calling prompt() (specifically by including a second parameter of the form gap.*:.*) that is enabling some custom behavior? Or have they somehow overridden the default behavior of the prompt() function somewhere external to their JavaScript code?

Note that this applies specifically to the Android version of Phonegap, as other versions seem to use slightly different mechanisms for executing the API calls.

aroth
  • 54,026
  • 20
  • 135
  • 176
  • The prompt return a string. What is wrong? – xdazz Aug 31 '11 at 02:42
  • 1
    What's wrong is that the standard version of `prompt()` displays a dialog to the user. However that is not what is happening here. There is no dialog displayed as the result of these `prompt()` calls, instead some other portion of the Phonegap API is invoked. In essence, they are using `prompt()` as their primary API entry point, and I'd like to know how/why. – aroth Aug 31 '11 at 04:34

2 Answers2

7

The prompt() function has been overridden.

You can find that in DroidGap.java.

@Override
public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
......
}
Waynn Lue
  • 11,344
  • 8
  • 51
  • 76
xdazz
  • 158,678
  • 38
  • 247
  • 274
  • Yep, PhoneGap uses prompt to actually make the JavaScript to Java bridge on Android. – Paul Beusterien Aug 31 '11 at 12:17
  • 1
    Interesting. So basically Phonegap has a callback/listener defined on the webview that is notified whenever the `prompt()` method is called, before the actual JavaScript prompt dialog is shown? And in their callback method they basically check the `prompt()` parameters for an encoded task, execute it if found (or just return false if not), and then pass the result back to the JavaScript via the `JsPromptResult`? And I suppose they couldn't use `onJsAlert()` or `onJsConfirm()` for this because only `onJsPrompt()` allows a string to be returned via the result object? Clever. And circuitous. – aroth Aug 31 '11 at 13:25
  • 1
    Don't copy an old style prompt() call from some Javscript you wrote a few years ago, and paste into a phonegap project. It will silently fail at that point! I thought it would be a nice easy way to enter some info when in a developer-only mode, but no... – Magnus Smith Dec 14 '12 at 16:24
4

The JavaScript to Java bridge stopped working on the emulator in Android 2.3. A clever PhoneGap contributor discovered that piggy backing on prompt was a workaround.

Here is the Android issue.

Paul Beusterien
  • 27,542
  • 6
  • 83
  • 139