I was so proud of myself: I held out for an amazing four days before I gave in to the iPhone. Certainly, the fact that my original phone was a piece of junk was a lot of incentive. But what really sold me was the fact that the phone had Wi-Fi built-in and—more importantly—has a great browser. You see, the software development kit (SDK) for the iPhone is standard Dynamic HTML (DHTML) through the Web browser. So, you can use all the familiar HTML, Cascading Style Sheet (CSS), and Asynchronous JavaScript™ + XML (Ajax) front-end technologies in combination with your choice of back-end technology: PHP, Rails, Java™ technology—whatever you like.
After playing with my iPhone and doing all the usual stuff like calling people, playing with Google Maps, and listening to tunes with the iPod functionality, it was time to develop something specifically for the phone. So, the question becomes, what to develop?
Well, one thing that I missed from my old phone was the Salling Clicker application. Salling Clicker turns any phone into a remote control for a Macintosh (and now, computers running Microsoft® Windows®, as well). Using the clicker application on the phone, I can launch AppleScripts on my Macintosh computer to do all kinds of useful things, such as controlling Apple iTunes or KeyNote (Apple's alternative to Microsoft Office PowerPoint®). On smart phones, this functionality required a small downloaded application on the phone. But the iPhone doesn't allow you to download special applications, because Apple Safari, the Web browser, is the SDK. So, how could I use Safari to control my Mac?
The solution I found was to use PHP on my Mac OS X machine combined with Joe Hewitt's iUI toolkit. The toolkit builds an iPhone-looking interface in the Web page. It also handles the feel of the interface. For example, as you page through a list of items, iUI sweeps from side to side, just like the iPhone does when you page through your list of contacts.
Building the application starts with defining some commands that the iPhone remote control will present for you to select. You use an XML file to define the commands. Listing 1 shows this file.
Listing 1. commands.xml
<commands>
<command title="Next Song">
tell application "iTunes" to next track
</command>
<command title="Previous Song">
tell application "iTunes" to back track
</command>
</commands>
|
The file is a list of <command> tags. Each tag has
a title attribute that defines a human readable title for the command. And the
content of the <command> tag is the AppleScript
code to execute when the command is requested. Because of XML encodings, if you
want to put in any AppleScript code that has angle bracket (< or >) or
ampersand (&) characters, you must encode those as <,
>, and &, respectively.
To wrap this XML file, I wrote a PHP V5 Command class
that reads the file, returns the command names, and runs the commands using the
Mac OS X osascript command. The code for this class is
shown in Listing 2.
Listing 2. commands.php
<?php
class Commands
{
private $_commands;
function __construct()
{
$this->_commands = array();
$doc = new DOMDocument();
$doc->load('commands.xml');
$cmds = $doc->getElementsByTagName( 'command' );
foreach( $cmds as $cmd )
{
$this->_commands []= array(
'title' => $cmd->getAttribute('title'),
'command' => $cmd->firstChild->nodeValue
);
}
}
function getCommands()
{
$cmds = array();
foreach( $this->_commands as $cmd )
{
$cmds []= $cmd['title'];
}
return $cmds;
}
function runCommand( $id )
{
$ph = popen( "osascript", "w" );
fwrite( $ph, $this->_commands[$id]['command'] );
fclose( $ph );
}
}
?>
|
The class starts by loading up the commands.xml file. It reads in the file using the
DomDocument PHP class. Then, it finds all the command
arguments using getElementsByTagName. When it has the
<command> tags as an array, the class loads the
_commands member variable with the titles and
AppleScript commands.
Two additional methods are defined:
- The
getCommands()method, which simply returns a list of the names - The
runCommand()method, which given an index runs that command using theosascriptcommand-line AppleScript executor.
With the commands XML file and Commands PHP class written,
it's time to add an interface. Just to make sure everything is
working properly, I'll put a fairly rudimentary interface on it. This interface is
shown in Listing 3.
Listing 3. Simple interface script
<html><body>
<?php
require_once('commands.php');
$cmds = new Commands();
?>
<?php
$id = 0;
foreach( $cmds->getCommands() as $cmd ) {
?>
<a href="do.php?id=<?php echo($id);?>"><?php echo( $cmd ); ?></a><br/>
<?php $id++; } ?>
</body></html>
|
The script first gets the Command class, and then asks it
for the lists of commands using the getCommands() method.
Then, the script builds a set of links to the do.php page using the command index
number and the name of the command that the Commands
class returned.
When I navigate to the page in the Safari browser, I see something like Figure 1.
Figure 1. The rudimentary interface
I could use this as my iPhone interface and it would work. But it wouldn't feel like the iPhone. So, the next thing to do is use the iUI toolkit to extend the interface. Listing 4 shows the code for doing so.
Listing 4. index.php
<!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>Mac Controller</title>
<meta name="viewport"
content="width=320; initial-scale=1.0; maximum-scale=1.0; user-scalable=no;"/>
<style type="text/css" media="screen">@import "iui/iui.css";</style>
<script type="application/x-javascript" src="iui/iui.js"></script>
</head>
<body>
<div class="toolbar">
<h1 id="pageTitle"></h1>
<a id="backButton" class="button" href="#"></a>
</div>
<?php
require_once('commands.php');
$cmds = new Commands();
?>
<ul title="Commands" selected="true">
<?php
$id = 0;
foreach( $cmds->getCommands() as $cmd ) {
?>
<li>
<a href="do.php?id=<?php echo($id);?>"><?php echo( $cmd ); ?></a>
</li>
<?php $id++; } ?>
</ul>
</body></html>
|
At the top of the file, you include the iUI CSS file that has all the styles that
give the page its iPhone look. Then, you include the iUI JavaScript file that
handles all the interactivity. After that, you use the Commands
class to get the list of commands. With that list, you build an unordered list
(<ul>) with list item elements for each item
(<li>). No, it's not as ugly as it sounds. In
fact, you can look at it in Safari, and you'll get exactly the same look as you
would on the iPhone, as shown in Figure 2.
Figure 2. The index.php page as rendered in Safari
If you use Windows, don't worry: Safari now runs on both Windows and Mac. Of
course, the PHP that runs this code must be on a Mac to run the
osascript command and the AppleScript code. But you
could use system commands if you want to run this on DOS or UNIX® systems.
The final step is to create the do.php file that index.php references to run the actual commands. This class is shown in Listing 5.
Listing 5. do.php
<?php
require_once('commands.php');
$cmds = new Commands();
$cmds->runCommand( $_GET['id'] );
?>
|
Now, you can use Safari to browse to the page locally and just click the links to check whether the application works. If everything is in order, iTunes will go to the next or previous song depending on what you select.
One thing I did have to change on my installation was to edit the /etc/httpd/httpd.conf file, change the User setting to my user name, and change the Group setting to staff. I then rebooted my Apache server by running this command line:
% apachectl graceful |
With that done, my iTunes interface flipped back and forth between tracks when I clicked the links. I can then turn on my iPhone and use the Safari browser to go to my local machine by IP address and access the application, as long as my laptop and my iPhone are on the same Wi-Fi network.
As I did the research for this article, I found that someone had already taken this whole concept of a Mac-driven remote for the iPhone to a new level. The project is called telekinesis, and it's hosted on the Google Code site. The application is called iPhone Remote, and it runs as a graphical user interface (GUI) application in Mac OS X.
When I launch iPhone Remote, it opens Safari to a page that shows what it will look like on the iPhone. This is shown in Figure 3.
Figure 3. The iPhone Remote interface
From here, I can navigate to my applications and open them, browse my documents, use an iTunes remote, even navigate around the screen and run command lines—all from my iPhone.
The iPhone Remote does prompt you for a user name and password so that not just anyone can use your Mac after you've installed and run it. So, it's possible to use the iPhone as a secure virtual network computing (VNC) device for your Mac remotely.
Developing for the iPhone is a breeze. The ads say that the iPhone gives you access to the Internet as is rather than some mobile version of it, and the ads are right: You can browse to your normal pages just as you would on your Mac or PC. But toolkits like the iUI interface builder help give the application a more genuine iPhone look and feel—handy with applications like this XML and PHP-driven iPhone remote.
Learn
-
iPhone: See Apple's iPhone site, a good place
to find information on the iPhone.
-
PHP home page: Visit the PHP home page to learn all about
PHP.
-
iUI toolkit: Check out Joe Hewitt's site and learn
more about the iUI toolkit.
-
Salling Clicker: Learn more about the Salling
Clicker, the original inspiration for this article. It remains a fantastic resource for people who want
to use their mobile phones to control their Macs or PCs.
-
iPhone Remote: Explore the iPhone Remote
from the telekenesis project, the full version of this example.
-
IBM XML certification:
Find out how you can become an IBM-Certified Developer in XML and related
technologies.
-
XML technical library:
See the developerWorks XML Zone for a wide range of technical articles and tips,
tutorials, standards, and IBM Redbooks.
-
developerWorks
technical events and webcasts: Stay current with technology in these sessions.
- The technology
bookstore: Browse for books on these and other technical topics.
Get products and technologies
-
Have an iPhone?: Don't miss a single developerWorks feed ever again. Pick a topic, zone, brand, select an article, read the blurb, or visit the site. All on your iPhone with this feed URL: http://www.ibm.com/developerWorks/iphone.
-
IBM trial software: Build your next development project with trial software available for download directly from developerWorks.
Discuss
- Participate in the discussion forum.
-
XML zone discussion
forums: Participate in any of several XML-centered forums.
-
developerWorks XML zone: Share your thoughts: After you read this article, post your comments and thoughts in this forum. The XML zone editors moderate the forum and welcome your input.
-
developerWorks blogs: Check out these blogs and get involved in the developerWorks community.
Jack D. Herrington is a senior software engineer with more than 20 years of experience. He's the author of three books: Code Generation in Action, Podcasting Hacks, and PHP Hacks. He has also written more than 30 articles. You can reach Jack at jherr@pobox.com.





