Search code examples
kmlgoogle-earthjak

How to properly update Google Earth KML using NetworkLinkControl and the Java API for KML (JAK)?


I'm building an application that serves up data to a standalone Google Earth client. I want to send over an initial set of data, then update it dynamically using <NetworkLinkControl> and <Update><cookie> tags as things change on the server. I'm generating the KML using the Java API for KML (JAK) library. Unfortunately, while I can confirm that GE is refreshing my NetworkLink and pulling down the Updates I'm sending, none of my updates are showing up in GE. After lots of reading, it seems like it might be that the Update's <targetHref> might be the issue, but I'm 99.9% sure I'm sending over the same string.

Part of what has me confused is that I've seen conflicting info on whether or not the <cookie> element's value needs to be appended to <targetHref>. I did actually see one early prototype updating when I was serving up hand-written test KML files from a static server URL, so I suspect it's not. Actually, that's what's frustrating at the moment: I've seen updating work on my own machine, but can't get it working now with what looks like valid and correct KML.

The current setup looks like this (extraneous XML namespaces stripped for clarity; "$CLIENT_ID" is a GUID-like string):

Root KML file served from http://server/kml/${CLIENT_ID}:

<kml  xmlns="http://www.opengis.net/kml/2.2" 
      xmlns:gx="http://www.google.com/kml/ext/2.2" 
      xmlns:atom="http://www.w3.org/2005/Atom"     
      xmlns:xal="urn:oasis:names:tc:ciq:xsdschema:xAL:2.0"><NetworkLink>
  <Link>
    <href>http://server/kmlupdates/${CLIENT_ID}</href>
    <refreshMode>onInterval</refreshMode>
    <refreshInterval>1.0</refreshInterval>
    <viewRefreshTime>0.0</viewRefreshTime>
    <viewBoundScale>0.0</viewBoundScale>
  </Link>
</NetworkLink></kml>

Initial content KML served from http://server/kmlupdates/${CLIENT_ID}:

<kml><NetworkLinkControl>
    <minRefreshPeriod>0.0</minRefreshPeriod>
    <maxSessionLength>-1.0</maxSessionLength>
    <cookie>cookie=0|kmlRequestType=updates|projectID=6|lastUpdateSeenIndex=-1</cookie>
  </NetworkLinkControl>
  <Document id="myProject">
    <name>My ProjectProject</name>
    <Placemark id="pm1"><name>point1</name>
        <Point><coordinates>-117.0,35.0</coordinates></Point>
    </Placemark>
</Document></kml>

Later update KML served from http://server/kmlupdates/${CLIENT_ID}:

<kml><NetworkLinkControl>
    <minRefreshPeriod>0.0</minRefreshPeriod>
    <maxSessionLength>-1.0</maxSessionLength>
    <cookie>cookie=0|kmlRequestType=updates|projectID=6|lastUpdateSeenIndex=0</cookie>
    <Update>
        <targetHref>http://server/kmlupdates/${CLIENT_ID}</targetHref>
        <Change>
            <Placemark targetId="pm1">
                <name>Name changed by Update Change</name>
            </Placemark>
        </Change>
    </Update>
</NetworkLinkControl></kml>

If anyone has any suggestions on what I'm missing here, I'd greatly appreciate it. Thanks!


Solution

  • My original version of the question left out two facts that turned out to be relevant: 1) I'm using the Java API for KML to generate this, and 2) the XML namespaces inside <kml>. I finally figured this out after reading this Google KML Group post for the umpteenth time.

    The problem is the last XML namespace, "xmlns:xal". For some reason, removing that from the KML allows the <Update> tags to actually change the items in Google Earth. JAK doesn't let you change the namespaces, but you can strip it manually from the marshaled string.

    Absolutely bizarre, but at least I found a solution.