Home » Android » Apache Cordova – Principle

Apache Cordova – Principle

Overview

Apache Cordova (formerly PhoneGap) is a framework which lets you build cross platform phone applications.If you use Cordova for your app development, most of functionality ( UI layer and Backend) can be built using html and web-service. These components can be re-used when you port from one platform to another. Integration with Native layer would require some customization (20-25%) from platform to platform
In this 2 part series I shall try to cover the basic principles and workflow of Cordova. Examples given are specific to Android but I am sure, principles stay same, it will be easy to translate.

1. In part 1, I shall discuss on Principle of Cordova – how the communication happens between JavaScript and Native platform. This will facilitate us in understanding the actual workflow in Cordova
2. In part 2, We shall look at  Workflow in Cordova

JavaScript to Native

Applications which uses Cordova framework are built using html and javascript. JS facilitates communication between UI Layer and Native platform. You can download a demo application from here This is a bare bone application which demonstrates communication between JavaScript and Android Native. Its based off Cordova Code but I have simplified it to help understand concept better .There are 3 important pieces

      1. Client Interaction
      2. Intercepting in Android
      3. Response From Android to JavaScript

We shall look at each of 3 in more details

1. Client Interaction

This is facilitated by html and javascript. Cordova uses JS Prompt for communication between JS Layer and Native platform .  Take a look at html under assets/www folder in demo application. There are two buttons in page and when these buttons are clicked javascript function callnative is invoked which in turn invokes demo.callnative . Below is the entire script .

      var methodStack = {},
      callbackId = 0,
      port;
       firsttime = true;

       var callback = {
          startXhr : function() {
          xmlhttp = new XMLHttpRequest();
          xmlhttp.onreadystatechange = function() {
          console.log("xmlhttp on state changed" + xmlhttp.readyState);
           if (!xmlhttp) {
              console.log("Not xmlHttp");
              return;
            }
         if (xmlhttp.readyState === 4 && xmlhttp.status === 200) {
             console.log("xmlhttp status: " + xmlhttp.status);
             var msg = decodeURIComponent(xmlhttp.responseText);
             if(msg!='undefined'){
              console.log("msg = "+msg);
              eval(msg);
              }
           }
        }
        xmlhttp.open("GET", "http://127.0.0.1:" + port, true);
        xmlhttp.send();
},

onSuccess : function(callbackId, args) {
      methodStack[callbackId].success(args);
},

onError : function(callbackId, args) {
      methodStack[callbackId].fail(args);
}
};

var demo = {
       callnative : function(successCallBackMethod, failureCallBackMethod, params) {
       if (firsttime) {
         port = prompt("get_port");
         firsttime = false;
        }
        callback.startXhr();
        callbackId++;
        methodStack[callbackId]={success : successCallBackMethod,fail : failureCallBackMethod};
        result = prompt(params, params + ":" + callbackId);
        if (result != "") {
           eval(result);
         }
        }
      };
     

Key Points to look at

  •  If function is called first time it sends prompt message – to get port – Line 41
  •  It starts XHR Request on port obtained in step 1. This generates XMLHttpRequest, and waits for response from server – Line 43
  •  Stores callbackId with appropriate methods( successCallBackMethod, failureCallBackMethod). This is used to process response from Native layer – Line 46
  •  Calls prompt again, this time with the parameters which are passed to function – Line 47

2. Intercepting in Android

NativeDemo is our main activity. There are two mediums through which Native platform can communicate/respond to JS Layer

  1. Invoking confirm on JsPromptResult . This is synchronous mode of response. This will be invoked when user clicks on “Confirm” button in  screen
  2.  Using simple server to respond to XHR Request (generated in in step 1 -Client Interaction/UI above). This is asnychronous mode of response

Cordova inernally uses combination of both depending on nature of request. For Plugins however default mode of response is asynchronous, which can be overridden

Below is the code for NativeDemoActivity

    public class NativeDemo extends Activity {

TrimmedDownCallbackServer trimmedServer;
@SuppressLint("SetJavaScriptEnabled")
@Override
public void onCreate(Bundle savedInstanceState) {
    trimmedServer = new TrimmedDownCallbackServer();

    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    WebView webView = (WebView) findViewById(R.id.webview);
    webView.getSettings().setJavaScriptEnabled(true);
    webView.loadUrl("file:///android_asset/www/index.html");

    webView.setWebChromeClient(new WebChromeClient(){
   public boolean onJsPrompt(WebView view, String url,String message, String defaultValue,JsPromptResult result){

   if(message.trim().equals("get_port")){
     result.confirm(generateResponseForPort());
   } else {
     result.confirm(genrateResponseForClick( message, defaultValue));
   }
   return true;
}
});
}

private String generateResponseForPort(){
     String response = trimmedServer.getPort()+"";
     return response;
}

private String genrateResponseForClick(String message, String defaultValue){
    String response = "";
    String androidResult = "";
    String [] array =defaultValue.split(":");
    String respChannel = array[0];
    String params = array[1];
     String callbackId = array[2];
     ///// do some action and generate result .
    if(respChannel.equals("Callbackserver")) {
       androidResult = "Server -"+message;
       String msgForQueue = "callback.onSuccess('"+callbackId+"','"+androidResult+"');";
       trimmedServer.addMessagetoQueue(msgForQueue);
    } else {
      ///// send response via JS confirm message
      androidResult = "JS Prompt-"+message;
     response = "callback.onSuccess('"+callbackId+"','"+androidResult+"');";
   }
    return response;
    }
 }
        

Key points to note

  • We are initializing and starting the server(TrimmedDownCallbackServer). This is barebones server (trimmed down for simplicity) based off Cardova  CallBackServer. In real scenario it needs to be beefed up by adding additional security  measures like token etc – Line  7
  • In main activity, we are creating instance of WebView, setting it to WebChromeClient , and override onJsPrompt method. – Line 15
  •  If message from client is get_port,  it is responded synchronously via result.confirm – Line 19
  • if message is other than get_port,   method generateResponseForClick() is invoked – Line 21 . In this case we  parse the parameters and find out which button user has clicked.
    • if user has clicked on button “CallBackServer”, message  is added to queue (Line 44) , and empty response is returned (Line 50)
    • if user has clicked on button “Confirm”, response is appended with callback method & result (Line 48)
  • Response is confirmed to client – Line 21

Below is response String when user clicks on CallBackServer button

           callback.onSuccess('2','Server-Callbackserver:test');
           

Generating response in above format, facilitates us to use eval function in JS side .In this example we are just appending some parameters to request and returning it as response. In real application, response you generate will be based on action which user requests.

3.Processing of Response

Last step is processing of response from server and displaying message to user

  • If response is returned via result.confim, result is evaluated and appropriate call back method is called. – Line 49
  • If response is returned via server then it is processed via onreadystatechange - Line 9. This method is very simplistic for demo purposes and in real scenario you need to additional checks.

That was overview on principle of how Cordova works. In next part we will look at specific workflow of Cardova

About these ads

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: