gt: 			return new KmlTrack(source);
context: package org.osmdroid.bonuspack.kml;
  
  import android.content.Context;
  import android.os.Parcel;
  import com.google.gson.JsonObject;
  import org.osmdroid.bonuspack.kml.KmlFeature.Styler;
  import org.osmdroid.bonuspack.utils.BonusPackHelper;
  import org.osmdroid.util.BoundingBox;
  import org.osmdroid.util.GeoPoint;
  import org.osmdroid.views.MapView;
  import org.osmdroid.views.overlay.Overlay;
  import org.osmdroid.views.overlay.Polyline;
  import org.osmdroid.views.overlay.infowindow.BasicInfoWindow;
  import java.io.IOException;
  import java.io.Writer;
  import java.text.ParseException;
  import java.text.SimpleDateFormat;
  import java.util.ArrayList;
  import java.util.Date;
  
  /**
   * KML gx:Track
   * @author M.Kergall
   */
  public class KmlTrack extends KmlGeometry {
  	static int mDefaultLayoutResId = BonusPackHelper.UNDEFINED_RES_ID;
  
  	public ArrayList<Date> mWhen;
  	//public ArrayList<GeoPoint> mAngles; //TODO later...
  
  	public KmlTrack(){
  		super();
  		mCoordinates = new ArrayList<>();
  		mWhen = new ArrayList<>();
  	}
  
  	/**
  	 * @param sGxCoord gx:Coord, string with "lon lat alt", comma-separated.
  	 * @return coord as a GeoPoint, or null if the element is empty or if parsing issue.
       */
  	public static GeoPoint parseKmlGxCoord(String sGxCoord) {
  		int end1 = sGxCoord.indexOf(' ');
  		int end2 = sGxCoord.indexOf(' ', end1+1);
  		try {
  			double lon = Double.parseDouble(sGxCoord.substring(0, end1));
  			double lat = Double.parseDouble(sGxCoord.substring(end1+1, end2));
  			double alt = Double.parseDouble(sGxCoord.substring(end2+1, sGxCoord.length()));
  			return new GeoPoint(lat, lon, alt);
  		} catch (NumberFormatException e) {
  			return null;
  		} catch (IndexOutOfBoundsException e) {
  			return null;
  		}
  	}
  
  	public void addGxCoord(String sGxCoord){
  		mCoordinates.add(parseKmlGxCoord(sGxCoord));
  	}
  
  	/**
  	 * @param sWhen "when" string, in one of the KML dateTime formats. Local time format not supported yet.
  	 * @return java Date if success, or null
       */
  	public static Date parseKmlWhen(String sWhen) {
  		SimpleDateFormat ft;
  		switch (sWhen.length()) {
  			case 4: ft = new SimpleDateFormat("yyyy"); break;
  			case 7:
  				ft = new SimpleDateFormat("yyyy-MM");
  				break;
  			case 10:
  				ft = new SimpleDateFormat("yyyy-MM-dd");
  				break;
  			case 19:
  				ft = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
  				break;
  			case 20:
  				ft = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
  				break;
  			default:
  				return null;
  		}
  		Date when;
  		try {
  			when = ft.parse(sWhen);
  			return when;
  		} catch (ParseException e) {
  			return null;
  		}
  	}
  
  	public void addWhen(String sWhen){
  		if (mWhen == null)
  			mWhen = new ArrayList<>();
  		mWhen.add(parseKmlWhen(sWhen));
  	}
  
  	/**
  	 * Add a time element (coord+when) to the track.
  	 *
  	 * @param coord
  	 * @param when
  	 */
  	public void add(GeoPoint coord, Date when) {
  		if (coord == null)
  			mCoordinates.add(coord);
  		else
  			mCoordinates.add(coord.clone());
  		mWhen.add(when);
  	}
  
  	public void applyDefaultStyling(Polyline lineStringOverlay, Style defaultStyle, KmlPlacemark kmlPlacemark,
  			KmlDocument kmlDocument, MapView map){
  		Context context = map.getContext();
  		Style style = kmlDocument.getStyle(kmlPlacemark.mStyle);
  		if (style != null){
  			lineStringOverlay.setColor(style.getOutlinePaint().getColor());
  			lineStringOverlay.setWidth(style.getOutlinePaint().getStrokeWidth());
  		} else if (defaultStyle!=null && defaultStyle.mLineStyle!=null){
  			lineStringOverlay.setColor(defaultStyle.getOutlinePaint().getColor());
  			lineStringOverlay.setWidth(defaultStyle.getOutlinePaint().getStrokeWidth());
  		}
  		if ((kmlPlacemark.mName!=null && !"".equals(kmlPlacemark.mName))
  				|| (kmlPlacemark.mDescription!=null && !"".equals(kmlPlacemark.mDescription))
  				|| (lineStringOverlay.getSubDescription()!=null && !"".equals(lineStringOverlay.getSubDescription()))
  				){
  			if (mDefaultLayoutResId == BonusPackHelper.UNDEFINED_RES_ID){
  				String packageName = context.getPackageName();
  				mDefaultLayoutResId = context.getResources().getIdentifier("layout/bonuspack_bubble", null, packageName);
  			}
  			lineStringOverlay.setInfoWindow(new BasicInfoWindow(mDefaultLayoutResId, map));
  		}
  		lineStringOverlay.setEnabled(kmlPlacemark.mVisibility);
  	}
  
  	/** Build the corresponding overlay.
  	 * Currently: a Polyline of gx:coords */
  	@Override public Overlay buildOverlay(MapView map, Style defaultStyle, Styler styler, KmlPlacemark kmlPlacemark,
  			KmlDocument kmlDocument){
  		Polyline lineStringOverlay = new Polyline();
  		lineStringOverlay.setGeodesic(true);
  		lineStringOverlay.setPoints(mCoordinates);
  		lineStringOverlay.setTitle(kmlPlacemark.mName);
  		lineStringOverlay.setSnippet(kmlPlacemark.mDescription);
  		lineStringOverlay.setSubDescription(kmlPlacemark.getExtendedDataAsText());
  		if (styler != null)
  			styler.onTrack(lineStringOverlay, kmlPlacemark, this);
  		else {
  			applyDefaultStyling(lineStringOverlay, defaultStyle, kmlPlacemark, kmlDocument, map);
  		}
  		return lineStringOverlay;
  	}
  
  	static final SimpleDateFormat KML_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
  
  	@Override public void saveAsKML(Writer writer){
  		try {
  			writer.write("<gx:Track>\n");
  			//write when:
  			for (Date when:mWhen){
  				writer.write("<when>");
  				if (when != null)
  					writer.write(KML_DATE_FORMAT.format(when));
  				writer.write("</when>\n");
  			}
  			//write coords:
  			for (GeoPoint coord:mCoordinates){
  				writer.write("<gx:coord>");
  				if (coord != null)
  					writer.write(coord.getLongitude() + " " + coord.getLatitude() + " " + coord.getAltitude());
  				writer.write("</gx:coord>\n");
  			}
  			writer.write("</gx:Track>\n");
  		} catch (IOException e) {
  			e.printStackTrace();
  		}
  	}
  
  	@Override public JsonObject asGeoJSON(){
  		JsonObject json = new JsonObject();
  		json.addProperty("type", "LineString");
  		json.add("coordinates", KmlGeometry.geoJSONCoordinates(mCoordinates));
  		return json;
  	}
  
  	@Override public BoundingBox getBoundingBox() {
  		return BoundingBox.fromGeoPoints(mCoordinates);
  	}
  
  	//Cloneable implementation ------------------------------------
  
  	@Override public KmlTrack clone(){
  		KmlTrack cloned = (KmlTrack) super.clone();
  		cloned.mWhen = new ArrayList<>(mWhen.size());
  		for (Date d : mWhen)
  			cloned.mWhen.add((Date) d.clone());
  		return cloned;
  	}
  
  	//Parcelable implementation ------------
  
  	@Override public int describeContents() {
  		return 0;
  	}
  
  	@Override public void writeToParcel(Parcel out, int flags) {
  		super.writeToParcel(out, flags);
  		out.writeList(mWhen);
  	}
  
  	public static final Creator<KmlTrack> CREATOR = new Creator<KmlTrack>() {
  		@Override public KmlTrack createFromParcel(Parcel source) {
  