Added gpx database

This commit is contained in:
Alexey Kulish 2017-02-19 12:18:07 +03:00
parent ac6e20f2e5
commit 80cd4b4c4f
5 changed files with 228 additions and 81 deletions

View file

@ -360,6 +360,7 @@ public class AppInitializer implements IProgress {
app.notificationHelper = startupInit(new NotificationHelper(app), NotificationHelper.class); app.notificationHelper = startupInit(new NotificationHelper(app), NotificationHelper.class);
app.liveMonitoringHelper = startupInit(new LiveMonitoringHelper(app), LiveMonitoringHelper.class); app.liveMonitoringHelper = startupInit(new LiveMonitoringHelper(app), LiveMonitoringHelper.class);
app.selectedGpxHelper = startupInit(new GpxSelectionHelper(app, app.savingTrackHelper), GpxSelectionHelper.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.favorites = startupInit(new FavouritesDbHelper(app), FavouritesDbHelper.class);
app.waypointHelper = startupInit(new WaypointHelper(app), WaypointHelper.class); app.waypointHelper = startupInit(new WaypointHelper(app), WaypointHelper.class);

View file

@ -2,7 +2,8 @@ package net.osmand.plus;
import net.osmand.IndexConstants; import net.osmand.IndexConstants;
import net.osmand.plus.GPXUtilities.GPXTrackAnalysis; 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 net.osmand.util.Algorithms;
import java.io.File; import java.io.File;
@ -59,6 +60,14 @@ public class GPXDatabase {
GPX_COL_POINTS + " int, " + GPX_COL_POINTS + " int, " +
GPX_COL_WPT_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; private OsmandApplication context;
public static class GpxDataItem { public static class GpxDataItem {
@ -83,8 +92,8 @@ public class GPXDatabase {
context = app; context = app;
} }
private SQLiteAPI.SQLiteConnection openConnection(boolean readonly) { private SQLiteConnection openConnection(boolean readonly) {
SQLiteAPI.SQLiteConnection conn = context.getSQLiteAPI().getOrCreateDatabase(DB_NAME, readonly); SQLiteConnection conn = context.getSQLiteAPI().getOrCreateDatabase(DB_NAME, readonly);
if (conn.getVersion() == 0 || DB_VERSION != conn.getVersion()) { if (conn.getVersion() == 0 || DB_VERSION != conn.getVersion()) {
if (readonly) { if (readonly) {
conn.close(); conn.close();
@ -101,11 +110,11 @@ public class GPXDatabase {
return conn; return conn;
} }
public void onCreate(SQLiteAPI.SQLiteConnection db) { public void onCreate(SQLiteConnection db) {
db.execSQL(GPX_TABLE_CREATE); 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) { if (newVersion == 2) {
db.execSQL(GPX_TABLE_CREATE); db.execSQL(GPX_TABLE_CREATE);
@ -114,12 +123,19 @@ public class GPXDatabase {
*/ */
} }
public boolean remove(GpxDataItem item) { public boolean rename(File currentFile, File newFile) {
SQLiteAPI.SQLiteConnection db = openConnection(false); SQLiteConnection db = openConnection(false);
if(db != null){ if(db != null){
try { try {
db.execSQL("DELETE FROM " + GPX_TABLE_NAME + " WHERE " + GPX_COL_NAME + " = ?, " + GPX_COL_DIR + " = ?", String newFileName = getFileName(newFile);
new Object[] { item.file.getName(), item.file.getParentFile().getName() }); 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 { } finally {
db.close(); db.close();
} }
@ -128,8 +144,28 @@ public class GPXDatabase {
return false; 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) { public boolean add(GpxDataItem item) {
SQLiteAPI.SQLiteConnection db = openConnection(false); SQLiteConnection db = openConnection(false);
if(db != null){ if(db != null){
try { try {
insert(item, db); insert(item, db);
@ -141,9 +177,18 @@ public class GPXDatabase {
return false; return false;
} }
private void insert(GpxDataItem item, SQLiteAPI.SQLiteConnection db) { private String getFileName(File itemFile) {
String fileName = item.file.getName(); return itemFile.getName();
String fileDir = item.file.getParentFile().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(); GPXTrackAnalysis a = item.getAnalysis();
db.execSQL( db.execSQL(
"INSERT INTO " + GPX_TABLE_NAME + " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", "INSERT INTO " + GPX_TABLE_NAME + " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
@ -152,22 +197,7 @@ public class GPXDatabase {
a.avgElevation, a.minElevation, a.maxElevation, a.maxSpeed, a.avgSpeed, a.points, a.wptPoints }); a.avgElevation, a.minElevation, a.maxElevation, a.maxSpeed, a.avgSpeed, a.points, a.wptPoints });
} }
public List<GpxDataItem> getItems() { private GpxDataItem readItem(SQLiteCursor query) {
List<GpxDataItem> items = new ArrayList<>();
SQLiteAPI.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);
if (query.moveToFirst()) {
do {
String fileName = query.getString(0); String fileName = query.getString(0);
String fileDir = query.getString(1); String fileDir = query.getString(1);
float totalDistance = (float)query.getDouble(2); float totalDistance = (float)query.getDouble(2);
@ -211,10 +241,19 @@ public class GPXDatabase {
} else { } else {
dir = context.getAppPath(IndexConstants.GPX_INDEX_DIR); dir = context.getAppPath(IndexConstants.GPX_INDEX_DIR);
} }
GpxDataItem item = new GpxDataItem(new File(dir, fileName), a); return new GpxDataItem(new File(dir, fileName), a);
items.add(item); }
} while (query.moveToNext());
public List<GpxDataItem> getItems() {
List<GpxDataItem> items = new ArrayList<>();
SQLiteConnection db = openConnection(true);
if (db != null){
try {
SQLiteCursor query = db.rawQuery(GPX_TABLE_SELECT , null);
if (query.moveToFirst()) {
do {
items.add(readItem(query));
} while (query.moveToNext());
} }
query.close(); query.close();
} finally { } finally {
@ -223,4 +262,24 @@ public class GPXDatabase {
} }
return items; 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;
}
} }

View file

@ -95,6 +95,7 @@ public class OsmandApplication extends MultiDexApplication {
FavouritesDbHelper favorites; FavouritesDbHelper favorites;
CommandPlayer player; CommandPlayer player;
GpxSelectionHelper selectedGpxHelper; GpxSelectionHelper selectedGpxHelper;
GPXDatabase gpxDatabase;
SavingTrackHelper savingTrackHelper; SavingTrackHelper savingTrackHelper;
NotificationHelper notificationHelper; NotificationHelper notificationHelper;
LiveMonitoringHelper liveMonitoringHelper; LiveMonitoringHelper liveMonitoringHelper;
@ -272,6 +273,10 @@ public class OsmandApplication extends MultiDexApplication {
return selectedGpxHelper; return selectedGpxHelper;
} }
public GPXDatabase getGpxDatabase() {
return gpxDatabase;
}
public FavouritesDbHelper getFavorites() { public FavouritesDbHelper getFavorites() {
return favorites; return favorites;
} }

View file

@ -213,10 +213,10 @@ public class LocalIndexesFragment extends OsmandExpandableListFragment implement
private boolean performBasicOperation(int resId, final LocalIndexInfo info) { private boolean performBasicOperation(int resId, final LocalIndexInfo info) {
if (resId == R.string.shared_string_rename) { if (resId == R.string.shared_string_rename) {
renameFile(getActivity(), new File(info.getPathToData()), new Runnable() { renameFile(getActivity(), new File(info.getPathToData()), new RenameCallback() {
@Override @Override
public void run() { public void renamedTo(File file) {
getDownloadActivity().reloadLocalIndexes(); getDownloadActivity().reloadLocalIndexes();
} }
}); });
@ -256,7 +256,7 @@ public class LocalIndexesFragment extends OsmandExpandableListFragment implement
return true; 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); AlertDialog.Builder b = new AlertDialog.Builder(a);
if (f.exists()) { if (f.exists()) {
int xt = f.getName().lastIndexOf('.'); int xt = f.getName().lastIndexOf('.');
@ -312,7 +312,7 @@ public class LocalIndexesFragment extends OsmandExpandableListFragment implement
} }
if (f.renameTo(dest)) { if (f.renameTo(dest)) {
if (callback != null) { if (callback != null) {
callback.run(); callback.renamedTo(dest);
} }
} else { } else {
Toast.makeText(a, R.string.file_can_not_be_renamed, Toast.makeText(a, R.string.file_can_not_be_renamed,
@ -1234,10 +1234,12 @@ public class LocalIndexesFragment extends OsmandExpandableListFragment implement
optionsMenu.show(); optionsMenu.show();
} }
private DownloadActivity getDownloadActivity() { private DownloadActivity getDownloadActivity() {
return (DownloadActivity) getActivity(); return (DownloadActivity) getActivity();
} }
public interface RenameCallback {
public void renamedTo(File file);
}
} }

View file

@ -38,6 +38,7 @@ import net.osmand.IndexConstants;
import net.osmand.plus.ContextMenuAdapter; import net.osmand.plus.ContextMenuAdapter;
import net.osmand.plus.ContextMenuAdapter.ItemClickListener; import net.osmand.plus.ContextMenuAdapter.ItemClickListener;
import net.osmand.plus.ContextMenuItem; import net.osmand.plus.ContextMenuItem;
import net.osmand.plus.GPXDatabase.GpxDataItem;
import net.osmand.plus.GPXUtilities; import net.osmand.plus.GPXUtilities;
import net.osmand.plus.GPXUtilities.GPXFile; import net.osmand.plus.GPXUtilities.GPXFile;
import net.osmand.plus.GPXUtilities.GPXTrackAnalysis; 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.base.OsmandExpandableListFragment;
import net.osmand.plus.dialogs.DirectionsDialogs; import net.osmand.plus.dialogs.DirectionsDialogs;
import net.osmand.plus.download.ui.LocalIndexesFragment; 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.helpers.AndroidUiHelper;
import net.osmand.plus.monitoring.OsmandMonitoringPlugin; import net.osmand.plus.monitoring.OsmandMonitoringPlugin;
import net.osmand.plus.osmedit.OsmEditingPlugin; import net.osmand.plus.osmedit.OsmEditingPlugin;
@ -86,6 +88,7 @@ public class AvailableGPXFragment extends OsmandExpandableListFragment {
private List<GpxInfo> selectedItems = new ArrayList<>(); private List<GpxInfo> selectedItems = new ArrayList<>();
private ActionMode actionMode; private ActionMode actionMode;
private LoadGpxTask asyncLoader; private LoadGpxTask asyncLoader;
private ProcessGpxTask asyncProcessor;
private GpxIndexesAdapter allGpxAdapter; private GpxIndexesAdapter allGpxAdapter;
private static MessageFormat formatMb = new MessageFormat("{0, number,##.#} MB", Locale.US); private static MessageFormat formatMb = new MessageFormat("{0, number,##.#} MB", Locale.US);
private ContextMenuAdapter optionsMenuAdapter; private ContextMenuAdapter optionsMenuAdapter;
@ -141,6 +144,8 @@ public class AvailableGPXFragment extends OsmandExpandableListFragment {
allGpxAdapter.refreshSelected(); allGpxAdapter.refreshSelected();
allGpxAdapter.notifyDataSetChanged(); allGpxAdapter.notifyDataSetChanged();
} }
asyncProcessor = new ProcessGpxTask();
asyncProcessor.execute();
updateCurrentTrack(); updateCurrentTrack();
updateEnable = true; updateEnable = true;
@ -154,6 +159,10 @@ public class AvailableGPXFragment extends OsmandExpandableListFragment {
if (operationTask != null) { if (operationTask != null) {
operationTask.cancel(true); operationTask.cancel(true);
} }
if (asyncProcessor != null) {
asyncProcessor.cancel(false);
asyncProcessor = null;
}
} }
public void updateCurrentTrack() { public void updateCurrentTrack() {
@ -354,6 +363,10 @@ public class AvailableGPXFragment extends OsmandExpandableListFragment {
if (itemId == R.string.local_index_mi_reload) { if (itemId == R.string.local_index_mi_reload) {
asyncLoader = new LoadGpxTask(); asyncLoader = new LoadGpxTask();
asyncLoader.execute(getActivity()); asyncLoader.execute(getActivity());
if (asyncProcessor == null) {
asyncProcessor = new ProcessGpxTask();
asyncProcessor.execute();
}
} else if (itemId == R.string.shared_string_show_on_map) { } else if (itemId == R.string.shared_string_show_on_map) {
openShowOnMapMode(); openShowOnMapMode();
} else if (itemId == R.string.shared_string_delete) { } 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(); Toast.makeText(app, R.string.file_with_name_already_exists, Toast.LENGTH_LONG).show();
} else { } else {
if (info.file.renameTo(dest)) { if (info.file.renameTo(dest)) {
app.getGpxDatabase().rename(info.file, dest);
asyncLoader = new LoadGpxTask(); asyncLoader = new LoadGpxTask();
asyncLoader.execute(getActivity()); asyncLoader.execute(getActivity());
} else { } else {
@ -1086,10 +1100,10 @@ public class AvailableGPXFragment extends OsmandExpandableListFragment {
item.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { item.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
@Override @Override
public boolean onMenuItemClick(MenuItem item) { public boolean onMenuItemClick(MenuItem item) {
LocalIndexesFragment.renameFile(getActivity(), gpxInfo.file, new Runnable() { LocalIndexesFragment.renameFile(getActivity(), gpxInfo.file, new RenameCallback() {
@Override @Override
public void run() { public void renamedTo(File file) {
app.getGpxDatabase().rename(gpxInfo.file, file);
asyncLoader = new LoadGpxTask(); asyncLoader = new LoadGpxTask();
asyncLoader.execute(getActivity()); asyncLoader.execute(getActivity());
} }
@ -1157,6 +1171,7 @@ public class AvailableGPXFragment extends OsmandExpandableListFragment {
if (!isCancelled() && (info.gpx == null || !info.gpx.showCurrentTrack)) { if (!isCancelled() && (info.gpx == null || !info.gpx.showCurrentTrack)) {
boolean successfull; boolean successfull;
successfull = Algorithms.removeAllFiles(info.file); successfull = Algorithms.removeAllFiles(info.file);
app.getGpxDatabase().remove(info.file);
total++; total++;
if (successfull) { if (successfull) {
count++; count++;
@ -1239,6 +1254,67 @@ public class AvailableGPXFragment extends OsmandExpandableListFragment {
} }
} }
public class ProcessGpxTask extends AsyncTask<Void, GpxDataItem, Void> {
private List<File> processedDataFiles = new ArrayList<>();
ProcessGpxTask() {
List<GpxDataItem> 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 { private class SearchFilter extends Filter {
@ -1421,7 +1497,11 @@ public class AvailableGPXFragment extends OsmandExpandableListFragment {
if (sgpx != null) { if (sgpx != null) {
icon.setImageDrawable(app.getIconsCache().getIcon(R.drawable.ic_action_polygom_dark, R.color.color_distance)); icon.setImageDrawable(app.getIconsCache().getIcon(R.drawable.ic_action_polygom_dark, R.color.color_distance));
analysis = sgpx.getTrackAnalysis(); analysis = sgpx.getTrackAnalysis();
} else {
GpxDataItem dataItem = app.getGpxDatabase().getItem(child.file);
if (dataItem != null) {
analysis = dataItem.getAnalysis();
}
} }
boolean sectionRead = analysis == null; boolean sectionRead = analysis == null;
if (sectionRead) { if (sectionRead) {