Phonegap and prompt()

2020-07-07 05:56发布

问题:

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.

回答1:

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) {
......
}


回答2:

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.