From adc910837bf7a870779d950436b5a7b406d12c7b Mon Sep 17 00:00:00 2001 From: Bartek Fabiszewski Date: Sat, 24 Jun 2017 18:00:28 +0200 Subject: [PATCH] Extend GPX export with custom data --- .../net/fabiszewski/ulogger/DbAccess.java | 142 ++++++++++++++++++ .../fabiszewski/ulogger/GpxExportService.java | 59 ++++++-- .../fabiszewski/ulogger/WebSyncService.java | 24 +-- 3 files changed, 199 insertions(+), 26 deletions(-) diff --git a/app/src/main/java/net/fabiszewski/ulogger/DbAccess.java b/app/src/main/java/net/fabiszewski/ulogger/DbAccess.java index 1d29ffb..859e192 100644 --- a/app/src/main/java/net/fabiszewski/ulogger/DbAccess.java +++ b/app/src/main/java/net/fabiszewski/ulogger/DbAccess.java @@ -17,6 +17,11 @@ import android.location.Location; import android.util.Log; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Locale; +import java.util.TimeZone; + /** * Gateway class for database access * @@ -381,4 +386,141 @@ void close() { } } + /** + * Get accuracy from positions cursor + * @param cursor Cursor + * @return String accuracy + */ + static String getAccuracy(Cursor cursor) { + return cursor.getString(cursor.getColumnIndex(DbContract.Positions.COLUMN_ACCURACY)); + } + + /** + * Check if cursor contains accuracy data + * @param cursor Cursor + * @return True if has accuracy data + */ + static boolean hasAccuracy(Cursor cursor) { + return !cursor.isNull(cursor.getColumnIndex(DbContract.Positions.COLUMN_ACCURACY)); + } + + /** + * Get speed from positions cursor + * @param cursor Cursor + * @return String speed + */ + static String getSpeed(Cursor cursor) { + return cursor.getString(cursor.getColumnIndex(DbContract.Positions.COLUMN_SPEED)); + } + + /** + * Check if cursor contains speed data + * @param cursor Cursor + * @return True if has speed data + */ + static boolean hasSpeed(Cursor cursor) { + return !cursor.isNull(cursor.getColumnIndex(DbContract.Positions.COLUMN_SPEED)); + } + + /** + * Get bearing from positions cursor + * @param cursor Cursor + * @return String bearing + */ + static String getBearing(Cursor cursor) { + return cursor.getString(cursor.getColumnIndex(DbContract.Positions.COLUMN_BEARING)); + } + + /** + * Check if cursor contains bearing data + * @param cursor Cursor + * @return True if has bearing data + */ + static boolean hasBearing(Cursor cursor) { + return !cursor.isNull(cursor.getColumnIndex(DbContract.Positions.COLUMN_BEARING)); + } + + /** + * Get altitude from positions cursor + * @param cursor Cursor + * @return String altitude + */ + static String getAltitude(Cursor cursor) { + return cursor.getString(cursor.getColumnIndex(DbContract.Positions.COLUMN_ALTITUDE)); + } + + /** + * Check if cursor contains altitude data + * @param cursor Cursor + * @return True if has altitude data + */ + static boolean hasAltitude(Cursor cursor) { + return !cursor.isNull(cursor.getColumnIndex(DbContract.Positions.COLUMN_ALTITUDE)); + } + + /** + * Get provider from positions cursor + * @param cursor Cursor + * @return String provider + */ + static String getProvider(Cursor cursor) { + return cursor.getString(cursor.getColumnIndex(DbContract.Positions.COLUMN_PROVIDER)); + } + + /** + * Get latitude from positions cursor + * @param cursor Cursor + * @return String latitude + */ + static String getLatitude(Cursor cursor) { + return cursor.getString(cursor.getColumnIndex(DbContract.Positions.COLUMN_LATITUDE)); + } + + /** + * Get longitude from positions cursor + * @param cursor Cursor + * @return String longitude + */ + static String getLongitude(Cursor cursor) { + return cursor.getString(cursor.getColumnIndex(DbContract.Positions.COLUMN_LONGITUDE)); + } + + /** + * Get time from positions cursor + * @param cursor Cursor + * @return String time + */ + static String getTime(Cursor cursor) { + return cursor.getString(cursor.getColumnIndex(DbContract.Positions.COLUMN_TIME)); + } + + /** + * Get ISO 8601 formatted time from positions cursor + * @param cursor Cursor + * @return String time + */ + static String getTimeISO8601(Cursor cursor) { + long timestamp = cursor.getLong(cursor.getColumnIndex(DbContract.Positions.COLUMN_TIME)); + return getTimeISO8601(timestamp); + } + + /** + * Get ID from positions cursor + * @param cursor Cursor + * @return String ID + */ + static String getID(Cursor cursor) { + return cursor.getString(cursor.getColumnIndex(DbContract.Positions._ID)); + } + + /** + * Format unix timestamp as ISO 8601 time + * @param timestamp Timestamp + * @return Formatted time + */ + static String getTimeISO8601(long timestamp) { + DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US); + df.setTimeZone(TimeZone.getTimeZone("UTC")); + return df.format(timestamp * 1000); + } } diff --git a/app/src/main/java/net/fabiszewski/ulogger/GpxExportService.java b/app/src/main/java/net/fabiszewski/ulogger/GpxExportService.java index 4ec7d65..73eefd0 100644 --- a/app/src/main/java/net/fabiszewski/ulogger/GpxExportService.java +++ b/app/src/main/java/net/fabiszewski/ulogger/GpxExportService.java @@ -17,7 +17,6 @@ import android.os.Environment; import android.support.annotation.NonNull; import android.support.v4.app.ActivityCompat; -import android.text.format.DateFormat; import android.util.Log; import android.util.Xml; @@ -40,8 +39,10 @@ public class GpxExportService extends IntentService { public static final String BROADCAST_EXPORT_DONE = "net.fabiszewski.ulogger.broadcast.write_ok"; private static final String ns_gpx = "http://www.topografix.com/GPX/1/1"; + private static final String ns_ulogger = "https://github.com/bfabiszewski/ulogger-android/1"; private static final String ns_xsi = "http://www.w3.org/2001/XMLSchema-instance"; - private static final String schemaLocation = ns_gpx + " http://www.topografix.com/GPX/1/1/gpx.xsd"; + private static final String schemaLocation = ns_gpx + " http://www.topografix.com/GPX/1/1/gpx.xsd " + + ns_ulogger + " https://raw.githubusercontent.com/bfabiszewski/ulogger-server/master/scripts/gpx_extensions1.xsd"; private static final String ULOGGER_DIR = "ulogger_tracks"; private static final String GPX_EXTENSION = ".gpx"; @@ -123,6 +124,7 @@ protected void onHandleIntent(Intent intent) { serializer.startDocument("UTF-8", true); serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true); serializer.setPrefix("xsi", ns_xsi); + serializer.setPrefix("ulogger", ns_ulogger); serializer.startTag("", "gpx"); serializer.attribute(null, "xmlns", ns_gpx); serializer.attribute(ns_xsi, "schemaLocation", schemaLocation); @@ -132,7 +134,7 @@ protected void onHandleIntent(Intent intent) { // metadata long trackTimestamp = db.getFirstTimestamp(); - String trackTime = DateFormat.format("yyyy-MM-ddThh:mm:ss", trackTimestamp * 1000).toString(); + String trackTime = DbAccess.getTimeISO8601(trackTimestamp); serializer.startTag(null, "metadata"); writeTag(serializer, "name", trackName); writeTag(serializer, "time", trackTime); @@ -189,15 +191,28 @@ private void writePositions(@NonNull XmlSerializer serializer) serializer.startTag(null, "trkseg"); while (cursor.moveToNext()) { serializer.startTag(null, "trkpt"); - serializer.attribute(null, "lat", cursor.getString(cursor.getColumnIndex(DbContract.Positions.COLUMN_LATITUDE))); - serializer.attribute(null, "lon", cursor.getString(cursor.getColumnIndex(DbContract.Positions.COLUMN_LONGITUDE))); - if (!cursor.isNull(cursor.getColumnIndex(DbContract.Positions.COLUMN_ALTITUDE))) { - writeTag(serializer, "ele", cursor.getString(cursor.getColumnIndex(DbContract.Positions.COLUMN_ALTITUDE))); + serializer.attribute(null, "lat", DbAccess.getLatitude(cursor)); + serializer.attribute(null, "lon", DbAccess.getLongitude(cursor)); + if (DbAccess.hasAltitude(cursor)) { + writeTag(serializer, "ele", DbAccess.getAltitude(cursor)); } - long timestamp = cursor.getLong(cursor.getColumnIndex(DbContract.Positions.COLUMN_TIME)); - String time = DateFormat.format("yyyy-MM-ddThh:mm:ss", timestamp * 1000).toString(); - writeTag(serializer, "time", time); - writeTag(serializer, "name", cursor.getString(cursor.getColumnIndex(DbContract.Positions._ID))); + writeTag(serializer, "time", DbAccess.getTimeISO8601(cursor)); + writeTag(serializer, "name", DbAccess.getID(cursor)); + + // ulogger extensions (accuracy, speed, bearing, provider) + serializer.startTag(null, "extensions"); + if (DbAccess.hasAccuracy(cursor)) { + writeTag(serializer, "accuracy", DbAccess.getAccuracy(cursor), ns_ulogger); + } + if (DbAccess.hasSpeed(cursor)) { + writeTag(serializer, "speed", DbAccess.getSpeed(cursor), ns_ulogger); + } + if (DbAccess.hasBearing(cursor)) { + writeTag(serializer, "bearing", DbAccess.getBearing(cursor), ns_ulogger); + } + writeTag(serializer, "provider", DbAccess.getProvider(cursor), ns_ulogger); + serializer.endTag(null, "extensions"); + serializer.endTag(null, "trkpt"); } serializer.endTag(null, "trkseg"); @@ -207,7 +222,7 @@ private void writePositions(@NonNull XmlSerializer serializer) } /** - * Write tag + * Write tag without namespace * * @param serializer XmlSerializer * @param name Tag name @@ -218,9 +233,25 @@ private void writePositions(@NonNull XmlSerializer serializer) */ private void writeTag(@NonNull XmlSerializer serializer, @NonNull String name, @NonNull String text) throws IOException, IllegalArgumentException, IllegalStateException { - serializer.startTag(null, name); + writeTag(serializer, name, text, null); + } + + /** + * Write tag + * + * @param serializer XmlSerializer + * @param name Tag name + * @param text Tag text + * @param ns Namespace + * @throws IOException IO exception + * @throws IllegalArgumentException Xml illegal argument + * @throws IllegalStateException Xml illegal state + */ + private void writeTag(@NonNull XmlSerializer serializer, @NonNull String name, @NonNull String text, String ns) + throws IOException, IllegalArgumentException, IllegalStateException { + serializer.startTag(ns, name); serializer.text(text); - serializer.endTag(null, name); + serializer.endTag(ns, name); } /** diff --git a/app/src/main/java/net/fabiszewski/ulogger/WebSyncService.java b/app/src/main/java/net/fabiszewski/ulogger/WebSyncService.java index 77b75df..7f06d72 100644 --- a/app/src/main/java/net/fabiszewski/ulogger/WebSyncService.java +++ b/app/src/main/java/net/fabiszewski/ulogger/WebSyncService.java @@ -203,22 +203,22 @@ private void handleError(Exception e) { */ private Map cursorToMap(Cursor cursor) { Map params = new HashMap<>(); - params.put(WebHelper.PARAM_TIME, cursor.getString(cursor.getColumnIndex(DbContract.Positions.COLUMN_TIME))); - params.put(WebHelper.PARAM_LAT, cursor.getString(cursor.getColumnIndex(DbContract.Positions.COLUMN_LATITUDE))); - params.put(WebHelper.PARAM_LON, cursor.getString(cursor.getColumnIndex(DbContract.Positions.COLUMN_LONGITUDE))); - if (!cursor.isNull(cursor.getColumnIndex(DbContract.Positions.COLUMN_ALTITUDE))) { - params.put(WebHelper.PARAM_ALT, cursor.getString(cursor.getColumnIndex(DbContract.Positions.COLUMN_ALTITUDE))); + params.put(WebHelper.PARAM_TIME, DbAccess.getTime(cursor)); + params.put(WebHelper.PARAM_LAT, DbAccess.getLatitude(cursor)); + params.put(WebHelper.PARAM_LON, DbAccess.getLongitude(cursor)); + if (DbAccess.hasAltitude(cursor)) { + params.put(WebHelper.PARAM_ALT, DbAccess.getAltitude(cursor)); } - if (!cursor.isNull(cursor.getColumnIndex(DbContract.Positions.COLUMN_SPEED))) { - params.put(WebHelper.PARAM_SPEED, cursor.getString(cursor.getColumnIndex(DbContract.Positions.COLUMN_SPEED))); + if (DbAccess.hasSpeed(cursor)) { + params.put(WebHelper.PARAM_SPEED, DbAccess.getSpeed(cursor)); } - if (!cursor.isNull(cursor.getColumnIndex(DbContract.Positions.COLUMN_BEARING))) { - params.put(WebHelper.PARAM_BEARING, cursor.getString(cursor.getColumnIndex(DbContract.Positions.COLUMN_BEARING))); + if (DbAccess.hasBearing(cursor)) { + params.put(WebHelper.PARAM_BEARING, DbAccess.getBearing(cursor)); } - if (!cursor.isNull(cursor.getColumnIndex(DbContract.Positions.COLUMN_ACCURACY))) { - params.put(WebHelper.PARAM_ACCURACY, cursor.getString(cursor.getColumnIndex(DbContract.Positions.COLUMN_ACCURACY))); + if (DbAccess.hasAccuracy(cursor)) { + params.put(WebHelper.PARAM_ACCURACY, DbAccess.getAccuracy(cursor)); } - params.put(WebHelper.PARAM_PROVIDER, cursor.getString(cursor.getColumnIndex(DbContract.Positions.COLUMN_PROVIDER))); + params.put(WebHelper.PARAM_PROVIDER, DbAccess.getProvider(cursor)); return params; }