Sunteți pe pagina 1din 4

PhoneGap The Internals 2010

Part 1. phonegap.js lay bare


About the Author:
Fergus Morrow is a Developer based in London, England. He has experience with web technologies such as jQuery, PHP, HTML and CSS; as well as mobile development with the iOS SDK.

Aims and Objectives:


In this introductory four part series on the PhoneGap Framework Im not going to cover the traditional tutorial type material; i.e. building apps with PhoneGap. There are a wide whole range of documents explaining these topics! Instead, I plan on examining the framework from a developers point of view, examining the internal design and structure of the framework. Naturally, this increased understanding will provide useful if you do develop apps with the framework. Over the four parts of this series I aim to cover the following: 1. Introduce you to the workings of the PhoneGap Framework 2. Examine the front-end JavaScript powering the cross platform aspects of the framework 3. Examine the back-end Objective-C code behind the iOS version 4. Begin to explore the possibilities of extending the framework If youre reading this then I expect youll have some knowledge of both JavaScript and the native SDK of the platform youre interested in. However, with some general programming knowledge (such as functions, flow control and so on) you should still be able to gain a loose understanding of the framework design.
Update 2012: Wow. I wrote this in 2010, uploaded it to scribd and forgot about it; so I was pretty surprised to see it had 6000 views when I logged on to scribd recently. I thought this was quite embarrassing as I dont consider it very comprehensive and the formatting was quite poor. However, Ive tried to clean it up a little, and will try and write an updated version soon.

Fergus Morrow (http://www.fergus-morrow.com)

PhoneGap The Internals 2010


What is PhoneGap?
To quote Wikipedia, PhoneGap is an open -source mobile development framework - but in reality PhoneGap is much more than that. PhoneGap is a revolutionary framework that allows applications to be rapidly developed using cross-platform web standards, and compiled down into a native application able to run on most of today's smart-phones. This new technology allows a much wider variety of developers to take up mobile application development. No longer are the barriers to development as high as learning a completely new programming methodology and language, developers can use their existing skills with web technologies such as AJAX, CSS and XHTML to produce applications that are both stylish and functional. For avid AJAX fans out there you are most likely aware of the cross-domain limitations of the technology. Note that as your code is being run from the local machine , it is treated as though it is using the file:// protocol for access!

So, it's a web browser?


In one sense yes its implementations generally make use of the native web browser widget which is appropriate to the platform for example; the iPhone port makes extensive use of the UIWebView component of the Objective-C iPhone SDK, and the Android port relies upon the WebView component of the Java Android SDK. However, PhoneGap goes further than this to view the framework as merely a single component of the SDK you would be missing out on a whole variety of features that PhoneGap opens up to a mobile developer. PhoneGap goes further by allowing many native platform functions to be called from JavaScript. By making such calls accessible to JavaScript code suddenly the doors open to a whole variety of new features implemented in innovative new ways. Such calls include accessing the phones hardware such as the accelerometer, compass, camera or even audio devices. In addition to providing an extensive framework to access hardware features it can also allow you to access operating system specific features like the address book, network manager, file utilities and more.

Calling native code from JavaScript... They're totally different languages?!


This is where the design and implementation of PhoneGap shines! By including a simple JavaScript file in the source code of the application (phonegap.js stay tuned for a sneak peek inside this file!) it allows a perfectly normal XHTML page to access a whole wealth of different API's. It may be worth pointing out here, that the PhoneGap implementation for each platform obviously differs I will be using the iPhone implementation in this document! So what does this JavaScript file include? This is where the beauty of Open Source programming comes into play... We can simply have a look! (As a point of reference; you'll find a lot of the PhoneGap source code is superbly documented using the doxygen framework) PhoneGapLib/javascripts/core/phonegab.js.base:
/** * Execute a PhoneGap command in a queued fashion, to ensure commands do not * execute with any race conditions, and only run when PhoneGap is ready to * receive them. * @param {String} command Command to be run in PhoneGap, e.g. "ClassName.method" * @param {String[]} [args] Zero or more arguments to pass to the method */ PhoneGap.exec = function() { PhoneGap.queue.commands.push(arguments); if (PhoneGap.queue.timer == null) PhoneGap.queue.timer = setInterval(PhoneGap.run_command, 10); };

This is noteworthy as this function is responsible for executing the majority of commands that we'll issue although we would rarely ever really notice it. This function is pretty self explanatory and the superb example of documentation/comments above it further acts as a form of explanation. By taking the arguments and pushing them to the end of the queue, it then waits for PhoneGap.queue.timer- an object that is interfaced with directly from the Objective-C code. (Something you'll see later in Part 2!) The comments above hint at the function only being ran when PhoneGap is correctly set- up and ready to receive

