Deep Dive into Apache Cordova (PhoneGap) with Android

In this Blog post I will talk about how Apache Cordova works in detail with respect to android. This is for curious minds who like to know how it works and how is it implemented. Apache Cordova is an application framework that enables you to build natively installed mobile apps using HTML and JavaScript. This is the only free open source framework which supports 7 mobile platforms.

In this post I will give you an introduction with brief history and discuss about technique used in Cordova, implementation in Android in deep with code.

This was first started as PhoneGap in an iPhoneDevCamp, San Francisco in August 2008.(Originally this was only available for iOS) The entire development was carried out by a company named Nitobi. In October 2011, Nitobi was purchased by Adobe and the source code was donated to Apache. Since initial name given in Apache Software Foundation, ‘Callback’ was too generic, and then it was changed to Cordova.

Basically Cordova generates a hybrid app (i.e. which contains native component as well as non-native component with respect to each platform) in which

  • all UI is rendered using browser
  • functions are written in JavaScript
  • using Cordova framework access device native capabilities

let’s move to the technique of Cordova

  1. Instantiate chrome less browser instance
  2. implement “cordova.exec” bridge with JavaScript to send massages to native side
  3. implement native plugin code to push data back to JavaScript side
  4. Implement JavaScript API by wrapping cordova.exec()

You will write the entire program in index.html file and with in that file you will call JavaScript functions which are introduced by Cordova. Then those functions may call cordova.exec() bridge function which contains

  • {Function} success The success callback
  • {Function} fail The fail callback
  • {String} service The name of the service to use
  • {String} action Action to be run in cordova
  • {String[]} [args] Zero or more arguments to pass to the method (which is implemented in native code)

Let’s move to Android implementation in detail. It starts with instantiating chrome less browser and it is android webview. You can download Cordova source code from official web site or download Learn Cordova project here, open with eclipse and search through DroidGap Class.

import android.webkit.* //done in DroidGap Class

With Google excellence Android has got keen well defined interfaces and their implementations. So that WebView has several customization points

  • WebViewClient
  • ChromeViewClient
  • WebSettings
  • addJavaScriptInterface(Object, String)

And Cordova developers have exploited them in a nice way.

ChromeClient

This class is called when something that might impact a browser UI happens. for instance, progress updates and JavaScript alerts are sent here. In our case this handles JavaScripts and implementation is CorvovaChromeClient

WebViewClient

This is called when thing happens that impact the rendering of the content and intercept URL loading. Cordova overrides shouldOverrideUrlLoading() method and implementation is CordovaWebViewClient (here when overriding cordova lets WebViewClient to handle some browser API features itself)

enable JavaScripts in webView can be done through WebSetting

You may think “addJavaScriptInterface(Object, String)” is a wonderful method to implement entire Cordova functionality. But it is not…! (It was until android 2.3 cookies was used to communicate between WebClient and native code. some bug occurred in “addJavaScriptInterface()” and Cordova was forced to change the path.

At this point an out of box solution was needed. And it was overriding the prompt (download Learn Cordova project here, open with eclipse and search through CordovaChromeClient Class) With in CordovaChromeClient pluginManager.exec() is called (not to be confused with cordova.exec() )

When pluginManager receives a request for an execution, it finds the appropriate Java class and calls for the execute method. After the request is executed, it returns the PluginResult to pluginManager.

Here comes another challenge (don’t forget pluginManager is a native piece of code) put results back in the browser instance.

The obvious way is loadURL() but it has some issues. If you create web content and load to browser instance user will experience loss of focus in user interface. No matter how fast the loading there is no way to overcome. (If user was typing it would be lost and next it will focus on another input)

Next Option is CallBackServer provides a way for Java (native) to run JavaScript in the web page that has loaded Cordova.(please find in the code com.cordova.CallBackServer.java) The CallbackServer class implements

  • an XHR server (XMLHttpReuest)
  • a polling server

with a list of JavaScript statements that are to be executed on the web page(index.html)

For the completeness of the post I will brief how XHR works.

  1. JavaScript makes an async XHR call
  2. The server holds the connection open until data is available
  3. The server writes the data to the client and closes the connection
  4. The server immediately starts listening for the next XHR call
  5. The client receives this XHR response, processes it
  6. The client sends a new async XHR request

In addition if the device has a proxy set, then XHR cannot be used directly, so polling must be used instead. (Polling is actively sampling/monitoring the status of an external device by a client program as a synchronous activity)

Polling works like this, first the client calls CallbackServer.getJavascript() to retrieve next statement, if statement available, then client processes it and again the client repeats. This is how Cordova pushes native data to JavaScript.

Thats all for this post and I will talk more about Cordova in future.