Thursday, October 23, 2008

BistroMath

My second Android application is a special-purpose calculator for solving some of the problems which often arise when it comes to paying the bill in a restaurant - like computing the tip or splitting the bill among N people. This seemed like a reasonably useful application for a device which the user always carries around and one that is very simple to do. In fact it turns out that tip calculators are somewhat the "hello world" equivalent of mobile application development. To be useful, the user experience would have to be very simple and rapid - not necessarily obvious with the clunky keyboard setup of the G1!

The calculator uses a table view of buttons as a virtual keypad for inputting numbers and another table on the top to display the results. The display table is fully specified in the XML layout file, while the cells of the keypad table are generated by the code. There is a menu to select the input fields (price, tax, tip, number of people and currency exchange rate) which can also be selected by touching the specific fields on the display using customized touch-event handlers.

When the keyboard is active, the virtual keypad is hidden and the activity intercepts keystroke events for updating the display. The application is not using any input widget, but raw events to update the display grid at every key-stroke.

The code is open-source and can be found at http://code.google.com/p/android-labs/source/browse/trunk/BistroMath

NoiseAlert

While on paternity leave, I wrote this first Android application as a kind of remote baby monitor - even though I would never dare to suggesting using it as such in public... The basic functionality is that when running the application monitors the sound volume through the microphone and if it exceeds a certain threshold automatically dials a number which previously has been configured.

Based on existing examples which come with the SDK distribution it is pretty easy to put together the basic application skeleton - including the XML description of the UI layout. If you don't know what you are looking for the documentation on the Android SDK site is a bit sparse but is great to look up details.

The application consists of an Activity, the Android abstraction for a single self-contained screen with some associated behavior and user interaction. This screen has a layout and a main menu defined in XML and provides framework methods to handle I/O and life-cycle events. For simple apps we can also use periodic event handlers to trigger actions directly from the UI thread.

It seems the only way to currently measure the sound input at the microphone is to run the MediaRecorder and use its getMaxAmplitude method to periodically get the maximum sound level since the last call. Setting up the recorder to write to "/dev/null" - the Unix special bit blackhole works just fine, which avoids filling up the flash card and having to deal with cleanup. For added benefit, there is a special graphical widget which displays a bar power meter with the current sound level from 1-10 in green and red depending on the threshold.

When it comes to calling the phone number, Android supports a intents - a framework of publish-subscribe signals which an application can send to get something done without knowing who is registered to handle them. In this case, the standard system phone application happens to be registered for the ACTION_CALL intent which is used to call a number.

The configuration is nearly automatic. A hierarchy of preferences can be described in XML and then loaded to generated a standard preferences screen which happens many common cases: on/off checkbox options, 1 out of N selection lists, text entry fields, etc. When the preference screen returns it has automatically store the results in the applications default preferences DB instance.

Thus writing a simple Android application with a main menu, some settings and a bit of behavior is really that simple.

The application code is open-source and can be found at http://code.google.com/p/android-labs/source/browse/trunk/NoiseAlert/. Application package can be downloaded from the same site or is available through the Android Market.

Wednesday, October 22, 2008

Android / T-Mobile G1

I have been using the new T-Mobile G1 as my primary phone for a while now. It is the first phone which runs the open-source Android mobile software stack. I agree with most of the reviewers that the G1 or even the Android software is no iPhone when it comes to stylish elegance, attention to detail and consistency in the user experience. However, this is somewhat besides the point. Android is a developers dream - designed from the ground up as a 3rd party application delivery platform. I have also played around with the application development toolkit and written 2 small Android applications - which even for somebody without any prior experience in Java or mobile device programming is surprisingly easy.

The main criticism for the G1 hardware is that it seems to have been designed by former soviet industrial planers - I can't quite figure out if it is meant to be retro Brezhnev or Khrushchev era styling... I would also prefer a 100% touch-screen driven device instead of the neither fish nor fowl physical design compromise which a sliding phone requires. On the other hand, lot's of people seem to think the keyboard is a great advantage over the iPhone and since the G1 has all the imaginable hardware features (3G, WiFi, bluetooth, camera, touch-screen, keyboard, GPS, accelerometer, compass, etc.) I makes for a great eval and development platform for the Android software before it is ported and released on hardware which maybe will make some more radical design choices - e.g. an iPhone class 100% touch-screen only phone (HTC Touch HD anybody...) or a BlackBerry/Nokia style high quality fixed keyboard body without touch-screen. The G1 feels solid and can't really be faulted for anything other than being somewhat unrefined and uninspired - at least next to an iPhone.

The software stack is surprisingly stable and mature for a product which is barely out of the door. The tight integration with Google gmail, calendar, contacts and IM is nice for people who mostly use it. In the beginning the sync for contacts and calendar acted up a few times and got stuck, but since the server side is the master copy anyway, it is easy to get unstuck again by simply erasing the data for the application in question.

In general the current release of Android lacks monitoring and management. It's all nice when things work, but when something is funny there is very little even a power user can look at - short of connecting the USB port and using the development bridge (adb shell...). Since Android gives developers far reaching powers - including running in the background or continuously as a service - the user is often at the mercy of the application developer being reasonable - specially when it comes to being power efficient - which is probably one of the most critical things on a mobile device. There is very little the user can currently do to even see what the apps are doing and override their behavior once they are installed - other than uninstalling them again, if the user can figure out which app might be causing the problem.

Many apps have been developed purely on the emulator and the hope is that once the developers themselves have real hardware in their hands and see how their app kills the battery in 3h they will maybe figure out that polling the GPS for current position every 3s is maybe not such a smart idea - even though location aware application seemed like such a cool idea in concept. Half the apps currently in the Android Market are somehow location based - and the GPS on the G1 is one of the worst battery killer...

