Level: Intermediate
Adam Houghton (adam@adamhoughton.com), Senior Software Developer, SAS Institute, Inc.
29 Jan 2008
Learn to create iPhone Web sites using Eclipse, Aptana's iPhone Development plug-in, and the iUi framework. See the development of a Javadoc viewer for the iPhone, uncover tips for user interface design, and hear about the future of iPhone application development.
Apple's iPhone platform presents an interesting opportunity to developers. With a small form factor and interactive touchscreen, the iPhone and iPod Touch have won over millions of users in a short period of time. But this novel design and proprietary platform present a new set of challenges for application developers. Until Apple releases its software development kit (SDK) in February 2008, developers wishing to target the platform must create Web applications that mimic the iPhone's native look and feel.
Fortunately, a new set of open source tools is available to make this easier. Aptana's iPhone Development plug-in for Eclipse generates iPhone-specific projects and previews applications in a rotatable viewfinder. Joe Hewitt's iUi, a Cascading Style Sheets (CSS) and JavaScript framework, contains a grab bag of widgets and pages that emulate the native iPhone experience.
In this article, we use Aptana and iUi to create a new application: a simple Javadoc viewer for the iPhone. First, we design a user interface (UI) for browsing Javadoc on an iPhone, then create a custom doclet to generate the Javadoc pages from any source code. Along the way, we describe UI issues encountered when targeting the iPhone, how these open source tools can simplify development and debugging, and the future direction of iPhone development.
A quick walk through the tools
Start by installing Aptana and downloading iUi:
http://update.aptana.com/update/3.2/
. When everything is in place, use Eclipse to create a new iPhone Project called iDoc, shown in Figure 1.
Figure 2 shows the resulting project containing a simple iPhone application.
Note the syntax highlighting provided by Aptana's base editor, which supports HTML, CSS, and JavaScript.
iPhone Preview mode and application server
At the bottom of the text editor, you see the tabs Source, iPhone Preview, and each browser installed on your system (for example, Safari Preview, Firefox Preview). Click iPhone Preview to see what the sample application looks like on the iPhone. Click outside the browser to rotate the phone or click the phone title bar to hide the navigation bar. The horizontal iPhone Preview mode is shown below.
The iPhone Preview mode is a great time-saver: You can test new design ideas quickly and iteratively develop without leaving the computer. When it's time to test drive your application on an actual iPhone, Aptana's built-in application server comes in handy. Click the Run icon on the Eclipse toolbar to launch the server. Figure 4 shows the application server running in Eclipse.
If your iPhone is connected to your local network through a WiFi connection, it can access the URL displayed on the server window. Save yourself a step by clicking E-mail this url and sending a message to the e-mail account on your iPhone. Tap the link in the e-mail, and the application launches in the iPhone's Web browser.
iUi demo: Theater listings Web application
Although Aptana's starter application contains iPhone-specific HTML and CSS files, they are limited in functionality. A better alternative is the iUi framework, which has a rich set of custom widgets and JavaScript effects that accurately mimic the native iPhone interface.
Uncompress the downloaded iUi distribution, iui-0.13.tar, and copy the files into the iDoc Project in Eclipse. Figure 5 shows a Project containing iUi.
The demo Web applications for iUi are found in the samples folder, expanded above. They include a music browser, theater listings, and a Digg-like site. Using Aptana's iPhone Preview mode, we can view them in Eclipse. Figure 6 shows the search page of the theater listings Web application (samples/theaters/index.html).
Note how closely the demo resembles the native iPhone look and feel. These prepackaged widgets enable rapid development of iPhone Web applications.
|
In this example, create a Javadoc viewer for the iPhone called iDoc. The dense HTML files created by Sun Microsystems' standard Javadoc generator look great on the desktop, but are difficult to navigate and read on the iPhone. iDoc generates iPhone-friendly Javadoc — perfect for browsing application program interfaces (APIs) on the subway or letting the observer in your pair programming team help out.
iPhone human interface guidelines
Before we start designing the UI for iDoc, it's important to understand what makes iPhone development different from ordinary Web development. Figure 7 from Apple's iPhone Dev Center (see Resources) summarizes it nicely: A finger is not a mouse. This removes the pixel preciseness found in desktop applications, but opens a rich new user interaction model with taps, flicks, and pinches. Additionally, an iPhone travels with a user and is often used in distracting environments, so applications need to provide quick, easy access to targeted information.
Apple's iPhone Human Interface Guidelines (see Resources) define three types of iPhone Web content.
Standard Javadoc pages fall under the first category, Compatible with Safari on iPhone. They can be displayed correctly, but require a good deal of pinching and flicking to find relevant information. With iDoc, aim for a full iPhone application. Although there are no opportunities for integrating with other services, iDoc's interface feels right at home on the iPhone.
When targeting the iPhone, it's important to remain focused. Applications should accomplish specific tasks in a quick manner, not try to include every possible feature. With iDoc, users must find basic documentation about Java classes, such as class names, method names, method signatures, and comments. Present this information with three levels of navigation leading to a destination detail page.
To keep iDoc uncluttered and task-focused, some traditional Javadoc features are missing. For example, package description comments aren't displayed. Because these are often uninformative (for example, acme.client contains client code) and sometimes missing altogether, it makes sense to leave them out of iDoc and simplify the interface.
For the three levels of navigation, use an edge-to-edge list. This is a familiar construct in native iPhone applications, used for browsing contacts, e-mail, and music. Edge-to-edge lists display items in equal-size rows 44 pixels high and are useful for scrolling through large amounts of information. Apple's iPhone Human Interface Guidelines provide metrics for constructing an edge-to-edge list, including font, font size, and border spacing. The iUi framework implements these metrics in CSS and the JavaScript language, allowing you to create simple HTML lists displayed like native iPhone components.
Listing 1 shows the page header, along with the first two levels of navigation for the java.applet and java.rmi packages.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>iDoc</title> <meta name="viewport" content="width=320; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;"/> <style type="text/css" media="screen">@import "iui/iui.css";</style> <style type="text/css" media="screen">@import "iDoc.css";</style> <script type="application/x-javascript" src="iui/iui.js"></script> </head> <body onclick="console.log('Hello', event.target);"> <div class="toolbar"> <h1 id="pageTitle"></h1> <a id="backButton" class="button" href="#"></a> </div> <ul id="home" title="Packages" selected="true"> <li><a href="#java.applet">java.applet</a></li> <!-- more packages...--> <li><a href="#java.rmi">java.rmi</a></li> </ul> <ul id="java.applet" title="java.applet"> <li class="group">Interfaces</li> <li><a href="java.applet.AppletContext.html"> AppletContext</a></li> <li><a href="java.applet.AppletStub.html"> AppletStub</a></li> <li><a href="java.applet.AudioClip.html"> AudioClip</a></li> <li class="group">Classes</li> <li><a href="java.applet.Applet.html">Applet </a></li> <li><a href="java.applet.Applet.AccessibleApplet.html"> AccessibleApplet</a></li> </ul> <ul id="java.rmi" title="java.rmi"> <li class="group">Interfaces</li> <li><a href="java.rmi.Remote.html"> Remote</a></li> <li class="group">Classes</li> <li><a href="java.rmi.MarshalledObject.html"> MarshalledObject</a></li> <li><a href="java.rmi.Naming.html"> Naming</a></li> <li><a href="java.rmi.RMISecurityManager.html"> RMISecurityManager</a></li> <li class="group">Exceptions</li> <li><a href="java.rmi.AccessException.html"> AccessException</a></li> <li><a href="java.rmi.AlreadyBoundException.html"> AlreadyBoundException</a></li> <li><a href="java.rmi.ConnectException.html"> ConnectException</a></li> <li><a href="java.rmi.ConnectIOException.html"> ConnectIOException</a></li> <li><a href="java.rmi.MarshalException.html"> MarshalException</a></li> <li><a href="java.rmi.NoSuchObjectException.html"> NoSuchObjectException</a></li> <li><a href="java.rmi.NotBoundException.html"> NotBoundException</a></li> <li><a href="java.rmi.RemoteException.html"> RemoteException</a></li> <li><a href="java.rmi.RMISecurityException.html"> RMISecurityException</a></li> <li><a href="java.rmi.ServerError.html"> ServerError</a></li> <li><a href="java.rmi.ServerException.html"> ServerException</a></li> <li><a href="java.rmi.ServerRuntimeException.html"> ServerRuntimeException</a></li> <li><a href="java.rmi.StubNotFoundException.html"> StubNotFoundException</a></li> <li><a href="java.rmi.UnexpectedException.html"> UnexpectedException</a></li> <li><a href="java.rmi.UnknownHostException.html"> UnknownHostException</a></li> <li><a href="java.rmi.UnmarshalException.html"> UnmarshalException</a></li> </ul> |
Figure 8 shows the resulting top level of navigation for selecting packages, using edge-to-edge lists.
Figure 9 shows the resulting java.rmi package displayed in iPhone Preview mode.
For iDoc's destination detail page, use another iPhone construct: a rounded-rectangle list. These lists are useful for grouping information and are found throughout the settings panels on the iPhone. Use rounded-rectangle lists for separating method signatures and listings of parameters and exceptions. In V0.13, iUi only supports rounded-rectangle lists for form input; using their elements for static text produces incorrectly formatted blocks. Extend their CSS with a custom iDoc.css file (shown in Listing 2) to add a textRow
element for displaying rounded-rectangle lists with static text.
textRow
CSS extension to correctly display static text/* Adding a new row CSS style to iUi for displaying blocks of text */ .textRow { position: relative; border-bottom: 1px solid #999999; -webkit-border-radius: 0; text-align: right; } .textRow > p { text-align: left; margin: 5px 8px 5px 10px; padding: 0px 0px 0px 0px; } fieldset > .textRow:last-child { border-bottom: none !important; } |
Listing 3 shows the detail page for one of java.math.BigDecimal
's constructor methods.
textRow
elements<div id="java.math.BigDecimal(long,java.math.MathContext)" title="BigDecimal" class="panel"> <fieldset> <div class="textRow"><p><b> public BigDecimal(long, MathContext)</b></p></div> <div class="textRow"><p>Translates a <code>long</code> into a <code>BigDecimal</code>, with rounding according to the context settings. The scale of the <code>BigDecimal</code>, before any rounding, is zero. </p></div> </fieldset> <h2>Parameters</h2> <fieldset> <div class="textRow"><p><b>long val </b>: <code>long</code> value to be converted to <code>BigDecimal</code>.</p></div> <div class="textRow"><p><b>MathContext mc </b>: the context to use.</p></div> </fieldset> <h2>Throws</h2> <fieldset> <div class="textRow"><p><b>ArithmeticException </b>: if the result is inexact but the rounding mode is <code>UNNECESSARY</code>.</p></div> </fieldset> </div> |
Everything within the <fieldset>
tag is inside the rounded rectangle, with textRow <div>
s splitting the rows. Headings with <h2>
tags are displayed as group labels above the lists. Figure 10 shows the resulting page.
With the three levels of navigation and the destination detail page, the UI is complete. iDoc lets users focus on a specific task. With the help of the iUi framework and some custom CSS, it looks like a native iPhone application.
|
Now that we have designed the UI, we need code to generate HTML files. Create a simple doclet that plugs into Sun's javadoc
command. Our examples use standard java.* packages, but iDoc can generate Javadoc from any source code. Use the OpenJDK source code (see Resources), as it's publicly available and the GNU Public License (GPL) V2 license lets us generate and distribute its Javadoc.
With iDoc, simply iterate over the packages and classes and call methods to print static HTML pages in the format described above. Listing 4 shows the methods for printing the destination detail pages.
private void printDetail(PrintStream p, ProgramElementDoc doc, String id, String name) { divHeader(p, id, name, "panel"); textHeader(p, null); textRow(p, getSignature(doc)); textRow(p, getCommentText(doc.commentText())); textFooter(p); if (doc instanceof ExecutableMemberDoc) { printMethodDetail(p, (ExecutableMemberDoc) doc); } divFooter(p); } private void printMethodDetail(PrintStream p, ExecutableMemberDoc field) { if (field.parameters().length > 0) { textHeader(p, "Parameters"); for (int i=0; i<field.paramTags().length; i++) { textRow(p, "<b>" + field.parameters()[i].typeName() + " " + field.paramTags()[i].parameterName() + "</b>: " + getCommentText(field.paramTags()[i].parameterComment())); } textFooter(p); } if (field.throwsTags().length > 0) { textHeader(p, "Throws"); for (int i=0; i<field.throwsTags().length; i++) { textRow(p, "<b>" + field.throwsTags()[i].exceptionName() + "</b>: " + getCommentText(field.throwsTags()[i].exceptionComment())); } textFooter(p); } } |
The code is generalized such that printDetail()
handles the output of class descriptions, fields, constructors, and methods. The latter two types are subclasses of ExecutableMemberDoc
, so additional information is printed about their parameters and thrown exceptions.
|
Aptana's iPhone Preview mode helps debug the outputted files. After each iteration, you can quickly click through the application to find inconsistencies from the designed interface. However, using Preview mode can mask performance problems: Modern computers run three to five times faster than the iPhone's 620-MHz ARM processor. Additionally, users often download pages over slow cellular networks, so it's important to run your application with an actual iPhone.
In my tests viewing iDoc on an iPhone, I find that outputting one giant HTML file causes jumpy animations and degrades performance. To fix this, create one main file for navigating package/class names, then create separate files for each class with comments and method details (see Listing 5). Although this process produces a large number of files, the individual file sizes are small, and the application runs smoothly.
out = new FileOutputStream(index); p = new PrintStream(out); printHeader(p); PackageDoc[] packages = root.specifiedPackages(); Arrays.sort(packages); printPackages(p, packages); for (int i=0; i<packages.length; i++) { printPackageDetail(p, packages[i]); } for (int i=0; i<packages.length; i++) { ClassDoc[] classes = packages[i].allClasses(); Arrays.sort(classes); for (int j=0; j<classes.length; j++) { // Creating a separate file for each class. PrintStream p2 = new PrintStream(new FileOutputStream(getFilename(classes[j]))); printClassDetail(p2, classes[j]); p2.close(); } } printFooter(p); p.close(); |
With this performance enhancement, iDoc is ready to go. Generate Javadoc for the 51 java.* and javax.* packages in OpenJDK, representing 1,304 classes, then upload everything to your Web server. This comprises more than 16 MB of files, but the main navigation page is only 112 KB, and the individual class detail pages average 13 KB each. Even when using the EDGE network, the application is quite responsive. If you've got an iPhone, visit the iDoc site (see Resources) and try it out, or you can download iDoc to generate iPhone-specific Javadoc for your own code base. Figure 11 shows the final application.
Potential extensions to iDoc include support for displaying Java 5 generics and smarter capturing of tags within Javadoc comments to implement links between pages. The full source code is available online (see Resources) if you're interested in adding to iDoc's functionality.
|
In October 2007, Steve Jobs announced that Apple will release an iPhone SDK in February 2008. The details are sparse as this was written in December 2007, but an SDK will allow you to create applications that run natively on the iPhone without needing Safari. Given the underlying iPhone architecture, it is likely that the development platform will be Cocoa and Objective-C, similar to Mac OS X. Recent comments by Apple executives suggest that third-party applications will need to undergo some type of certification process.
Applications requiring advanced animation, graphics, and network access will benefit from running natively. However, even when the SDK is released, Web development for the iPhone will still be an attractive proposition. Web applications are easy to create and simple to deploy. Tools such as Aptana and iUi simplify development and allow for rapid creation of Web applications. As shown with iDoc, there's no need to wait for the SDK: With today's tools, you can create fully featured iPhone Web applications with a native look and feel.
Adam Houghton is a senior software developer in the SAS Advanced Computing Lab and specializes in all things Java. |