From 80cd4b4c4f7d32e44c5dc2c0e31f75d6ab7338de Mon Sep 17 00:00:00 2001 From: Alexey Kulish Date: Sun, 19 Feb 2017 12:18:07 +0300 Subject: [PATCH] Added gpx database --- .../src/net/osmand/plus/AppInitializer.java | 1 + OsmAnd/src/net/osmand/plus/GPXDatabase.java | 199 ++++++++++++------ .../net/osmand/plus/OsmandApplication.java | 5 + .../download/ui/LocalIndexesFragment.java | 16 +- .../plus/myplaces/AvailableGPXFragment.java | 88 +++++++- 5 files changed, 228 insertions(+), 81 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/AppInitializer.java b/OsmAnd/src/net/osmand/plus/AppInitializer.java index f35f1ea695..b2924f021b 100644 --- a/OsmAnd/src/net/osmand/plus/AppInitializer.java +++ b/OsmAnd/src/net/osmand/plus/AppInitializer.java @@ -360,6 +360,7 @@ public class AppInitializer implements IProgress { app.notificationHelper = startupInit(new NotificationHelper(app), NotificationHelper.class); app.liveMonitoringHelper = startupInit(new LiveMonitoringHelper(app), LiveMonitoringHelper.class); app.selectedGpxHelper = startupInit(new GpxSelectionHelper(app, app.savingTrackHelper), GpxSelectionHelper.class); + app.gpxDatabase = startupInit(new GPXDatabase(app), GPXDatabase.class); app.favorites = startupInit(new FavouritesDbHelper(app), FavouritesDbHelper.class); app.waypointHelper = startupInit(new WaypointHelper(app), WaypointHelper.class); diff --git a/OsmAnd/src/net/osmand/plus/GPXDatabase.java b/OsmAnd/src/net/osmand/plus/GPXDatabase.java index 78ece2e3f6..db54d1550a 100644 --- a/OsmAnd/src/net/osmand/plus/GPXDatabase.java +++ b/OsmAnd/src/net/osmand/plus/GPXDatabase.java @@ -2,7 +2,8 @@ package net.osmand.plus; import net.osmand.IndexConstants; import net.osmand.plus.GPXUtilities.GPXTrackAnalysis; -import net.osmand.plus.api.SQLiteAPI; +import net.osmand.plus.api.SQLiteAPI.SQLiteConnection; +import net.osmand.plus.api.SQLiteAPI.SQLiteCursor; import net.osmand.util.Algorithms; import java.io.File; @@ -59,6 +60,14 @@ public class GPXDatabase { GPX_COL_POINTS + " int, " + GPX_COL_WPT_POINTS + " int);"; + private static final String GPX_TABLE_SELECT = "SELECT " + GPX_COL_NAME + ", " + GPX_COL_DIR + "," + GPX_COL_TOTAL_DISTANCE + ", " + + GPX_COL_TOTAL_TRACKS + ", " + GPX_COL_START_TIME + ", " + GPX_COL_END_TIME + ", " + + GPX_COL_TIME_SPAN + ", " + GPX_COL_TIME_MOVING + ", " + GPX_COL_TOTAL_DISTANCE_MOVING + ", " + + GPX_COL_DIFF_ELEVATION_UP + ", " + GPX_COL_DIFF_ELEVATION_DOWN + ", " + GPX_COL_AVG_ELEVATION + ", " + + GPX_COL_MIN_ELEVATION + ", " + GPX_COL_MAX_ELEVATION + ", " + GPX_COL_MAX_SPEED + ", " + + GPX_COL_AVG_SPEED + ", " + GPX_COL_POINTS + ", " + GPX_COL_WPT_POINTS + + " FROM " + GPX_TABLE_NAME; + private OsmandApplication context; public static class GpxDataItem { @@ -83,8 +92,8 @@ public class GPXDatabase { context = app; } - private SQLiteAPI.SQLiteConnection openConnection(boolean readonly) { - SQLiteAPI.SQLiteConnection conn = context.getSQLiteAPI().getOrCreateDatabase(DB_NAME, readonly); + private SQLiteConnection openConnection(boolean readonly) { + SQLiteConnection conn = context.getSQLiteAPI().getOrCreateDatabase(DB_NAME, readonly); if (conn.getVersion() == 0 || DB_VERSION != conn.getVersion()) { if (readonly) { conn.close(); @@ -101,11 +110,11 @@ public class GPXDatabase { return conn; } - public void onCreate(SQLiteAPI.SQLiteConnection db) { + public void onCreate(SQLiteConnection db) { db.execSQL(GPX_TABLE_CREATE); } - public void onUpgrade(SQLiteAPI.SQLiteConnection db, int oldVersion, int newVersion) { + public void onUpgrade(SQLiteConnection db, int oldVersion, int newVersion) { /* if (newVersion == 2) { db.execSQL(GPX_TABLE_CREATE); @@ -114,12 +123,19 @@ public class GPXDatabase { */ } - public boolean remove(GpxDataItem item) { - SQLiteAPI.SQLiteConnection db = openConnection(false); + public boolean rename(File currentFile, File newFile) { + SQLiteConnection db = openConnection(false); if(db != null){ try { - db.execSQL("DELETE FROM " + GPX_TABLE_NAME + " WHERE " + GPX_COL_NAME + " = ?, " + GPX_COL_DIR + " = ?", - new Object[] { item.file.getName(), item.file.getParentFile().getName() }); + String newFileName = getFileName(newFile); + String newFileDir = getFileDir(newFile); + String fileName = getFileName(currentFile); + String fileDir = getFileDir(currentFile); + db.execSQL("UPDATE " + GPX_TABLE_NAME + " SET " + + GPX_COL_NAME + " = ? " + ", " + + GPX_COL_DIR + " = ? " + + " WHERE " + GPX_COL_NAME + " = ? AND " + GPX_COL_DIR + " = ?", + new Object[] { newFileName, newFileDir, fileName, fileDir }); } finally { db.close(); } @@ -128,8 +144,28 @@ public class GPXDatabase { return false; } + public boolean remove(File file) { + SQLiteConnection db = openConnection(false); + if(db != null){ + try { + String fileName = getFileName(file); + String fileDir = getFileDir(file); + db.execSQL("DELETE FROM " + GPX_TABLE_NAME + " WHERE " + GPX_COL_NAME + " = ? AND " + GPX_COL_DIR + " = ?", + new Object[] { fileName, fileDir }); + } finally { + db.close(); + } + return true; + } + return false; + } + + public boolean remove(GpxDataItem item) { + return remove(item.file); + } + public boolean add(GpxDataItem item) { - SQLiteAPI.SQLiteConnection db = openConnection(false); + SQLiteConnection db = openConnection(false); if(db != null){ try { insert(item, db); @@ -141,9 +177,18 @@ public class GPXDatabase { return false; } - private void insert(GpxDataItem item, SQLiteAPI.SQLiteConnection db) { - String fileName = item.file.getName(); - String fileDir = item.file.getParentFile().getName(); + private String getFileName(File itemFile) { + return itemFile.getName(); + } + + private String getFileDir(File itemFile) { + return itemFile.getParentFile().equals(context.getAppPath(IndexConstants.GPX_INDEX_DIR)) ? + "" : itemFile.getParentFile().getName(); + } + + private void insert(GpxDataItem item, SQLiteConnection db) { + String fileName = getFileName(item.file); + String fileDir = getFileDir(item.file); GPXTrackAnalysis a = item.getAnalysis(); db.execSQL( "INSERT INTO " + GPX_TABLE_NAME + " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", @@ -152,69 +197,63 @@ public class GPXDatabase { a.avgElevation, a.minElevation, a.maxElevation, a.maxSpeed, a.avgSpeed, a.points, a.wptPoints }); } + private GpxDataItem readItem(SQLiteCursor query) { + String fileName = query.getString(0); + String fileDir = query.getString(1); + float totalDistance = (float)query.getDouble(2); + int totalTracks = (int)query.getInt(3); + long startTime = query.getLong(4); + long endTime = query.getLong(5); + long timeSpan = query.getLong(6); + long timeMoving = query.getLong(7); + float totalDistanceMoving = (float)query.getDouble(8); + double diffElevationUp = query.getDouble(9); + double diffElevationDown = query.getDouble(10); + double avgElevation = query.getDouble(11); + double minElevation = query.getDouble(12); + double maxElevation = query.getDouble(13); + float maxSpeed = (float)query.getDouble(14); + float avgSpeed = (float)query.getDouble(15); + int points = (int)query.getInt(16); + int wptPoints = (int)query.getInt(17); + + GPXTrackAnalysis a = new GPXTrackAnalysis(); + a.totalDistance = totalDistance; + a.totalTracks = totalTracks; + a.startTime = startTime; + a.endTime = endTime; + a.timeSpan = timeSpan; + a.timeMoving = timeMoving; + a.totalDistanceMoving = totalDistanceMoving; + a.diffElevationUp = diffElevationUp; + a.diffElevationDown = diffElevationDown; + a.avgElevation = avgElevation; + a.minElevation = minElevation; + a.maxElevation = maxElevation; + a.maxSpeed = maxSpeed; + a.avgSpeed = avgSpeed; + a.points = points; + a.wptPoints = wptPoints; + + File dir; + if (!Algorithms.isEmpty(fileDir)) { + dir = new File(context.getAppPath(IndexConstants.GPX_INDEX_DIR), fileDir); + } else { + dir = context.getAppPath(IndexConstants.GPX_INDEX_DIR); + } + return new GpxDataItem(new File(dir, fileName), a); + } + public List getItems() { List items = new ArrayList<>(); - SQLiteAPI.SQLiteConnection db = openConnection(true); - if(db != null){ + SQLiteConnection db = openConnection(true); + if (db != null){ try { - SQLiteAPI.SQLiteCursor query = db.rawQuery( - "SELECT " + GPX_COL_NAME + ", " + GPX_COL_DIR + "," + GPX_COL_TOTAL_DISTANCE + ", " + - GPX_COL_TOTAL_TRACKS + ", " + GPX_COL_START_TIME + ", " + GPX_COL_END_TIME + ", " + - GPX_COL_TIME_SPAN + ", " + GPX_COL_TIME_MOVING + ", " + GPX_COL_TOTAL_DISTANCE_MOVING + ", " + - GPX_COL_DIFF_ELEVATION_UP + ", " + GPX_COL_DIFF_ELEVATION_DOWN + ", " + GPX_COL_AVG_ELEVATION + ", " + - GPX_COL_MIN_ELEVATION + ", " + GPX_COL_MAX_ELEVATION + ", " + GPX_COL_MAX_SPEED + ", " + - GPX_COL_AVG_SPEED + ", " + GPX_COL_POINTS + ", " + GPX_COL_WPT_POINTS + - " FROM " + GPX_TABLE_NAME , null); - + SQLiteCursor query = db.rawQuery(GPX_TABLE_SELECT , null); if (query.moveToFirst()) { do { - String fileName = query.getString(0); - String fileDir = query.getString(1); - float totalDistance = (float)query.getDouble(2); - int totalTracks = (int)query.getInt(3); - long startTime = query.getLong(4); - long endTime = query.getLong(5); - long timeSpan = query.getLong(6); - long timeMoving = query.getLong(7); - float totalDistanceMoving = (float)query.getDouble(8); - double diffElevationUp = query.getDouble(9); - double diffElevationDown = query.getDouble(10); - double avgElevation = query.getDouble(11); - double minElevation = query.getDouble(12); - double maxElevation = query.getDouble(13); - float maxSpeed = (float)query.getDouble(14); - float avgSpeed = (float)query.getDouble(15); - int points = (int)query.getInt(16); - int wptPoints = (int)query.getInt(17); - - GPXTrackAnalysis a = new GPXTrackAnalysis(); - a.totalDistance = totalDistance; - a.totalTracks = totalTracks; - a.startTime = startTime; - a.endTime = endTime; - a.timeSpan = timeSpan; - a.timeMoving = timeMoving; - a.totalDistanceMoving = totalDistanceMoving; - a.diffElevationUp = diffElevationUp; - a.diffElevationDown = diffElevationDown; - a.avgElevation = avgElevation; - a.minElevation = minElevation; - a.maxElevation = maxElevation; - a.maxSpeed = maxSpeed; - a.avgSpeed = avgSpeed; - a.points = points; - a.wptPoints = wptPoints; - - File dir; - if (!Algorithms.isEmpty(fileDir)) { - dir = new File(context.getAppPath(IndexConstants.GPX_INDEX_DIR), fileDir); - } else { - dir = context.getAppPath(IndexConstants.GPX_INDEX_DIR); - } - GpxDataItem item = new GpxDataItem(new File(dir, fileName), a); - items.add(item); + items.add(readItem(query)); } while (query.moveToNext()); - } query.close(); } finally { @@ -223,4 +262,24 @@ public class GPXDatabase { } return items; } + + public GpxDataItem getItem(File file) { + GpxDataItem result = null; + SQLiteConnection db = openConnection(true); + if (db != null){ + try { + String fileName = getFileName(file); + String fileDir = getFileDir(file); + SQLiteCursor query = db.rawQuery(GPX_TABLE_SELECT + " WHERE " + GPX_COL_NAME + " = ? AND " + + GPX_COL_DIR + " = ?", new String[] { fileName, fileDir }); + if (query.moveToFirst()) { + result = readItem(query); + } + query.close(); + } finally { + db.close(); + } + } + return result; + } } diff --git a/OsmAnd/src/net/osmand/plus/OsmandApplication.java b/OsmAnd/src/net/osmand/plus/OsmandApplication.java index b08a77681f..42e5c0b667 100644 --- a/OsmAnd/src/net/osmand/plus/OsmandApplication.java +++ b/OsmAnd/src/net/osmand/plus/OsmandApplication.java @@ -95,6 +95,7 @@ public class OsmandApplication extends MultiDexApplication { FavouritesDbHelper favorites; CommandPlayer player; GpxSelectionHelper selectedGpxHelper; + GPXDatabase gpxDatabase; SavingTrackHelper savingTrackHelper; NotificationHelper notificationHelper; LiveMonitoringHelper liveMonitoringHelper; @@ -272,6 +273,10 @@ public class OsmandApplication extends MultiDexApplication { return selectedGpxHelper; } + public GPXDatabase getGpxDatabase() { + return gpxDatabase; + } + public FavouritesDbHelper getFavorites() { return favorites; } diff --git a/OsmAnd/src/net/osmand/plus/download/ui/LocalIndexesFragment.java b/OsmAnd/src/net/osmand/plus/download/ui/LocalIndexesFragment.java index e759bfad4f..f1f2b9a8eb 100644 --- a/OsmAnd/src/net/osmand/plus/download/ui/LocalIndexesFragment.java +++ b/OsmAnd/src/net/osmand/plus/download/ui/LocalIndexesFragment.java @@ -213,10 +213,10 @@ public class LocalIndexesFragment extends OsmandExpandableListFragment implement private boolean performBasicOperation(int resId, final LocalIndexInfo info) { if (resId == R.string.shared_string_rename) { - renameFile(getActivity(), new File(info.getPathToData()), new Runnable() { + renameFile(getActivity(), new File(info.getPathToData()), new RenameCallback() { @Override - public void run() { + public void renamedTo(File file) { getDownloadActivity().reloadLocalIndexes(); } }); @@ -256,7 +256,7 @@ public class LocalIndexesFragment extends OsmandExpandableListFragment implement return true; } - public static void renameFile(final Activity a, final File f, final Runnable callback) { + public static void renameFile(final Activity a, final File f, final RenameCallback callback) { AlertDialog.Builder b = new AlertDialog.Builder(a); if (f.exists()) { int xt = f.getName().lastIndexOf('.'); @@ -312,7 +312,7 @@ public class LocalIndexesFragment extends OsmandExpandableListFragment implement } if (f.renameTo(dest)) { if (callback != null) { - callback.run(); + callback.renamedTo(dest); } } else { Toast.makeText(a, R.string.file_can_not_be_renamed, @@ -1234,10 +1234,12 @@ public class LocalIndexesFragment extends OsmandExpandableListFragment implement optionsMenu.show(); } - - - private DownloadActivity getDownloadActivity() { return (DownloadActivity) getActivity(); } + + public interface RenameCallback { + + public void renamedTo(File file); + } } diff --git a/OsmAnd/src/net/osmand/plus/myplaces/AvailableGPXFragment.java b/OsmAnd/src/net/osmand/plus/myplaces/AvailableGPXFragment.java index 6fc6584320..f2fca76b45 100644 --- a/OsmAnd/src/net/osmand/plus/myplaces/AvailableGPXFragment.java +++ b/OsmAnd/src/net/osmand/plus/myplaces/AvailableGPXFragment.java @@ -38,6 +38,7 @@ import net.osmand.IndexConstants; import net.osmand.plus.ContextMenuAdapter; import net.osmand.plus.ContextMenuAdapter.ItemClickListener; import net.osmand.plus.ContextMenuItem; +import net.osmand.plus.GPXDatabase.GpxDataItem; import net.osmand.plus.GPXUtilities; import net.osmand.plus.GPXUtilities.GPXFile; import net.osmand.plus.GPXUtilities.GPXTrackAnalysis; @@ -58,6 +59,7 @@ import net.osmand.plus.activities.TrackActivity; import net.osmand.plus.base.OsmandExpandableListFragment; import net.osmand.plus.dialogs.DirectionsDialogs; import net.osmand.plus.download.ui.LocalIndexesFragment; +import net.osmand.plus.download.ui.LocalIndexesFragment.RenameCallback; import net.osmand.plus.helpers.AndroidUiHelper; import net.osmand.plus.monitoring.OsmandMonitoringPlugin; import net.osmand.plus.osmedit.OsmEditingPlugin; @@ -86,6 +88,7 @@ public class AvailableGPXFragment extends OsmandExpandableListFragment { private List selectedItems = new ArrayList<>(); private ActionMode actionMode; private LoadGpxTask asyncLoader; + private ProcessGpxTask asyncProcessor; private GpxIndexesAdapter allGpxAdapter; private static MessageFormat formatMb = new MessageFormat("{0, number,##.#} MB", Locale.US); private ContextMenuAdapter optionsMenuAdapter; @@ -141,6 +144,8 @@ public class AvailableGPXFragment extends OsmandExpandableListFragment { allGpxAdapter.refreshSelected(); allGpxAdapter.notifyDataSetChanged(); } + asyncProcessor = new ProcessGpxTask(); + asyncProcessor.execute(); updateCurrentTrack(); updateEnable = true; @@ -154,6 +159,10 @@ public class AvailableGPXFragment extends OsmandExpandableListFragment { if (operationTask != null) { operationTask.cancel(true); } + if (asyncProcessor != null) { + asyncProcessor.cancel(false); + asyncProcessor = null; + } } public void updateCurrentTrack() { @@ -354,6 +363,10 @@ public class AvailableGPXFragment extends OsmandExpandableListFragment { if (itemId == R.string.local_index_mi_reload) { asyncLoader = new LoadGpxTask(); asyncLoader.execute(getActivity()); + if (asyncProcessor == null) { + asyncProcessor = new ProcessGpxTask(); + asyncProcessor.execute(); + } } else if (itemId == R.string.shared_string_show_on_map) { openShowOnMapMode(); } else if (itemId == R.string.shared_string_delete) { @@ -623,6 +636,7 @@ public class AvailableGPXFragment extends OsmandExpandableListFragment { Toast.makeText(app, R.string.file_with_name_already_exists, Toast.LENGTH_LONG).show(); } else { if (info.file.renameTo(dest)) { + app.getGpxDatabase().rename(info.file, dest); asyncLoader = new LoadGpxTask(); asyncLoader.execute(getActivity()); } else { @@ -1086,10 +1100,10 @@ public class AvailableGPXFragment extends OsmandExpandableListFragment { item.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem item) { - LocalIndexesFragment.renameFile(getActivity(), gpxInfo.file, new Runnable() { - + LocalIndexesFragment.renameFile(getActivity(), gpxInfo.file, new RenameCallback() { @Override - public void run() { + public void renamedTo(File file) { + app.getGpxDatabase().rename(gpxInfo.file, file); asyncLoader = new LoadGpxTask(); asyncLoader.execute(getActivity()); } @@ -1157,6 +1171,7 @@ public class AvailableGPXFragment extends OsmandExpandableListFragment { if (!isCancelled() && (info.gpx == null || !info.gpx.showCurrentTrack)) { boolean successfull; successfull = Algorithms.removeAllFiles(info.file); + app.getGpxDatabase().remove(info.file); total++; if (successfull) { count++; @@ -1239,6 +1254,67 @@ public class AvailableGPXFragment extends OsmandExpandableListFragment { } } + public class ProcessGpxTask extends AsyncTask { + + private List processedDataFiles = new ArrayList<>(); + + ProcessGpxTask() { + List dataItems = app.getGpxDatabase().getItems(); + for (GpxDataItem item : dataItems) { + processedDataFiles.add(item.getFile()); + } + } + + @Override + protected Void doInBackground(Void... params) { + + File gpxPath = app.getAppPath(IndexConstants.GPX_INDEX_DIR); + if (gpxPath.canRead()) { + processGPXFolder(gpxPath, ""); + } + return null; + } + + private File[] listFilesSorted(File dir) { + File[] listFiles = dir.listFiles(); + if (listFiles == null) { + return new File[0]; + } + Arrays.sort(listFiles); + return listFiles; + } + + private void processGPXFolder(File gpxPath, String gpxSubfolder) { + for (File gpxFile : listFilesSorted(gpxPath)) { + if (gpxFile.isDirectory()) { + String sub = gpxSubfolder.length() == 0 ? + gpxFile.getName() : gpxSubfolder + "/" + gpxFile.getName(); + processGPXFolder(gpxFile, sub); + } else if (gpxFile.isFile() && gpxFile.getName().toLowerCase().endsWith(".gpx") && !processedDataFiles.contains(gpxFile)) { + GPXFile f = GPXUtilities.loadGPXFile(app, gpxFile); + GPXTrackAnalysis analysis = f.getAnalysis(gpxFile.lastModified()); + GpxDataItem newItem = new GpxDataItem(gpxFile, analysis); + app.getGpxDatabase().add(newItem); + + if (isCancelled()) { + break; + } + processedDataFiles.add(gpxFile); + publishProgress(newItem); + } + } + } + + @Override + protected void onProgressUpdate(GpxDataItem... items) { + allGpxAdapter.notifyDataSetChanged(); + } + + @Override + protected void onPostExecute(Void aVoid) { + asyncProcessor = null; + } + } private class SearchFilter extends Filter { @@ -1421,7 +1497,11 @@ public class AvailableGPXFragment extends OsmandExpandableListFragment { if (sgpx != null) { icon.setImageDrawable(app.getIconsCache().getIcon(R.drawable.ic_action_polygom_dark, R.color.color_distance)); analysis = sgpx.getTrackAnalysis(); - + } else { + GpxDataItem dataItem = app.getGpxDatabase().getItem(child.file); + if (dataItem != null) { + analysis = dataItem.getAnalysis(); + } } boolean sectionRead = analysis == null; if (sectionRead) {