The G1 is certainly a great starting point to make Android real and I can only imagine what potential it has for development and research in mobile systems and applications. Personally, I am still hoping for a slicker more elegant device - with only a large high-quality touch screen and no moving parts.

Tuesday, March 11, 2008

Poor-Man's Time-Machine

Since my previous experiments with Apple's Time-Machine online backup solution had not turned out as expected, but I really like the idea of continuous online backup - specially since the new 10.5 Leopard release does not seem as stable any more as my old 10.2 Panther release.

The basic idea is to use rsync, which is an efficient and robust way to synchronize two file-system trees over the network. This article for example explains in much detail, how to use rsync and unix-file system hard-links to create multiple snapshots of a filesystem tree over time and only consume disk-space for the files which have change in the meantime. Minus the fancy GUI, sounds a lot like what Time-Machine is trying to do...

For my purpose a few monthly snapshots are more than good enough with the current one being kept reasonably well in sync - daily at least, as long as the laptop happens to be online long enough for the changes to be pushed over. Since the network is private, I am using a native rsync server directly instead of running over ssh, which should hopefully increase speed and reduce CPU consumption of the background backup task.

On the linux server, rotating the monthly snapshots from the current tree (using cp with hard-link option...) is as simple as adding the following script into the monthly cron queue:

/etc/cron.monthly/rotate-snapsots.sh:

/etc/cron.monthly/rotate-snapsots.sh:

#/bin/sh

cd /home/backup/powerbook
rm -rf snapshot.3
mv snapshot.2 snapshot.3
mv snapshot.1 snapshot.2
cp -al current snapshot.1


On the Mac side, the backup should only be triggered, if the laptop is connected to the home network. Unfortunately, there does not seem to be an easy way to trigger an action whenever the wireless interface connects to a network, we'll have to run a periodic job to check for it. Since the linux server advertises itself through bonjour, this could be done by detecting its presence - e.g. ping its local name - "tinylinux.local". Since this name is not very imaginative and somebody at work or on any wi-fi network I might connect could have a host with the same name, I use a check for the name of the wireless network instead to trigger the rsync backup:

#!/bin/bash

netname=<my>

sleep 30 # make sure wifi network is up and configured

# check if we are in home network
system_profiler SPAirPortDataType | grep $netname &amp;> /dev/null
if [ $? != 0 ]
then
exit 0
fi

echo "starting backup"
/sw/bin/rsync -vaHKL --numeric-ids --delete --progress \
--exclude="*/Cache/" --exclude="*/.Trash" --exclude=".Spotlight-*/" \
--exclude="*/Caches/" --exclude=".Trashes" --exclude="*.trindex" --exclude=".fseventsd" \
/Users/<my>/ tinylinux.local::backup &amp;> /tmp/backup.log


Launchd seems to be the recommended way to run periodic and background tasks on Mac Os now, so here is a user specific launchd config for the backup service, to run the above rsync-backup.sh script every 1800s (30min):

~/Library/LaunchAgens/rsync-backup.plist:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-
1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>rsync-backup</string>
<key>Program</key>
<string>/Users/<my>/backup/rsync-backup.sh</string>
<key>StartInterval</key>
<integer>1800</integer>
</dict>
</plist>


It seems the StartInterval does unfortunately not take into account hibernation time, otherwise the job would start up most likely right away whenever the laptop is unsuspended after sleeping for more than 30min.

Even if rsync is interrupted in the middle of a synchronization, it is smart enough to pick up right away when started the next time. As long as the laptop is online for at least somewhat more than 30min on the home network, any changes made since the last time, should be synchronized properly to the current snapshot on the linux server.

Playing with Time-Machine

The latest version of Mac Os comes with automated backup system called time machine, which besides the cool GUI is basically taking periodic snapshots of all changes and saves them to an attached disk. Since my new 17' Powerbook is suspended most of the time and moving back and forth between home and office, any solution which assumes a static environment is going to be challenging.

I was hoping for a solution which would automatically back up any changes incrementally to my linux server at home, whenever the laptop finds itself on that network. This means, the system would have to auto discover its network environment and deal with interruptions, since I am not going to wait for any invisible backup job to complete before closing the laptop again.

Following these instructions , I created an AFP share from my linux server, including a bonjour zero-conf advertisement, which can easily be discovered in the network neighborhood and mounted as a share on the mac. Despite Apple's stated commitment for zero-conf plug-and-play wireless networking, there does not seem to be a way for a share to be automatically re-mounted whenever it becomes in reach. Funny enough, this seems to work only for AFP shares exported from Apple's own new Airport extreme base-stations, which can double as a network share based on an USB attached or built-in hard-disk. Unfortunately, nobody seems to have reverse engineered yet how that is done to replicate it on linux... Another interesting quirk by Apple is that Time-Machine does not work with any AFP shares other than those base-stations anyway - something which can be circumvented pretty easily.

So far, I can at least activate time machine on that network share to play with it, but given that it will time out when disconnected and not re-connect when back in range takes out most of the fun. In addition, Time-Machine seems to want to complete writing one of its snapshots and doesn't' re-try incrementally, which means it may never finish a single one if my laptop never stays online long enough. In addition, Time-Machine seems to have a tendency to fill out any available disk-space which is quite nasty on any shared disk unless it is given a dedicated disk.

All in all, I don't seem to be able to get Time-machine to do what I want - except maybe by spending another $300 for Apple's new Time-Capsule base-station with file-server, which might get closer to a usable solutions for mobile host like my laptop. On the other hand Time-Machine seems very rigid and not very thought out yet, but I like the basic concept so maybe it is time to build something myself...