phonegap framework

Keywords: socket Java Android Javascript

First, take a look at the phonegap initialization process and the flow chart of Native and JS interaction.

 

Description: In socket server mode, phonegap.js source code implements an XHR request in 1 millisecond, when there is JS statement data in the Native JS queue, it is the real 1 millisecond call; when there is no data, scoket server blocks 10 milliseconds, that is, XHR waits 10 seconds to receive the results and conduct the next polling.

 

1. Activity inherits DroidGap (extends PhonegapActivity)

Load whitelist configuration and log configuration from phonegap.xml


2. loadUrl (each Activity is initialized once)

>> Initialize webview
>> Initialize callbackServer
>> Plugin Manager

 

3. Load plug-in configuration:

>> Read the plugins.xml configuration and store it in map.

<plugins>
<plugin name="Camera" value="com.phonegap.CameraLauncher"/>
<plugin name="Contacts" value="com.phonegap.ContactManager"/>
<plugin name="Crypto" value="com.phonegap.CryptoHandler"/>
<plugin name="File" value="com.phonegap.FileUtils"/>
<plugin name="Network Status" value="com.phonegap.NetworkManager"/>
</plugins>

Explain:
name is an alias, which is called by an alias when javascript is invoked.
value: java implementation class

web page calls (for example, finding associates)
PhoneGap.exec(successCB, errorCB, "Contacts", "search", [fields, options]);


4. Plug-in Implementation

>> Programming java class, inheriting Plugin class (Plugin implements IPlugin interface), and implementing execute method.
For example, the Contact Management Plug-in:

public class ContactManager extends Plugin{
    /**
     * action : Used to specify a specific action search to represent search contacts 
     * args:  Method parameters
     * callbackId: js Specify an identity with java,
     */
  	public PluginResult execute(String action, JSONArray args, String callbackId) {
		try {
			if (action.equals("search")) {
				JSONArray res = contactAccessor.search(args.getJSONArray(0), args.optJSONObject(1));
				return new PluginResult(status, res, "navigator.contacts.cast");
			}
			else if (action.equals("save")) {
			    String id = contactAccessor.save(args.getJSONObject(0));
			    if (id != null) {
	                	          JSONObject res = contactAccessor.getContactById(id);
	                                  if (res != null) {
	                                     return new PluginResult(status, res);
	                                 }
			    }
			}
			else if (action.equals("remove")) {
				if (contactAccessor.remove(args.getString(0))) {
					return new PluginResult(status, result);					
				}
			}
			// If we get to this point an error has occurred
           		JSONObject r = new JSONObject();
            		r.put("code", UNKNOWN_ERROR);
                            return new PluginResult(PluginResult.Status.ERROR, r);
		} catch (JSONException e) {
			Log.e(LOG_TAG, e.getMessage(), e);
			return new PluginResult(PluginResult.Status.JSON_EXCEPTION);
		}
    }
}

  


5. Poling and server initialization


When android DroidGap is initialized, if the url of loadUrl does not start with file://polling = true, otherwise it is socket server mode

See CallbackServer.java class init method for the code

public void init(String url) {
    //System.out.println("CallbackServer.start("+url+")");
    // Determine if XHR or polling is to be used
    if ((url != null) && !url.startsWith("file://")) {
       this.usePolling = true;
       this.stopServer();
    }
    else if (android.net.Proxy.getDefaultHost() != null) {
        this.usePolling = true;
        this.stopServer();
    }
    else {
        this.usePolling = false;
        this.startServer();
    }
}

  


6. phonegap.js Key Code Description

 

When phonegap.js starts, it first gets the invocation mode through prompt("usePolling", "gap_callbackServer:"): XHR polling OR prompt polling, and if it is XHR, it starts XHR calling to get the http server port and token.


Method PhoneGap.Channel.join starts js server or polling calls

