About 2 weeks ago one of my team members, Robin Eggenkamp, mentioned there would be some iPhone dev ‘conference’ this month (iPhone Dev Camp, Amsterdam), originally at the building exactly opposite of the building where our own office is. Since I’m always interested in anything related to development I agreed to tag along. I expected it to be the kind of event where some talks are organized with a small hands on lab where some expert developer teaches newbies how to get up and running.
Now I’m certainly not a newbie when it comes to development. I lead a team of Java developers working on a rather large 200.000+ loc Java EE enterprise application and in a past life I worked as a win32/MFC C++ developer. Somewhere in between I also managed to finish a CS master. But… the iPhone was new to me. Although I’ve owned Apple computers ever since System 6 was still new & shiny, I’d never touched Xcode, Objective-C or Cocoa before. The closest I ever came was firing up Project Builder on my G3 iMac’s OS X 10.2, but only to test some C++ routine.
Because of the hands-on thing, I did plan to at least read an Objective-C tutorial the night before going to the event, but unfortunately couldn’t find the time to do so. When we arrived at the scene at exactly 10:00 in the morning, the place was already rather filled up. We found a cozy spot at a place in the back and while Robin started to connect his MacBook, I looked around and noticed it was not exactly what I thought it would be. Instead of an organized series of talks, this was a bunch of people sitting behind their computers, hacking away at stuff. The atmosphere seemed top notch though and I had a quick chat with some of the other people. At around 11 there was a short introduction talk and it became clear that the intend was to code something up for the iPhone and demo it at 17:00. The best apps would win a prize, with the first prize being a speaker set and a copy of Adobe CS3 or so.
By total coincidence, only moments after having his MacBook connected to the network, Robin finally received an email that he had been accepted for the iPhone developer program, something for which he had applied a whole month before. That meant we could start with some real development now! Robin had a little bit of experience with Xcode, but had done barely more than deploy some hello world examples to the simulator and tinkering a bit with the code. The fun thing about this was that normally whenever I need to use a new technique for my regular enterprise development, I first get myself a book of at least 600 pages, read the first 200 pages of that, try out some basic concepts, read another 200 pages, try another aspect of the tech, etc before I even attempt to apply it. Now we had to build something in a language we both didn’t know, on a platform we didn’t know, with tools we didn’t know and all of that in the course of a day 😛
We started thinking about what kind of application we would try to create for the iPhone and I suddenly got the idea of letting the iPhone connect to a Mac and using data from its acceleratometer to move the Mac’s mouse pointer. I started with formulating some simple milestones to reach that goal:
- Create local Mac app that moves mouse programmatically.
- Create local iPhone app that just prints accelerator values to the screen.
- Setup a connection from the iPhone to the Mac that just sends “hello”. Let the Mac prints this.
- Integrate the individual steps to become the app we actually want. I assumed we would need some time to calibrate the raw acceleratometer and to find a suitable mapping from the meter’s range to the pixels on the Mac’s screen.
Meanwhile Robin was attempting to deploy his hello world example app to his iPhone using his just obtained certificate. It should have been a trivial thing, but after each deployment attempt a message box was displayed saying something like “0xE8000001, your mobile device has encountered an unexpected error (0x…) during the install phase: verifying application”. We tried many things, but nothing seemed to work. While we were feverishly googling for a solution, precious time on the clock ticked away. It must have been somewhere around 13:00 when Robin finally found out which settings in the project needed to be adjusted in what way. The example hello world app deployed correctly to the iPhone and it worked! Looking at the clock we realized we only had about 4 hours to go and we hadn’t written a single line of code ourselves yet…
Milestone 1 The local Mac app – moving the mouse
The initial plan was to build the Mac app in Cocoa, but we decided that using Java would be the fastest way for us, basically since we simply know the language and environment. This milestone was easily completed. Using the java.awt.Robot class moving the Mac’s mouse pointer was a breeze.
Milestone 2 The local iPhone app – printing accelerator values
For this milestone we couldn’t shy away from Objective-C anymore and actually had to take the plunge. We first looked up an example for getting data from the acceleratometer and luckily Apple had provided one. The next thing was to build a simple app, barely more than a hello world, that prints these values to the screen. This proved to be a little harder. Objective-C sometimes looks like Java and sometimes doesn’t. What are those square brackets everywhere? It looked like a kind of method call, but I couldn’t really figure out the meaning of the square brackets themselves. And how where we supposed to define properties so we could take advantage of the injection features of interface builder? Using @Property seemed obvious to us, but the compiler kept generating tons of warnings and errors. And how do we organize our code? We had created an AppDelegate, which we connected in interface builder to a mainView that inherited from the Window class. We added two labels that we injected to this view class, deployed our app to the iPhone, and… nothing happened. After feeling a little silly, we actually tried to quickly read some documentation. We learned that the square brackets have no extra special meaning, it’s just the Objective-C syntax for doing a method call. @Property needed to be accompanied with a declaration in the header and another annotation in the implementation file, @synthesize, that’s there to actually generate the getter and setter. Also, when creating a new project Xcode had already created an AppDelegate for us, something we overlooked.
With this new insight we ‘almost’ got our first real code completely working, but a few small things were still not going as planned. We therefor decided to throw it all away and change our strategy; start with an existing iPhone example application and just throw away what we don’t need and add what we do need. Going that route would save us from dealing with some of the nitty-gritty.
It was 14:00 by then and lunch had started. We enjoyed our nice and free lunch and had a chat again with the other guys. It seemed to be the case that we where hopelessly behind, since we still didn’t really had anything. After lunch things started to improve though. Having some idea of the Objective-C syntax now and using some of my almost forgotten C knowledge, we were quickly able to adapt an existing app to just print the 3 accelerator values (x, y, z) to 3 separate labels. Check!
Milestone 3 Connecting iPhone and Mac
Since we had wasted a tremendous amount of time on the deployment and second milestone, we only had little time remaining. My original plan was to have one thread on the Mac listening to incoming communication, fetching commands and dispatching these to a (blocking) queue which will be read by another thread that controls the mouse movement. For the communication we wanted to dig through the iPhone API a little to see what it had to offer. With only 2 hours remaining, we decided to use the most basic communication method available; a simple BSD socket. At the Mac side we used a simple ServerSocket in Java and at the iPhone side we used the low level C socket()/connect() functions, for which we found a basic snippet of code that needed only a few adjustments. Although absolutely not the best technical solution, we decided to create and close a connection for each message sent.
Sending a basic test string from the iPhone to the Mac worked perfectly, so a little later we were able to send the accelerator values to the Mac. Check!
Milestone 4 Integration
We had all the separate components up and running and now only needed to integrate them together. The acceleratometer’s values appeared to be in the range of -3 to 3 for all axis, while Robin’s Mac had a 1280*800 resolution. When totally in rest, there was a certain noise margin in the values that we got from the acceleratometer, so we expected that a little calibration was required. To test a little though we started with just multiplying the values we got by 60 and added that to the current mouse position. Surprisingly this already gave fairly good results. The multiplication and the rounding down to whole pixels canceled out the noise perfectly. In a few minutes we ended up with a really simple mapping that was just something like max(0,min(forceX * 15,1280)) for the movement on the X-axis. Sending about 15 messages per second appeared to be enough for smooth motion.
By now we suddenly had some time remaining, so we used that to implement the ability to also do a mouse click. Our initial approach to that was to sent a separate message for a mouse click, but it appeared to be more robust to just add the mouse button state as a fourth parameter to the existing message. At the very last moment there was a little panic when all messages being sent appeared to be empty. Apparently, our string formatting syntax for a boolean wasn’t supported by Objective-C (we used something like “%d,%d,%d,%b”) or maybe there was a difference between a primitive boolean and an Object boolean. We decided not to pursue the issue and simply use the string “false” and “true” (something I normally always stay far from, but with 30 seconds on the clock remaining there wasn’t much choice). Since we had been fumbling with the code for most of the day, we figured that our chances of winning anything where rather slim. Nevertheless we were happy that we had came up with something that worked, and actually worked rather nice.
It was now time for all of us to demo our application. Among others there was a tips of the days app, an app that retrieved quotes from the Internet, a very cool looking game where you had to touch the screen to cause a kind of bubble on which a moving object bounced to another side complete with sound effects and all and a very impressive looking application that measured your air time when skiing in addition to your speed, path and direction. Unfortunately this last app appeared to be only concept art.
When it was our time for the demo, I told something about the technical shortcuts we had taken, while Robin demonstrated how to use the iPhone to paint a running man in a painting application on the Mac.
Much to our surprise, our application was well received and we got the first price; a nice speaker set for the iPhone or iPod. We’ll install it in the office 🙂
- http://www.iphonedevcamp.nl/ The event’s home-page
- http://developer.apple.com/iphone/ Our starting point. If you’re into iPhone development, you’ve probably discovered this site already 😛
- http://java.sun.com/j2se/1.5.0/docs/api/java/awt/Robot.html Java’s Robot class let’s you control the native mouse cursor
- http://www.tuaw.com/2007/09/10/iphone-coding-using-the-accelerometer Explanation about the accelerometer.
- http://discussions.apple.com/thread.jspa?messageID=7815634 Simple code example of opening a socket on the iPhone
- http://www.mobypicture.com/slideshow/idc.html Some photos taken at the event.
- http://www.bright.tv/series//iphone-dev-camp Some footage of the event by bright TV.
- http://www.admanager.nl/mobile/nieuws/8441/M4N-medewerkers_winnen_eerste_prijs_op_iPhone_Dev_Camp/ Press release of event (DUTCH)
- http://www.computable.nl/artikel/ict_topics/development/2699373/1277180/een-iphoneapplicatie-ontwikkelen-in-n-dag.html Article in the Dutch ICT magazine computable about the event.