Fergus Morrow (http://www.fergus-morrow.com)

PhoneGap The Internals 2010


commands this is perhaps best explained by another code snippet in the same file; this time taken from the add Constructor function PhoneGapLib/javascripts/core/phonegab.js.base:
/** * Add an initialization function to a queue that ensures it will run and initialize * application constructors only once PhoneGap has been initialized. * @param {Function} func The function callback you want run once PhoneGap is initialized */ PhoneGap.addConstructor = function(func) { var state = document.readyState; if ( ( state == 'loaded' || state == 'complete' ) && DeviceInfo.uuid != null ) { func(); } else { PhoneGap._constructors.push(func); } };

This code clearly checks that the state of the web page is either loaded or complete and that the DeviceInfo.uuid (The UUID of the device) object holds a valid value. If these conditions are true, it will run a function that is specified as an argument. (i.e. specified as an anonymous function in the call) The last function we are going to look at in this file is the rather important one that explains the exact method of which JavaScript code calls the objective-C. This is by a rather cool trick that sets the location of the page to a custom protocol. Here it is! PhoneGapLib/javascripts/core/phonegab.js.base:
/** * Internal function used to dispatch the request to PhoneGap. It processes the * command queue and executes the next command on the list. If one of the * arguments is a JavaScript object, it will be passed on the QueryString of the * url, which will be turned into a dictionary on the other end. * @private */ PhoneGap.run_command = function() { /* snip */ var uri = []; var dict = null; for (var i = 1; i < args.length; i++) { var arg = args[i]; if (arg == undefined || arg == null) arg = ''; if (typeof(arg) == 'object') dict = arg; else uri.push(encodeURIComponent(arg)); } var url = "gap://" + args[0] + "/" + uri.join("/"); if (dict != null) { var query_args = []; for (var name in dict) { if (typeof(name) != 'string') continue; query_args.push(encodeURIComponent(name) + "=" + encodeURIComponent(dict[name])); } if (query_args.length > 0) url += "?" + query_args.join("&"); } document.location = url; };

This is the real brain of the framework. This block of code takes all the arguments and formats them into a string that is compliant like a standard URL. Well cover how the arguments are handled in the native code in the next part, but what we need to know now is the format of the URL it generates. Remember: this URL scheme is used behind the scenes for every call to the underlying native framework.

Fergus Morrow (http://www.fergus-morrow.com)

PhoneGap The Internals 2010


gap://CommandHandler.method?arg1Name=arg1Value&arg2Na me=arg2Value gap:// CommandHandler Method arg1Name=arg1Value... Protocol set to gap:// to enable PhoneGap to parse the URL as a command. CommandHandler a PhoneGapCommand sub-class class (i.e Location) The method to call from the CommandHandler (implemented in the PhoneGapCommand class) The arguments for the method; encoded as a URL. (Like PHP GET commands for example)

So to run an alert, which is a method of the Notification commandhandler (PhoneGapCommand sub-class), the generated URL sent to the UIWebView would be: gap://Notification.alert?message=Called%20By%20PhoneGap&title=Hello&buttonLabel=Goodbye This would call the alert method, of the Notification Command Handler and provide 3 arguments; the message, title and button label. Its important to remember that these URLs are generated through the JavaScript component of the framework, and most PhoneGap developers will be unaware of the functioning under the hood. Instead, a developer will call this functionality like this:
navigator.notification.alert( 'Called by PhoneGap', function(){ /* callback function */}, 'Hello', 'Goodbye' );

So now we have a basic understanding of what the JavaScript does when it executes a command, and weve also seen an example of how a developer would call such a command, heres a look at one of the JavaScript objects responsible for a command; the wrapper for the native compass functionality. PhoneGapLib/javascripts/core/compass.js
Compass.prototype.start = function(args) { PhoneGap.exec("Location.startHeading", args); }; Compass.prototype.stop = function() { PhoneGap.exec("Location.stopHeading"); };

Using our previous knowledge of the PhoneGap.exec() method, we can understand that we're simply telling PhoneGap to start utilising the Location service in one function, and telling it to stop in the next. The only difference being the optional second argument in the first call to PhoneGap.exec this is named in a self explanatory fashion; and contains the arguments to the call. So now we have a pretty thorough understanding of the JavaScript part of the PhoneGap Framework. In Part 2 we will explore the bindings of the native implementation examining how it interfaces with the native SDK.

Fergus Morrow (http://www.fergus-morrow.com)

S-ar putea să vă placă și