UsePolling defaults to false. Get the invocation method by VAR polling = prompt ("usePolling", "gap_callbackServer:").

 PhoneGap.Channel.join(function () {

    // Start listening for XHR callbacks
    setTimeout(function () {
      if (PhoneGap.UsePolling) {
        PhoneGap.JSCallbackPolling();
      }
      else {
        console.log('PhoneGap.Channel.join>>>>>>>>>>>>>>>>>>>>>>>>>');
//phonegap js starts for the first time to get js to call Native mode var polling = prompt("usePolling", "gap_callbackServer:"); PhoneGap.UsePolling = polling; if (polling == "true") { PhoneGap.UsePolling = true; PhoneGap.JSCallbackPolling(); } else { PhoneGap.UsePolling = false; PhoneGap.JSCallback(); } } }, 1); }

  

XHR polling: PhoneGap.JSCallback method

Communicate with java socket through XHR, execute JSCallback once per millisecond, get javascript execution result code from android socket, and execute javascript dynamically through eval.

XHR call to get the socket port and token (uuid) through prompt

if (PhoneGap.JSCallbackPort === null) {
   PhoneGap.JSCallbackPort = prompt("getPort", "gap_callbackServer:");
   console.log('PhoneGap.JSCallback getPort>>>>>>>>>>>>>>>>>>>>>>>>>:' + PhoneGap.JSCallbackPort);
}
if (PhoneGap.JSCallbackToken === null) {
  PhoneGap.JSCallbackToken = prompt("getToken", "gap_callbackServer:");
  console.log('PhoneGap.JSCallback getToken>>>>>>>>>>>>>>>>>>>>>>>>>:' + PhoneGap.JSCallbackToken);
}
xmlhttp.open("GET", "http://127.0.0.1:" + PhoneGap.JSCallbackPort + "/" + PhoneGap.JSCallbackToken, true);
xmlhttp.send();

XHR Return result code fragment
var msg = decodeURIComponent(xmlhttp.responseText);
setTimeout(function () {
try {
    var t = eval(msg);
}
catch (e) {
  // If we're getting an error here, seeing the message will help in debugging
  console.log("JSCallback: Message from Server: " + msg);
  console.log("JSCallback Error: " + e);
}
 }, 1);
 setTimeout(PhoneGap.JSCallback, 1);
}

  

prompt polling: PhoneGap.JSCallbackPolling method

 

PhoneGap.JSCallbackPolling = function () {

    // Exit if shutting down app
    if (PhoneGap.shuttingDown) {
      return;
    }

    // If polling flag was changed, stop using polling from now on
    if (!PhoneGap.UsePolling) {
      PhoneGap.JSCallback();
      return;
    }

    var msg = prompt("", "gap_poll:");
    if (msg) {
      setTimeout(function () {
        try {
          var t = eval("" + msg);
        }
        catch (e) {
          console.log("JSCallbackPolling: Message from Server: " + msg);
          console.log("JSCallbackPolling Error: " + e);
        }
      }, 1);
      setTimeout(PhoneGap.JSCallbackPolling, 1);
    }
    else {
      setTimeout(PhoneGap.JSCallbackPolling, PhoneGap.JSCallbackPollingPeriod);
    }
  };

  

7. Summary

1. When Plugin Manager, the phonegap android plug-in manager is initialized, every Activity is initialized once, and the data is cached once, which results in the same data being cached many times. It's not clear why this is done. Is the phonegap framework implemented for a single webview? If you know why, please let me know.

2. As in point 1, each Activity of Socket Server will be initialized. If the url type of loadUrl is different, will it lead to the disorder of scoket server body?

3. phonegap uses prompt and XHR polling mechanism. One is that it will lead to serious power consumption of mobile phones, and the other is that it will block the execution of js by prompt call, which will affect the page loading speed.

 

phonegap has been renamed cordova, and socket server mode has been removed from the latest version of Cordova framework. For more details, please see: http://www.cnblogs.com/hubcarl/p/4202784.html

 

Reprinted at: https://www.cnblogs.com/hubcarl/p/4216844.html

Posted by jon23d on Wed, 26 Jun 2019 16:40:34 -0700