Converting 'My Tracks' KML files for DDMS

KML files store geographical information about paths. They can be generated with applications such as Android's My Tracks application, and in theory we should be able to load them into the emulator, using the DDMS Eclipse Plug-in, to debug and test applications which depend on the user's location without having to be actually out in the street...

... but I sadly discovered that the files generated with My Tracks do not work :-(

Looking for answers, I found an online application that supposedly converts the files into something that DDMS would accept, but apart from the fact that it didn't work at all, it also required me to log in with my Google Account in order to use it (why?)

So I decided to write my own converter, in Javascript, and put it online, so that you don't have to lose time as I did. It's here. It's free, it's fast, it won't pester you asking you to log in, and most specially, it works.

For the curious in you

Since reading the KML specification is about the most tedious thing I've ever done on a Friday afternoon, I ended up writing a working KML file by the classical method of deduction, trial and error. After all, they are simply XML files.

Also, it seems the DDMS plug-in only expects a series of Placemarks, and will list them once loaded, one by line, with the Longitude, Latitude, Elevation and Description columns--you can then select distinct locations in DDMS, and they are sent to the emulator via geo commands (I presume that this is a nice way of abstracting the telnet connection underneath). Having them listed is a way to debug and make sure you're getting the proper data into DDMS :-D

The structure of a working KML file is as follows:


<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://earth.google.com/kml/2.x">
    <Placemark>
        <name>1</name>
        <description></description>
        <Point>
            <coordinates>-122.08220,37.42228,0</coordinates>
        </Point>
    </Placemark>
    <Placemark>
        <name>2</name>
        <description></description>
        <Point>
            <coordinates>-122.083,37.4222851,0</coordinates>
        </Point>
    </Placemark>
    <!-- More placemarks ... -->
</kml>

KML files generated by My Tracks have an insane amount of extraneous data and I won't even bother to post them! Just trust me :-)

My script takes a very naive approach: when you paste the malformed KML into the textarea and press Convert, it will create and load an XML document with the data from the textarea, and then look for <coordinates> nodes using the good old getElementsByTagName node method. Therefore, it's possible to get duplicated values (for example, the start and end markers are reported as separate placemarkers, although their coordinates are already included in the main path).

There's something extra to consider: all the values must specify an elevation value. Otherwise, DDMS will not load the KML file. So when parsing the coordinates I'm splitting their values and making sure that they have three values; otherwise I add an extra default '0' for elevation.

One last thing. It's been quite fun to do this with Javascript, but I'm quite surprised that it took me more time to find out how to create an XML document from a String, than actually writing the script! Finding about this line:


var xml = (new DOMParser()).parseFromString(xml_text, "application/xml");

has taken me ages and dozens of tabs!

I would have expected that handling XML with Javascript would have been a solved problem by now, but it seems otherwise. There was a lot of people talking about AJAX and XMLHttpRequest (no wonder! XML was the X in AJAX), others solving everything with a use JSON! and some other people suggesting a certain XML() constructor which never worked, IE proprietary methods or even E4X which isn't implemented in Chrome/Webkit. And it was so simple in fact! But so counter-intuitive...

Anyway, there it is. Don't forget about it, kids: new DOMParser() is the answer :P

PS Oh I also used the new HTML5 placeholder attribute in the textareas. It doesn't work on Firefox 3.6 but it does on Chrome, so it's cool anyway.