/*
* This file is part of GPSLogger for Android.
*
* GPSLogger for Android is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* GPSLogger for Android is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GPSLogger for Android. If not, see <http://www.gnu.org/licenses/>.
*/
package com.mendhak.gpslogger.loggers;
import android.location.Location;
import com.mendhak.gpslogger.common.RejectionHandler;
import com.mendhak.gpslogger.common.Utilities;
import java.io.*;
import java.util.Date;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class Kml22FileLogger implements ILogger
{
protected final static Object lock = new Object();
private final static ThreadPoolExecutor EXECUTOR = new ThreadPoolExecutor(1, 1, 60, TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>(128), new RejectionHandler());
private final boolean useSatelliteTime;
private final boolean addNewTrackSegment;
private final File kmlFile;
protected final String name = "KML";
public Kml22FileLogger(File kmlFile, boolean useSatelliteTime, boolean addNewTrackSegment)
{
this.useSatelliteTime = useSatelliteTime;
this.kmlFile = kmlFile;
this.addNewTrackSegment = addNewTrackSegment;
}
public void write(Location loc) throws Exception
{
Kml22WriteHandler writeHandler = new Kml22WriteHandler(useSatelliteTime, loc, kmlFile, addNewTrackSegment);
EXECUTOR.execute(writeHandler);
}
public void annotate(String description, Location loc) throws Exception
{
Kml22AnnotateHandler annotateHandler = new Kml22AnnotateHandler(kmlFile, description, loc);
EXECUTOR.execute(annotateHandler);
}
// @Override
public String getName()
{
return name;
}
public void annotate(String name, String description, Location loc)
throws Exception {
// TODO Auto-generated method stub
}
}
class Kml22AnnotateHandler implements Runnable
{
File kmlFile;
String description;
Location loc;
public Kml22AnnotateHandler(File kmlFile, String description, Location loc)
{
this.kmlFile = kmlFile;
this.description = description;
this.loc = loc;
}
// @Override
public void run()
{
if (!kmlFile.exists())
{
return;
}
try
{
synchronized (Kml22FileLogger.lock)
{
StringBuilder descriptionNode = new StringBuilder();
descriptionNode.append("<Placemark><name>");
descriptionNode.append(description);
descriptionNode.append("</name><Point><coordinates>");
descriptionNode.append(String.valueOf(loc.getLongitude()));
descriptionNode.append(",");
descriptionNode.append(String.valueOf(loc.getLatitude()));
descriptionNode.append(",");
descriptionNode.append(String.valueOf(loc.getAltitude()));
descriptionNode.append("</coordinates></Point></Placemark>\n");
BufferedReader bf = new BufferedReader(new FileReader(kmlFile));
StringBuilder restOfFile = new StringBuilder();
String currentLine;
int lineNumber = 1;
while ((currentLine = bf.readLine()) != null)
{
if (lineNumber > 1)
{
restOfFile.append(currentLine);
restOfFile.append("\n");
}
lineNumber++;
}
bf.close();
RandomAccessFile raf = new RandomAccessFile(kmlFile, "rw");
raf.seek(255);
raf.write(descriptionNode.toString().getBytes());
raf.write(restOfFile.toString().getBytes());
raf.close();
}
}
catch (Exception e)
{
Utilities.LogError("Kml22FileLogger.Annotate", e);
}
}
}
class Kml22WriteHandler implements Runnable
{
boolean useSatelliteTime;
boolean addNewTrackSegment;
File kmlFile;
Location loc;
public Kml22WriteHandler(boolean useSatelliteTime, Location loc, File kmlFile, boolean addNewTrackSegment)
{
this.useSatelliteTime = useSatelliteTime;
this.loc = loc;
this.kmlFile = kmlFile;
this.addNewTrackSegment = addNewTrackSegment;
}
// @Override
public void run()
{
try
{
RandomAccessFile raf;
Date now;
if (useSatelliteTime)
{
now = new Date(loc.getTime());
}
else
{
now = new Date();
}
String dateTimeString = Utilities.GetIsoDateTime(now);
String placemarkHead = "<Placemark>\n<gx:Track>\n";
String placemarkTail = "</gx:Track>\n</Placemark></Document></kml>\n";
synchronized (Kml22FileLogger.lock)
{
if (!kmlFile.exists())
{
kmlFile.createNewFile();
FileOutputStream initialWriter = new FileOutputStream(kmlFile, true);
BufferedOutputStream initialOutput = new BufferedOutputStream(initialWriter);
StringBuilder initialXml = new StringBuilder();
initialXml.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
initialXml.append("<kml xmlns=\"http://www.opengis.net/kml/2.2\" ");
initialXml.append("xmlns:gx=\"http://www.google.com/kml/ext/2.2\" ");
initialXml.append("xmlns:kml=\"http://www.opengis.net/kml/2.2\" ");
initialXml.append("xmlns:atom=\"http://www.w3.org/2005/Atom\">");
initialXml.append("<Document>");
initialXml.append("<name>").append(dateTimeString).append("</name>\n");
initialXml.append("</Document></kml>\n");
initialOutput.write(initialXml.toString().getBytes());
initialOutput.flush();
initialOutput.close();
//New file, so new track segment
addNewTrackSegment = true;
}
if (addNewTrackSegment)
{
raf = new RandomAccessFile(kmlFile, "rw");
raf.seek(kmlFile.length() - 18);
raf.write((placemarkHead + placemarkTail).getBytes());
raf.close();
}
StringBuilder coords = new StringBuilder();
coords.append("\n<when>");
coords.append(dateTimeString);
coords.append("</when>\n<gx:coord>");
coords.append(String.valueOf(loc.getLongitude()));
coords.append(" ");
coords.append(String.valueOf(loc.getLatitude()));
coords.append(" ");
coords.append(String.valueOf(loc.getAltitude()));
coords.append("</gx:coord>\n");
coords.append(placemarkTail);
raf = new RandomAccessFile(kmlFile, "rw");
raf.seek(kmlFile.length() - 42);
raf.write(coords.toString().getBytes());
raf.close();
Utilities.LogDebug("Finished writing to KML22 File");
}
}
catch (Exception e)
{
Utilities.LogError("Kml22FileLogger.Write", e);
}
}
}