This commit is contained in:
max-klaus 2019-10-27 20:06:02 +03:00
parent 03144c7a2b
commit 15326798b1
16 changed files with 622 additions and 248 deletions

View file

@ -1210,11 +1210,11 @@ public class OsmandAidlApi {
if (!destinationExists) { if (!destinationExists) {
GpxDataItem gpxDataItem = new GpxDataItem(destination, col); GpxDataItem gpxDataItem = new GpxDataItem(destination, col);
gpxDataItem.setApiImported(true); gpxDataItem.setApiImported(true);
app.getGpxDatabase().add(gpxDataItem); app.getGpxDbHelper().add(gpxDataItem);
} else { } else {
GpxDataItem item = app.getGpxDatabase().getItem(destination); GpxDataItem item = app.getGpxDbHelper().getItem(destination);
if (item != null) { if (item != null) {
app.getGpxDatabase().updateColor(item, col); app.getGpxDbHelper().updateColor(item, col);
} }
} }
final GpxSelectionHelper helper = app.getSelectedGpxHelper(); final GpxSelectionHelper helper = app.getSelectedGpxHelper();
@ -1435,7 +1435,7 @@ public class OsmandAidlApi {
} }
boolean getImportedGpxV2(List<net.osmand.aidlapi.gpx.AGpxFile> files) { boolean getImportedGpxV2(List<net.osmand.aidlapi.gpx.AGpxFile> files) {
List<GpxDataItem> gpxDataItems = app.getGpxDatabase().getItems(); List<GpxDataItem> gpxDataItems = app.getGpxDbHelper().getItems();
for (GpxDataItem dataItem : gpxDataItems) { for (GpxDataItem dataItem : gpxDataItems) {
File file = dataItem.getFile(); File file = dataItem.getFile();
if (file.exists()) { if (file.exists()) {
@ -1460,7 +1460,7 @@ public class OsmandAidlApi {
} }
boolean getImportedGpx(List<AGpxFile> files) { boolean getImportedGpx(List<AGpxFile> files) {
List<GpxDataItem> gpxDataItems = app.getGpxDatabase().getItems(); List<GpxDataItem> gpxDataItems = app.getGpxDbHelper().getItems();
for (GpxDataItem dataItem : gpxDataItems) { for (GpxDataItem dataItem : gpxDataItems) {
File file = dataItem.getFile(); File file = dataItem.getFile();
if (file.exists()) { if (file.exists()) {
@ -1480,7 +1480,7 @@ public class OsmandAidlApi {
} }
String getGpxColor(String gpxFileName) { String getGpxColor(String gpxFileName) {
List<GpxDataItem> gpxDataItems = app.getGpxDatabase().getItems(); List<GpxDataItem> gpxDataItems = app.getGpxDbHelper().getItems();
for (GpxDataItem dataItem : gpxDataItems) { for (GpxDataItem dataItem : gpxDataItems) {
File file = dataItem.getFile(); File file = dataItem.getFile();
if (file.exists()) { if (file.exists()) {
@ -1499,10 +1499,10 @@ public class OsmandAidlApi {
if (!Algorithms.isEmpty(fileName)) { if (!Algorithms.isEmpty(fileName)) {
final File f = app.getAppPath(IndexConstants.GPX_INDEX_DIR + fileName); final File f = app.getAppPath(IndexConstants.GPX_INDEX_DIR + fileName);
if (f.exists()) { if (f.exists()) {
GpxDataItem item = app.getGpxDatabase().getItem(f); GpxDataItem item = app.getGpxDbHelper().getItem(f);
if (item != null && item.isApiImported()) { if (item != null && item.isApiImported()) {
Algorithms.removeAllFiles(f); Algorithms.removeAllFiles(f);
app.getGpxDatabase().remove(f); app.getGpxDbHelper().remove(f);
return true; return true;
} }
} }

View file

@ -482,7 +482,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.gpxDbHelper = startupInit(new GpxDbHelper(app), GpxDbHelper.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);
app.aidlApi = startupInit(new OsmandAidlApi(app), OsmandAidlApi.class); app.aidlApi = startupInit(new OsmandAidlApi(app), OsmandAidlApi.class);
@ -669,6 +669,7 @@ public class AppInitializer implements IProgress {
notifyEvent(InitEvents.NATIVE_INITIALIZED); notifyEvent(InitEvents.NATIVE_INITIALIZED);
app.favorites.loadFavorites(); app.favorites.loadFavorites();
app.gpxDbHelper.loadGpxItems();
notifyEvent(InitEvents.FAVORITES_INITIALIZED); notifyEvent(InitEvents.FAVORITES_INITIALIZED);
app.poiFilters.reloadAllPoiFilters(); app.poiFilters.reloadAllPoiFilters();
app.poiFilters.loadSelectedPoiFilters(); app.poiFilters.loadSelectedPoiFilters();

View file

@ -199,13 +199,35 @@ public class GPXDatabase {
public void setShowAsMarkers(boolean showAsMarkers) { public void setShowAsMarkers(boolean showAsMarkers) {
this.showAsMarkers = showAsMarkers; this.showAsMarkers = showAsMarkers;
} }
@Override
public int hashCode() {
return file != null ? file.hashCode() : 0;
} }
public GPXDatabase(OsmandApplication app) { @Override
public boolean equals(Object obj) {
if (!(obj instanceof GpxDataItem)) {
return false;
}
final GpxDataItem other = (GpxDataItem) obj;
if (file == null || other.file == null) {
return false;
}
return file.equals(other.file);
}
}
GPXDatabase(OsmandApplication app) {
context = app; context = app;
// init database
SQLiteConnection db = openConnection(false);
if (db != null) {
db.close();
}
} }
private SQLiteConnection openConnection(boolean readonly) { SQLiteConnection openConnection(boolean readonly) {
SQLiteConnection conn = context.getSQLiteAPI().getOrCreateDatabase(DB_NAME, readonly); SQLiteConnection conn = context.getSQLiteAPI().getOrCreateDatabase(DB_NAME, readonly);
if (conn.getVersion() < DB_VERSION) { if (conn.getVersion() < DB_VERSION) {
if (readonly) { if (readonly) {
@ -225,6 +247,7 @@ public class GPXDatabase {
private void onCreate(SQLiteConnection db) { private void onCreate(SQLiteConnection db) {
db.execSQL(GPX_TABLE_CREATE); db.execSQL(GPX_TABLE_CREATE);
db.execSQL("CREATE INDEX IF NOT EXISTS " + GPX_INDEX_NAME_DIR + " ON " + GPX_TABLE_NAME + " (" + GPX_COL_NAME + ", " + GPX_COL_DIR + ");");
} }
private void onUpgrade(SQLiteConnection db, int oldVersion, int newVersion) { private void onUpgrade(SQLiteConnection db, int oldVersion, int newVersion) {
@ -401,7 +424,7 @@ public class GPXDatabase {
public boolean remove(File file) { public boolean remove(File file) {
SQLiteConnection db = openConnection(false); SQLiteConnection db = openConnection(false);
if (db != null){ if (db != null) {
try { try {
String fileName = getFileName(file); String fileName = getFileName(file);
String fileDir = getFileDir(file); String fileDir = getFileDir(file);
@ -421,7 +444,7 @@ public class GPXDatabase {
public boolean add(GpxDataItem item) { public boolean add(GpxDataItem item) {
SQLiteConnection db = openConnection(false); SQLiteConnection db = openConnection(false);
if (db != null){ if (db != null) {
try { try {
insert(item, db); insert(item, db);
} finally { } finally {
@ -442,7 +465,7 @@ public class GPXDatabase {
"" : itemFile.getParentFile().getName(); "" : itemFile.getParentFile().getName();
} }
private void insert(GpxDataItem item, SQLiteConnection db) { void insert(GpxDataItem item, SQLiteConnection db) {
String fileName = getFileName(item.file); String fileName = getFileName(item.file);
String fileDir = getFileDir(item.file); String fileDir = getFileDir(item.file);
GPXTrackAnalysis a = item.getAnalysis(); GPXTrackAnalysis a = item.getAnalysis();
@ -482,22 +505,30 @@ public class GPXDatabase {
SQLiteConnection db = openConnection(false); SQLiteConnection db = openConnection(false);
if (db != null) { if (db != null) {
try { try {
String fileName = getFileName(item.file); return updateAnalysis(item, a, db);
String fileDir = getFileDir(item.file);
db.execSQL(GPX_TABLE_UPDATE_ANALYSIS + " WHERE " + GPX_COL_NAME + " = ? AND " + GPX_COL_DIR + " = ?",
new Object[]{ a.totalDistance, a.totalTracks, a.startTime, a.endTime,
a.timeSpan, a.timeMoving, a.totalDistanceMoving, a.diffElevationUp,
a.diffElevationDown, a.avgElevation, a.minElevation, a.maxElevation,
a.maxSpeed, a.avgSpeed, a.points, a.wptPoints, item.file.lastModified(),
Algorithms.encodeStringSet(a.wptCategoryNames), fileName, fileDir });
} finally { } finally {
db.close(); db.close();
} }
return true;
} }
return false; return false;
} }
public boolean updateAnalysis(GpxDataItem item, GPXTrackAnalysis a, SQLiteConnection db) {
if (a == null) {
return false;
}
String fileName = getFileName(item.file);
String fileDir = getFileDir(item.file);
db.execSQL(GPX_TABLE_UPDATE_ANALYSIS + " WHERE " + GPX_COL_NAME + " = ? AND " + GPX_COL_DIR + " = ?",
new Object[]{a.totalDistance, a.totalTracks, a.startTime, a.endTime,
a.timeSpan, a.timeMoving, a.totalDistanceMoving, a.diffElevationUp,
a.diffElevationDown, a.avgElevation, a.minElevation, a.maxElevation,
a.maxSpeed, a.avgSpeed, a.points, a.wptPoints, item.file.lastModified(),
Algorithms.encodeStringSet(a.wptCategoryNames), fileName, fileDir});
item.analysis = a;
return true;
}
public boolean clearAnalysis(GpxDataItem item) { public boolean clearAnalysis(GpxDataItem item) {
SQLiteConnection db = openConnection(false); SQLiteConnection db = openConnection(false);
if (db != null) { if (db != null) {
@ -584,20 +615,24 @@ public class GPXDatabase {
return item; return item;
} }
@NonNull
public List<GpxDataItem> getItems() { public List<GpxDataItem> getItems() {
List<GpxDataItem> items = new ArrayList<>(); List<GpxDataItem> items = new ArrayList<>();
SQLiteConnection db = openConnection(true); SQLiteConnection db = openConnection(false);
if (db != null) { if (db != null) {
try { try {
SQLiteCursor query = db.rawQuery(GPX_TABLE_SELECT, null); SQLiteCursor query = db.rawQuery(GPX_TABLE_SELECT, null);
if (query != null && query.moveToFirst()) { if (query != null) {
try {
if (query.moveToFirst()) {
do { do {
items.add(readItem(query)); items.add(readItem(query));
} while (query.moveToNext()); } while (query.moveToNext());
} }
if (query != null) { } finally {
query.close(); query.close();
} }
}
} finally { } finally {
db.close(); db.close();
} }
@ -608,23 +643,58 @@ public class GPXDatabase {
@Nullable @Nullable
public GpxDataItem getItem(File file) { public GpxDataItem getItem(File file) {
GpxDataItem result = null; GpxDataItem result = null;
SQLiteConnection db = openConnection(true); SQLiteConnection db = openConnection(false);
if (db != null){ if (db != null) {
try { try {
String fileName = getFileName(file); result = getItem(file, db);
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 != null && query.moveToFirst()) {
result = readItem(query);
}
if (query != null) {
query.close();
}
} finally { } finally {
db.close(); db.close();
} }
} }
return result; return result;
} }
@Nullable
public GpxDataItem getItem(File file, SQLiteConnection db) {
GpxDataItem result = null;
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 != null) {
try {
if (query.moveToFirst()) {
result = readItem(query);
}
} finally {
query.close();
}
}
return result;
}
@NonNull
public List<GpxDataItem> getSplitItems() {
List<GpxDataItem> items = new ArrayList<>();
SQLiteConnection db = openConnection(false);
if (db != null) {
try {
SQLiteCursor query = db.rawQuery(GPX_TABLE_SELECT + " WHERE " + GPX_COL_SPLIT_TYPE + " != ?", new String[] { String.valueOf(0) });
if (query != null) {
try {
if (query.moveToFirst()) {
do {
items.add(readItem(query));
} while (query.moveToNext());
}
} finally {
query.close();
}
}
} finally {
db.close();
}
}
return items;
}
} }

View file

@ -0,0 +1,265 @@
package net.osmand.plus;
import android.annotation.SuppressLint;
import android.os.AsyncTask;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import net.osmand.GPXUtilities;
import net.osmand.GPXUtilities.GPXFile;
import net.osmand.GPXUtilities.GPXTrackAnalysis;
import net.osmand.plus.GPXDatabase.GpxDataItem;
import net.osmand.plus.api.SQLiteAPI;
import net.osmand.plus.api.SQLiteAPI.SQLiteConnection;
import java.io.File;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
public class GpxDbHelper {
private static final int MAX_ITEMS_CACHE_SIZE = 5000;
private OsmandApplication app;
private GPXDatabase db;
private Map<File, GpxDataItem> itemsCache = new ConcurrentHashMap<>();
private ConcurrentLinkedQueue<File> readingItems = new ConcurrentLinkedQueue<>();
private Map<File, GpxDataItem> readingItemsMap = new ConcurrentHashMap<>();
private Map<File, GpxDataItemCallback> readingItemsCallbacks = new ConcurrentHashMap<>();
private GpxReaderTask readerTask;
public interface GpxDataItemCallback {
boolean isCancelled();
void onGpxDataItemReady(GpxDataItem item);
}
GpxDbHelper(OsmandApplication app) {
this.app = app;
db = new GPXDatabase(app);
}
void loadGpxItems() {
List<GpxDataItem> items = getItems();
for (GpxDataItem item : items) {
putToCache(item);
}
}
private void updateItemsCacheSize() {
if (itemsCache.size() > MAX_ITEMS_CACHE_SIZE) {
itemsCache.clear();
}
}
private GpxDataItem putToCache(GpxDataItem item) {
updateItemsCacheSize();
return itemsCache.put(item.getFile(), item);
}
private void removeFromCache(GpxDataItem item) {
itemsCache.remove(item.getFile());
}
public boolean rename(File currentFile, File newFile) {
boolean res = db.rename(currentFile, newFile);
itemsCache.remove(currentFile);
return res;
}
public boolean updateColor(GpxDataItem item, int color) {
boolean res = db.updateColor(item, color);
putToCache(item);
return res;
}
public boolean updateShowAsMarkers(GpxDataItem item, boolean showAsMarkers) {
boolean res = db.updateShowAsMarkers(item, showAsMarkers);
putToCache(item);
return res;
}
public boolean updateSplit(@NonNull GpxDataItem item, int splitType, double splitInterval) {
boolean res = db.updateSplit(item, splitType, splitInterval);
putToCache(item);
return res;
}
public boolean remove(File file) {
boolean res = db.remove(file);
itemsCache.remove(file);
return res;
}
public boolean remove(GpxDataItem item) {
boolean res = db.remove(item);
itemsCache.remove(item.getFile());
return res;
}
public boolean add(GpxDataItem item) {
boolean res = db.add(item);
putToCache(item);
return res;
}
public boolean updateAnalysis(GpxDataItem item, GPXTrackAnalysis a) {
boolean res = db.updateAnalysis(item, a);
putToCache(item);
return res;
}
public boolean clearAnalysis(GpxDataItem item) {
boolean res = db.clearAnalysis(item);
itemsCache.remove(item.getFile());
return res;
}
public List<GpxDataItem> getItems() {
return db.getItems();
}
public GpxDataItem getItem(File file) {
return getItem(file, null);
}
public GpxDataItem getItem(File file, @Nullable GpxDataItemCallback callback) {
GpxDataItem item = itemsCache.get(file);
if (item == null && !isGpxReading(file)) {
readGpxItem(file, item, callback);
}
return item;
}
public List<GpxDataItem> getSplitItems() {
return db.getSplitItems();
}
public boolean isRead() {
GpxReaderTask readerTask = this.readerTask;
return readerTask == null || !readerTask.isReading();
}
private boolean isGpxReading(@NonNull File gpxFile) {
GpxReaderTask analyser = this.readerTask;
return readingItems.contains(gpxFile)
|| (analyser != null && gpxFile.equals(analyser.getGpxFile()));
}
private void readGpxItem(@NonNull File gpxFile, @Nullable GpxDataItem item, @Nullable GpxDataItemCallback callback) {
readingItemsMap.put(gpxFile, item != null ? item : new GpxDataItem(null, null));
if (callback != null) {
readingItemsCallbacks.put(gpxFile, callback);
}
readingItems.add(gpxFile);
if (readerTask == null) {
startReading();
}
}
private void startReading() {
readerTask = new GpxReaderTask();
readerTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
private void stopReading() {
if (readerTask != null) {
readerTask.cancel(false);
readerTask = null;
}
}
@SuppressLint("StaticFieldLeak")
private class GpxReaderTask extends AsyncTask<Void, GpxDataItem, Void> {
private File gpxFile;
public File getGpxFile() {
return gpxFile;
}
public boolean isReading() {
return readingItems.size() > 0 || gpxFile != null;
}
private boolean isAnalyseNeeded(@NonNull File gpxFile, @Nullable GpxDataItem item) {
return item == null
|| item.getFileLastModifiedTime() != gpxFile.lastModified()
|| item.getAnalysis() == null
|| item.getAnalysis().wptCategoryNames == null;
}
@Override
protected Void doInBackground(Void... voids) {
SQLiteConnection conn = db.openConnection(false);
if (conn != null) {
try {
gpxFile = readingItems.poll();
while (gpxFile != null && !isCancelled()) {
GpxDataItem item = readingItemsMap.remove(gpxFile);
if (item.getFile() == null) {
item = db.getItem(gpxFile, conn);
}
if (isAnalyseNeeded(gpxFile, item)) {
GPXFile f = GPXUtilities.loadGPXFile(gpxFile);
GPXTrackAnalysis analysis = f.getAnalysis(gpxFile.lastModified());
if (item == null || item.getFile() == null) {
item = new GpxDataItem(gpxFile, analysis);
db.insert(item, conn);
putToCache(item);
} else {
db.updateAnalysis(item, analysis, conn);
putToCache(item);
}
} else {
putToCache(item);
}
if (!isCancelled()) {
publishProgress(item);
}
gpxFile = readingItems.poll();
}
} finally {
conn.close();
}
} else {
cancel(false);
}
return null;
}
@Override
protected void onCancelled(Void aVoid) {
readingItems.clear();
readingItemsMap.clear();
readingItemsCallbacks.clear();
}
@Override
protected void onProgressUpdate(GpxDataItem... values) {
GpxDataItem item = values[0];
GpxDataItemCallback callback = readingItemsCallbacks.remove(item.getFile());
if (callback != null) {
if (callback.isCancelled()) {
stopReading();
} else {
callback.onGpxDataItemReady(item);
}
}
}
@Override
protected void onPostExecute(Void aVoid) {
if (readingItems.size() > 0 && !isCancelled()) {
startReading();
} else {
readerTask = null;
}
}
}
}

View file

@ -152,9 +152,8 @@ public class GpxSelectionHelper {
} }
public void processSplit() { public void processSplit() {
List<GpxDataItem> items = app.getGpxDatabase().getItems(); List<GpxDataItem> items = app.getGpxDbHelper().getSplitItems();
for (GpxDataItem dataItem : items) { for (GpxDataItem dataItem : items) {
if (dataItem.getSplitType() != 0) {
SelectedGpxFile selectedGpxFile = getSelectedFileByPath(dataItem.getFile().getAbsolutePath()); SelectedGpxFile selectedGpxFile = getSelectedFileByPath(dataItem.getFile().getAbsolutePath());
if (selectedGpxFile != null && selectedGpxFile.getGpxFile() != null) { if (selectedGpxFile != null && selectedGpxFile.getGpxFile() != null) {
GPXFile gpxFile = selectedGpxFile.getGpxFile(); GPXFile gpxFile = selectedGpxFile.getGpxFile();
@ -178,7 +177,6 @@ public class GpxSelectionHelper {
} }
} }
} }
}
private String getString(int resId, Object... formatArgs) { private String getString(int resId, Object... formatArgs) {
return app.getString(resId, formatArgs); return app.getString(resId, formatArgs);
@ -622,7 +620,7 @@ public class GpxSelectionHelper {
} }
public SelectedGpxFile selectGpxFile(GPXFile gpx, boolean show, boolean notShowNavigationDialog, boolean syncGroup, boolean selectedByUser, boolean canAddToMarkers) { public SelectedGpxFile selectGpxFile(GPXFile gpx, boolean show, boolean notShowNavigationDialog, boolean syncGroup, boolean selectedByUser, boolean canAddToMarkers) {
GpxDataItem dataItem = app.getGpxDatabase().getItem(new File(gpx.path)); GpxDataItem dataItem = app.getGpxDbHelper().getItem(new File(gpx.path));
if (canAddToMarkers && show && dataItem != null && dataItem.isShowAsMarkers()) { if (canAddToMarkers && show && dataItem != null && dataItem.isShowAsMarkers()) {
app.getMapMarkersHelper().addOrEnableGroup(gpx); app.getMapMarkersHelper().addOrEnableGroup(gpx);
} }

View file

@ -370,9 +370,9 @@ public class MapMarkersHelper {
} }
private void updateGpxShowAsMarkers(File file) { private void updateGpxShowAsMarkers(File file) {
GPXDatabase.GpxDataItem dataItem = ctx.getGpxDatabase().getItem(file); GPXDatabase.GpxDataItem dataItem = ctx.getGpxDbHelper().getItem(file);
if (dataItem != null) { if (dataItem != null) {
ctx.getGpxDatabase().updateShowAsMarkers(dataItem, true); ctx.getGpxDbHelper().updateShowAsMarkers(dataItem, true);
dataItem.setShowAsMarkers(true); dataItem.setShowAsMarkers(true);
} }
} }

View file

@ -116,7 +116,6 @@ public class OsmandApplication extends MultiDexApplication {
FavouritesDbHelper favorites; FavouritesDbHelper favorites;
CommandPlayer player; CommandPlayer player;
GpxSelectionHelper selectedGpxHelper; GpxSelectionHelper selectedGpxHelper;
GPXDatabase gpxDatabase;
SavingTrackHelper savingTrackHelper; SavingTrackHelper savingTrackHelper;
AnalyticsHelper analyticsHelper; AnalyticsHelper analyticsHelper;
NotificationHelper notificationHelper; NotificationHelper notificationHelper;
@ -137,6 +136,7 @@ public class OsmandApplication extends MultiDexApplication {
MapViewTrackingUtilities mapViewTrackingUtilities; MapViewTrackingUtilities mapViewTrackingUtilities;
LockHelper lockHelper; LockHelper lockHelper;
SettingsHelper settingsHelper; SettingsHelper settingsHelper;
GpxDbHelper gpxDbHelper;
private RoutingConfiguration.Builder routingConfig; private RoutingConfiguration.Builder routingConfig;
private Locale preferredLocale = null; private Locale preferredLocale = null;
@ -316,8 +316,8 @@ public class OsmandApplication extends MultiDexApplication {
return selectedGpxHelper; return selectedGpxHelper;
} }
public GPXDatabase getGpxDatabase() { public GpxDbHelper getGpxDbHelper() {
return gpxDatabase; return gpxDbHelper;
} }
public FavouritesDbHelper getFavorites() { public FavouritesDbHelper getFavorites() {

View file

@ -235,7 +235,7 @@ public class SavingTrackHelper extends SQLiteOpenHelper {
GPXFile gpx = data.get(f); GPXFile gpx = data.get(f);
GPXTrackAnalysis analysis = gpx.getAnalysis(fout.lastModified()); GPXTrackAnalysis analysis = gpx.getAnalysis(fout.lastModified());
GpxDataItem item = new GpxDataItem(fout, analysis); GpxDataItem item = new GpxDataItem(fout, analysis);
ctx.getGpxDatabase().add(item); ctx.getGpxDbHelper().add(item);
} }
} }
} }

View file

@ -337,7 +337,7 @@ public class TrackActivity extends TabActivity {
private void onGPXFileReady(@Nullable GPXFile gpxFile) { private void onGPXFileReady(@Nullable GPXFile gpxFile) {
setGpx(gpxFile); setGpx(gpxFile);
setGpxDataItem(file != null ? app.getGpxDatabase().getItem(file) : null); setGpxDataItem(file != null ? app.getGpxDbHelper().getItem(file) : null);
WindowManager mgr = (WindowManager) getSystemService(Context.WINDOW_SERVICE); WindowManager mgr = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
if (gpxFile != null && mgr != null) { if (gpxFile != null && mgr != null) {

View file

@ -73,7 +73,10 @@ import net.osmand.PlatformUtil;
import net.osmand.plus.ContextMenuAdapter; import net.osmand.plus.ContextMenuAdapter;
import net.osmand.plus.ContextMenuItem; import net.osmand.plus.ContextMenuItem;
import net.osmand.plus.GPXDatabase.GpxDataItem; import net.osmand.plus.GPXDatabase.GpxDataItem;
import net.osmand.plus.GpxDbHelper;
import net.osmand.plus.GpxDbHelper.GpxDataItemCallback;
import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile; import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile;
import net.osmand.plus.OsmAndConstants;
import net.osmand.plus.OsmAndFormatter; import net.osmand.plus.OsmAndFormatter;
import net.osmand.plus.OsmandApplication; import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandPlugin; import net.osmand.plus.OsmandPlugin;
@ -437,6 +440,59 @@ public class GpxUiHelper {
return dlg; return dlg;
} }
private static class DialogGpxDataItemCallback implements GpxDataItemCallback {
private static final int UPDATE_GPX_ITEM_MSG_ID = OsmAndConstants.UI_HANDLER_LOCATION_SERVICE + 6;
private static final long MIN_UPDATE_INTERVAL = 500;
private OsmandApplication app;
private long lastUpdateTime;
private boolean updateEnable = true;
private ArrayAdapter<String> listAdapter;
DialogGpxDataItemCallback(OsmandApplication app) {
this.app = app;
}
public boolean isUpdateEnable() {
return updateEnable;
}
public void setUpdateEnable(boolean updateEnable) {
this.updateEnable = updateEnable;
}
public ArrayAdapter<String> getListAdapter() {
return listAdapter;
}
public void setListAdapter(ArrayAdapter<String> listAdapter) {
this.listAdapter = listAdapter;
}
private Runnable updateItemsProc = new Runnable() {
@Override
public void run() {
if (updateEnable) {
lastUpdateTime = System.currentTimeMillis();
listAdapter.notifyDataSetChanged();
}
}
};
@Override
public boolean isCancelled() {
return !updateEnable;
}
@Override
public void onGpxDataItemReady(GpxDataItem item) {
if (System.currentTimeMillis() - lastUpdateTime > MIN_UPDATE_INTERVAL) {
updateItemsProc.run();
}
app.runMessageInUIThreadAndCancelPrevious(UPDATE_GPX_ITEM_MSG_ID, updateItemsProc, MIN_UPDATE_INTERVAL);
}
}
private static AlertDialog createDialog(final Activity activity, private static AlertDialog createDialog(final Activity activity,
final boolean showCurrentGpx, final boolean showCurrentGpx,
final boolean multipleChoice, final boolean multipleChoice,
@ -451,12 +507,11 @@ public class GpxUiHelper {
AlertDialog.Builder builder = new AlertDialog.Builder(new ContextThemeWrapper(activity, themeRes)); AlertDialog.Builder builder = new AlertDialog.Builder(new ContextThemeWrapper(activity, themeRes));
final int layout = R.layout.gpx_track_item; final int layout = R.layout.gpx_track_item;
final Map<String, String> gpxAppearanceParams = new HashMap<>(); final Map<String, String> gpxAppearanceParams = new HashMap<>();
final DialogGpxDataItemCallback gpxDataItemCallback = new DialogGpxDataItemCallback(app);
final ArrayAdapter<String> listAdapter = new ArrayAdapter<String>(activity, layout, R.id.title, final ArrayAdapter<String> listAdapter = new ArrayAdapter<String>(activity, layout, R.id.title,
adapter.getItemNames()) { adapter.getItemNames()) {
List<GpxDataItem> dataItems = null;
@Override @Override
public int getItemViewType(int position) { public int getItemViewType(int position) {
return showCurrentGpx && position == 0 ? 1 : 0; return showCurrentGpx && position == 0 ? 1 : 0;
@ -468,18 +523,14 @@ public class GpxUiHelper {
} }
private GpxDataItem getDataItem(GPXInfo info) { private GpxDataItem getDataItem(GPXInfo info) {
if (dataItems != null) { return app.getGpxDbHelper().getItem(
for (GpxDataItem item : dataItems) { new File(app.getAppPath(IndexConstants.GPX_INDEX_DIR), info.getFileName()),
if (item.getFile().getAbsolutePath().endsWith(info.fileName)) { gpxDataItemCallback);
return item;
}
}
}
return null;
} }
@Override @Override
public View getView(final int position, View convertView, ViewGroup parent) { @NonNull
public View getView(final int position, View convertView, @NonNull ViewGroup parent) {
// User super class to create the View // User super class to create the View
View v = convertView; View v = convertView;
boolean checkLayout = getItemViewType(position) == 0; boolean checkLayout = getItemViewType(position) == 0;
@ -487,13 +538,10 @@ public class GpxUiHelper {
v = View.inflate(new ContextThemeWrapper(activity, themeRes), layout, null); v = View.inflate(new ContextThemeWrapper(activity, themeRes), layout, null);
} }
if (dataItems == null) {
dataItems = app.getGpxDatabase().getItems();
}
final ContextMenuItem item = adapter.getItem(position); final ContextMenuItem item = adapter.getItem(position);
GPXInfo info = list.get(position); GPXInfo info = list.get(position);
updateGpxInfoView(v, item.getTitle(), info, getDataItem(info), showCurrentGpx && position == 0, app); boolean currentlyRecordingTrack = showCurrentGpx && position == 0;
updateGpxInfoView(v, item.getTitle(), info, currentlyRecordingTrack ? null : getDataItem(info), currentlyRecordingTrack, app);
if (item.getSelected() == null) { if (item.getSelected() == null) {
v.findViewById(R.id.check_item).setVisibility(View.GONE); v.findViewById(R.id.check_item).setVisibility(View.GONE);
@ -535,6 +583,7 @@ public class GpxUiHelper {
public void onClick(DialogInterface dialog, int position) { public void onClick(DialogInterface dialog, int position) {
} }
}; };
gpxDataItemCallback.setListAdapter(listAdapter);
builder.setAdapter(listAdapter, onClickListener); builder.setAdapter(listAdapter, onClickListener);
if (multipleChoice) { if (multipleChoice) {
if (showAppearanceSetting) { if (showAppearanceSetting) {
@ -721,6 +770,12 @@ public class GpxUiHelper {
} }
} }
}); });
dlg.setOnDismissListener(new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog) {
gpxDataItemCallback.setUpdateEnable(false);
}
});
dlg.show(); dlg.show();
try { try {
dlg.getListView().setFastScrollEnabled(true); dlg.getListView().setFastScrollEnabled(true);

View file

@ -17,8 +17,6 @@ import android.support.annotation.NonNull;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.v7.app.AlertDialog; import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity; import android.support.v7.app.AppCompatActivity;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.style.ForegroundColorSpan; import android.text.style.ForegroundColorSpan;
import android.view.View; import android.view.View;
import android.widget.Toast; import android.widget.Toast;
@ -47,7 +45,6 @@ import net.osmand.plus.base.bottomsheetmenu.SimpleBottomSheetItem;
import net.osmand.plus.base.bottomsheetmenu.simpleitems.DividerHalfItem; import net.osmand.plus.base.bottomsheetmenu.simpleitems.DividerHalfItem;
import net.osmand.plus.base.bottomsheetmenu.simpleitems.ShortDescriptionItem; import net.osmand.plus.base.bottomsheetmenu.simpleitems.ShortDescriptionItem;
import net.osmand.plus.base.bottomsheetmenu.simpleitems.TitleItem; import net.osmand.plus.base.bottomsheetmenu.simpleitems.TitleItem;
import net.osmand.plus.myplaces.FavoritesActivity;
import net.osmand.plus.rastermaps.OsmandRasterMapsPlugin; import net.osmand.plus.rastermaps.OsmandRasterMapsPlugin;
import net.osmand.plus.views.OsmandMapTileView; import net.osmand.plus.views.OsmandMapTileView;
import net.osmand.util.Algorithms; import net.osmand.util.Algorithms;
@ -630,11 +627,11 @@ public class ImportHelper {
File file = new File(gpxFile.path); File file = new File(gpxFile.path);
if (!destinationExists) { if (!destinationExists) {
GPXDatabase.GpxDataItem item = new GPXDatabase.GpxDataItem(file, gpxFile.getColor(0)); GPXDatabase.GpxDataItem item = new GPXDatabase.GpxDataItem(file, gpxFile.getColor(0));
app.getGpxDatabase().add(item); app.getGpxDbHelper().add(item);
} else { } else {
GPXDatabase.GpxDataItem item = app.getGpxDatabase().getItem(file); GPXDatabase.GpxDataItem item = app.getGpxDbHelper().getItem(file);
if (item != null) { if (item != null) {
app.getGpxDatabase().clearAnalysis(item); app.getGpxDbHelper().clearAnalysis(item);
} }
} }

View file

@ -3,6 +3,7 @@ package net.osmand.plus.mapmarkers;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView;
import android.view.View; import android.view.View;
@ -13,8 +14,9 @@ import net.osmand.GPXUtilities;
import net.osmand.GPXUtilities.GPXFile; import net.osmand.GPXUtilities.GPXFile;
import net.osmand.GPXUtilities.GPXTrackAnalysis; import net.osmand.GPXUtilities.GPXTrackAnalysis;
import net.osmand.IndexConstants; import net.osmand.IndexConstants;
import net.osmand.plus.GPXDatabase;
import net.osmand.plus.GPXDatabase.GpxDataItem; import net.osmand.plus.GPXDatabase.GpxDataItem;
import net.osmand.plus.GpxDbHelper;
import net.osmand.plus.GpxDbHelper.GpxDataItemCallback;
import net.osmand.plus.GpxSelectionHelper; import net.osmand.plus.GpxSelectionHelper;
import net.osmand.plus.OsmandApplication; import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R; import net.osmand.plus.R;
@ -24,18 +26,47 @@ import net.osmand.plus.mapmarkers.adapters.TracksGroupsAdapter;
import java.io.File; import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
public class AddTracksGroupBottomSheetDialogFragment extends AddGroupBottomSheetDialogFragment { public class AddTracksGroupBottomSheetDialogFragment extends AddGroupBottomSheetDialogFragment {
private OsmandApplication app;
private GpxDbHelper dbHelper;
private ProcessGpxTask asyncProcessor; private ProcessGpxTask asyncProcessor;
private List<GpxDataItem> gpxList; private List<GpxDataItem> gpxList;
private ProgressBar progressBar;
private RecyclerView recyclerView;
private TextView lookingForTracksText;
private GpxDataItemCallback gpxDataItemCallback = new GpxDataItemCallback() {
@Override @Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { public boolean isCancelled() {
ProcessGpxTask processor = asyncProcessor;
return processor == null || processor.isCancelled();
}
@Override
public void onGpxDataItemReady(GpxDataItem item) {
populateList(item);
if (dbHelper.isRead()) {
onListPopulated();
}
}
};
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState); super.onViewCreated(view, savedInstanceState);
app = requiredMyApplication();
dbHelper = app.getGpxDbHelper();
progressBar = (ProgressBar) mainView.findViewById(R.id.progress_bar);
recyclerView = (RecyclerView) mainView.findViewById(R.id.groups_recycler_view);
lookingForTracksText = (TextView) mainView.findViewById(R.id.looking_for_tracks_text);
asyncProcessor = new ProcessGpxTask(); asyncProcessor = new ProcessGpxTask();
asyncProcessor.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); asyncProcessor.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
} }
@ -82,22 +113,32 @@ public class AddTracksGroupBottomSheetDialogFragment extends AddGroupBottomSheet
dismiss(); dismiss();
} }
private void populateList(GpxDataItem item) {
if (item != null && item.getFile() != null) {
GPXTrackAnalysis analysis = item.getAnalysis();
if (analysis != null && analysis.wptPoints > 0) {
int index = gpxList.indexOf(item);
if (index != -1) {
gpxList.set(index, item);
} else {
gpxList.add(item);
}
}
}
}
private void onListPopulated() {
asyncProcessor = null;
adapter.notifyDataSetChanged();
progressBar.setVisibility(View.GONE);
lookingForTracksText.setVisibility(View.GONE);
recyclerView.setVisibility(View.VISIBLE);
setupHeightAndBackground(getView());
}
@SuppressLint("StaticFieldLeak") @SuppressLint("StaticFieldLeak")
public class ProcessGpxTask extends AsyncTask<Void, GpxDataItem, Void> { private class ProcessGpxTask extends AsyncTask<Void, GpxDataItem, Void> {
private OsmandApplication app = getMyApplication();
private Map<File, GpxDataItem> processedDataFiles = new HashMap<>();
private GPXDatabase db = app.getGpxDatabase();
private ProgressBar progressBar = (ProgressBar) mainView.findViewById(R.id.progress_bar);
private RecyclerView recyclerView = (RecyclerView) mainView.findViewById(R.id.groups_recycler_view);
private TextView lookingForTracksText = (TextView) mainView.findViewById(R.id.looking_for_tracks_text);
ProcessGpxTask() {
List<GpxDataItem> dataItems = db.getItems();
for (GpxDataItem item : dataItems) {
processedDataFiles.put(item.getFile(), item);
}
}
@Override @Override
protected void onPreExecute() { protected void onPreExecute() {
@ -131,25 +172,8 @@ public class AddTracksGroupBottomSheetDialogFragment extends AddGroupBottomSheet
gpxFile.getName() : gpxSubfolder + "/" + gpxFile.getName(); gpxFile.getName() : gpxSubfolder + "/" + gpxFile.getName();
processGPXFolder(gpxFile, sub); processGPXFolder(gpxFile, sub);
} else if (gpxFile.isFile() && gpxFile.getName().toLowerCase().endsWith(".gpx")) { } else if (gpxFile.isFile() && gpxFile.getName().toLowerCase().endsWith(".gpx")) {
GpxDataItem item = processedDataFiles.get(gpxFile); GpxDataItem item = dbHelper.getItem(gpxFile, gpxDataItemCallback);
GPXTrackAnalysis itemAnalysis = item != null ? item.getAnalysis() : null; publishProgress(item);
if (item == null
|| item.getFileLastModifiedTime() != gpxFile.lastModified()
|| itemAnalysis == null
|| itemAnalysis.wptCategoryNames == null) {
GPXFile f = GPXUtilities.loadGPXFile(gpxFile);
GPXTrackAnalysis analysis = f.getAnalysis(gpxFile.lastModified());
if (item == null) {
item = new GpxDataItem(gpxFile, analysis);
db.add(item);
} else {
db.updateAnalysis(item, analysis);
}
}
processedDataFiles.put(gpxFile, item);
if (itemAnalysis != null && itemAnalysis.wptPoints > 0) {
gpxList.add(item);
}
} }
if (isCancelled()) { if (isCancelled()) {
break; break;
@ -157,14 +181,19 @@ public class AddTracksGroupBottomSheetDialogFragment extends AddGroupBottomSheet
} }
} }
@Override
protected void onProgressUpdate(GpxDataItem... items) {
GpxDataItem item = items[0];
if (item != null) {
populateList(item);
}
}
@Override @Override
protected void onPostExecute(Void aVoid) { protected void onPostExecute(Void aVoid) {
asyncProcessor = null; if (dbHelper.isRead()) {
adapter.notifyDataSetChanged(); onListPopulated();
progressBar.setVisibility(View.GONE); }
lookingForTracksText.setVisibility(View.GONE);
recyclerView.setVisibility(View.VISIBLE);
setupHeightAndBackground(getView());
} }
} }
} }

View file

@ -167,7 +167,7 @@ public class DashTrackFragment extends DashBaseFragment {
info.subfolder = ""; info.subfolder = "";
info.file = f; info.file = f;
View v = inflater.inflate(R.layout.dash_gpx_track_item, null, false); View v = inflater.inflate(R.layout.dash_gpx_track_item, null, false);
AvailableGPXFragment.updateGpxInfoView(v, info, app, true); AvailableGPXFragment.updateGpxInfoView(v, info, app, true, null);
v.setOnClickListener(new View.OnClickListener() { v.setOnClickListener(new View.OnClickListener() {
@Override @Override
@ -259,7 +259,7 @@ public class DashTrackFragment extends DashBaseFragment {
AvailableGPXFragment.GpxInfo info = new AvailableGPXFragment.GpxInfo(); AvailableGPXFragment.GpxInfo info = new AvailableGPXFragment.GpxInfo();
info.subfolder = ""; info.subfolder = "";
info.file = f; info.file = f;
AvailableGPXFragment.updateGpxInfoView(pView, info, app, true); AvailableGPXFragment.updateGpxInfoView(pView, info, app, true, null);
updateShowOnMap(app, f, v, showOnMap); updateShowOnMap(app, f, v, showOnMap);
} }
}); });

View file

@ -55,12 +55,13 @@ import net.osmand.data.PointDescription;
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;
import net.osmand.plus.GPXDatabase.GpxDataItem; import net.osmand.plus.GPXDatabase.GpxDataItem;
import net.osmand.plus.GpxDbHelper.GpxDataItemCallback;
import net.osmand.plus.GpxSelectionHelper; import net.osmand.plus.GpxSelectionHelper;
import net.osmand.plus.GpxSelectionHelper.GpxDisplayGroup; import net.osmand.plus.GpxSelectionHelper.GpxDisplayGroup;
import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem; import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem;
import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile; import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile;
import net.osmand.plus.OsmAndConstants;
import net.osmand.plus.OsmAndFormatter; import net.osmand.plus.OsmAndFormatter;
import net.osmand.plus.OsmandApplication; import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandPlugin; import net.osmand.plus.OsmandPlugin;
@ -92,7 +93,6 @@ import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.Date; import java.util.Date;
import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
@ -117,7 +117,6 @@ public class AvailableGPXFragment extends OsmandExpandableListFragment implement
private Set<Integer> selectedGroups = new LinkedHashSet<>(); private Set<Integer> selectedGroups = new LinkedHashSet<>();
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;
@ -193,8 +192,6 @@ public class AvailableGPXFragment extends OsmandExpandableListFragment implement
allGpxAdapter.refreshSelected(); allGpxAdapter.refreshSelected();
allGpxAdapter.notifyDataSetChanged(); allGpxAdapter.notifyDataSetChanged();
} }
asyncProcessor = new ProcessGpxTask();
asyncProcessor.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
} }
updateCurrentTrack(); updateCurrentTrack();
@ -210,10 +207,6 @@ public class AvailableGPXFragment extends OsmandExpandableListFragment implement
if (operationTask != null) { if (operationTask != null) {
operationTask.cancel(true); operationTask.cancel(true);
} }
if (asyncProcessor != null) {
asyncProcessor.cancel(false);
asyncProcessor = null;
}
if (actionMode != null) { if (actionMode != null) {
actionMode.finish(); actionMode.finish();
} }
@ -410,10 +403,6 @@ public class AvailableGPXFragment extends OsmandExpandableListFragment implement
public void reloadTracks() { public void reloadTracks() {
asyncLoader = new LoadGpxTask(); asyncLoader = new LoadGpxTask();
asyncLoader.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, getActivity()); asyncLoader.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, getActivity());
if (asyncProcessor == null) {
asyncProcessor = new ProcessGpxTask();
asyncProcessor.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
} }
@Override @Override
@ -830,7 +819,7 @@ public class AvailableGPXFragment extends OsmandExpandableListFragment implement
} else if (destFolder.mkdirs()) { } else if (destFolder.mkdirs()) {
File dest = new File(destFolder, info.fileName); File dest = new File(destFolder, info.fileName);
if (info.file.renameTo(dest)) { if (info.file.renameTo(dest)) {
app.getGpxDatabase().rename(info.file, dest); app.getGpxDbHelper().rename(info.file, dest);
asyncLoader = new LoadGpxTask(); asyncLoader = new LoadGpxTask();
asyncLoader.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, getActivity()); asyncLoader.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, getActivity());
} else { } else {
@ -853,7 +842,7 @@ public class AvailableGPXFragment extends OsmandExpandableListFragment implement
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); app.getGpxDbHelper().rename(info.file, dest);
asyncLoader = new LoadGpxTask(); asyncLoader = new LoadGpxTask();
asyncLoader.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, getActivity()); asyncLoader.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, getActivity());
} else { } else {
@ -994,6 +983,37 @@ public class AvailableGPXFragment extends OsmandExpandableListFragment implement
int corruptedColor; int corruptedColor;
private SearchFilter filter; private SearchFilter filter;
private GpxInfoViewCallback updateGpxCallback = new GpxInfoViewCallback() {
private static final int UPDATE_GPX_ITEM_MSG_ID = OsmAndConstants.UI_HANDLER_LOCATION_SERVICE + 5;
private static final long MIN_UPDATE_INTERVAL = 500;
private long lastUpdateTime;
private Runnable updateItemsProc = new Runnable() {
@Override
public void run() {
if (updateEnable) {
lastUpdateTime = System.currentTimeMillis();
allGpxAdapter.notifyDataSetChanged();
}
}
};
@Override
public boolean isCancelled() {
return !updateEnable;
}
@Override
public void onGpxDataItemChanged(GpxDataItem item) {
if (System.currentTimeMillis() - lastUpdateTime > MIN_UPDATE_INTERVAL) {
updateItemsProc.run();
}
app.runMessageInUIThreadAndCancelPrevious(UPDATE_GPX_ITEM_MSG_ID, updateItemsProc, MIN_UPDATE_INTERVAL);
}
};
public GpxIndexesAdapter(Context ctx) { public GpxIndexesAdapter(Context ctx) {
warningColor = ContextCompat.getColor(ctx, R.color.color_warning); warningColor = ContextCompat.getColor(ctx, R.color.color_warning);
TypedArray ta = ctx.getTheme().obtainStyledAttributes(new int[]{android.R.attr.textColorPrimary}); TypedArray ta = ctx.getTheme().obtainStyledAttributes(new int[]{android.R.attr.textColorPrimary});
@ -1102,7 +1122,7 @@ public class AvailableGPXFragment extends OsmandExpandableListFragment implement
LayoutInflater inflater = getActivity().getLayoutInflater(); LayoutInflater inflater = getActivity().getLayoutInflater();
v = inflater.inflate(R.layout.dash_gpx_track_item, parent, false); v = inflater.inflate(R.layout.dash_gpx_track_item, parent, false);
} }
updateGpxInfoView(v, child, app, false); updateGpxInfoView(v, child, app, false, updateGpxCallback);
ImageView icon = (ImageView) v.findViewById(R.id.icon); ImageView icon = (ImageView) v.findViewById(R.id.icon);
ImageButton options = (ImageButton) v.findViewById(R.id.options); ImageButton options = (ImageButton) v.findViewById(R.id.options);
@ -1409,7 +1429,7 @@ public class AvailableGPXFragment extends OsmandExpandableListFragment implement
}); });
GPXTrackAnalysis analysis; GPXTrackAnalysis analysis;
if ((analysis = getGpxTrackAnalysis(gpxInfo, app)) != null) { if ((analysis = getGpxTrackAnalysis(gpxInfo, app, null)) != null) {
if (analysis.totalDistance != 0 && !gpxInfo.currentlyRecordingTrack) { if (analysis.totalDistance != 0 && !gpxInfo.currentlyRecordingTrack) {
item = optionsMenu.getMenu().add(R.string.analyze_on_map).setIcon(iconsCache.getThemedIcon(R.drawable.ic_action_info_dark)); item = optionsMenu.getMenu().add(R.string.analyze_on_map).setIcon(iconsCache.getThemedIcon(R.drawable.ic_action_info_dark));
item.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { item.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
@ -1439,7 +1459,7 @@ public class AvailableGPXFragment extends OsmandExpandableListFragment implement
LocalIndexesFragment.renameFile(getActivity(), gpxInfo.file, new RenameCallback() { LocalIndexesFragment.renameFile(getActivity(), gpxInfo.file, new RenameCallback() {
@Override @Override
public void renamedTo(File file) { public void renamedTo(File file) {
app.getGpxDatabase().rename(gpxInfo.file, file); app.getGpxDbHelper().rename(gpxInfo.file, file);
asyncLoader = new LoadGpxTask(); asyncLoader = new LoadGpxTask();
asyncLoader.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, getActivity()); asyncLoader.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, getActivity());
} }
@ -1508,7 +1528,7 @@ public class AvailableGPXFragment extends OsmandExpandableListFragment implement
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); app.getGpxDbHelper().remove(info.file);
total++; total++;
if (successfull) { if (successfull) {
count++; count++;
@ -1591,80 +1611,6 @@ public class AvailableGPXFragment extends OsmandExpandableListFragment implement
} }
} }
public class ProcessGpxTask extends AsyncTask<Void, GpxDataItem, Void> {
private Map<File, GpxDataItem> processedDataFiles = new HashMap<>();
private GPXDatabase db = app.getGpxDatabase();
ProcessGpxTask() {
List<GpxDataItem> dataItems = db.getItems();
for (GpxDataItem item : dataItems) {
processedDataFiles.put(item.getFile(), item);
}
}
@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")) {
GpxDataItem item = processedDataFiles.get(gpxFile);
GPXTrackAnalysis itemAnalysis = item != null ? item.getAnalysis() : null;
if (item == null
|| item.getFileLastModifiedTime() != gpxFile.lastModified()
|| itemAnalysis == null
|| itemAnalysis.wptCategoryNames == null) {
GPXFile f = GPXUtilities.loadGPXFile(gpxFile);
GPXTrackAnalysis analysis = f.getAnalysis(gpxFile.lastModified());
if (item == null) {
item = new GpxDataItem(gpxFile, analysis);
db.add(item);
} else {
db.updateAnalysis(item, analysis);
}
}
processedDataFiles.put(gpxFile, item);
publishProgress(item);
}
if (isCancelled()) {
break;
}
}
}
@Override
protected void onProgressUpdate(GpxDataItem... items) {
allGpxAdapter.notifyDataSetChanged();
}
@Override
protected void onPostExecute(Void aVoid) {
asyncProcessor = null;
listView.setEmptyView(emptyView);
}
}
private class SearchFilter extends Filter { private class SearchFilter extends Filter {
@Override @Override
@ -1819,7 +1765,14 @@ public class AvailableGPXFragment extends OsmandExpandableListFragment implement
} }
} }
public static void updateGpxInfoView(View v, GpxInfo child, OsmandApplication app, boolean isDashItem) { public interface GpxInfoViewCallback {
boolean isCancelled();
void onGpxDataItemChanged(GpxDataItem item);
}
public static void updateGpxInfoView(View v, GpxInfo child, OsmandApplication app, boolean isDashItem, @Nullable GpxInfoViewCallback callback) {
TextView viewName = ((TextView) v.findViewById(R.id.name)); TextView viewName = ((TextView) v.findViewById(R.id.name));
if (!isDashItem) { if (!isDashItem) {
v.findViewById(R.id.divider_list).setVisibility(View.VISIBLE); v.findViewById(R.id.divider_list).setVisibility(View.VISIBLE);
@ -1843,7 +1796,7 @@ public class AvailableGPXFragment extends OsmandExpandableListFragment implement
if (getSelectedGpxFile(child, app) != null) { if (getSelectedGpxFile(child, app) != null) {
icon.setImageDrawable(app.getUIUtilities().getIcon(R.drawable.ic_action_polygom_dark, R.color.color_distance)); icon.setImageDrawable(app.getUIUtilities().getIcon(R.drawable.ic_action_polygom_dark, R.color.color_distance));
} }
GPXTrackAnalysis analysis = getGpxTrackAnalysis(child, app); GPXTrackAnalysis analysis = getGpxTrackAnalysis(child, app, callback);
boolean sectionRead = analysis == null; boolean sectionRead = analysis == null;
if (sectionRead) { if (sectionRead) {
v.findViewById(R.id.read_section).setVisibility(View.GONE); v.findViewById(R.id.read_section).setVisibility(View.GONE);
@ -1911,15 +1864,29 @@ public class AvailableGPXFragment extends OsmandExpandableListFragment implement
} }
@Nullable @Nullable
private static GPXTrackAnalysis getGpxTrackAnalysis(GpxInfo gpxInfo, OsmandApplication app) { private static GPXTrackAnalysis getGpxTrackAnalysis(GpxInfo gpxInfo, OsmandApplication app, @Nullable final GpxInfoViewCallback callback) {
SelectedGpxFile sgpx = getSelectedGpxFile(gpxInfo, app); SelectedGpxFile sgpx = getSelectedGpxFile(gpxInfo, app);
GPXTrackAnalysis analysis = null; GPXTrackAnalysis analysis = null;
if (sgpx != null) { if (sgpx != null) {
analysis = sgpx.getTrackAnalysis(); analysis = sgpx.getTrackAnalysis();
} else if (gpxInfo.currentlyRecordingTrack) { } else if (gpxInfo.currentlyRecordingTrack) {
analysis = app.getSavingTrackHelper().getCurrentTrack().getTrackAnalysis(); analysis = app.getSavingTrackHelper().getCurrentTrack().getTrackAnalysis();
} else { } else if (gpxInfo.file != null) {
GpxDataItem dataItem = gpxInfo.file == null ? null : app.getGpxDatabase().getItem(gpxInfo.file); GpxDataItemCallback analyserCallback = null;
if (callback != null) {
analyserCallback = new GpxDataItemCallback() {
@Override
public boolean isCancelled() {
return callback.isCancelled();
}
@Override
public void onGpxDataItemReady(GpxDataItem item) {
callback.onGpxDataItemChanged(item);
}
};
}
GpxDataItem dataItem = app.getGpxDbHelper().getItem(gpxInfo.file, analyserCallback);
if (dataItem != null) { if (dataItem != null) {
analysis = dataItem.getAnalysis(); analysis = dataItem.getAnalysis();
} }

View file

@ -381,12 +381,12 @@ public class TrackActivityFragmentAdapter implements TrackBitmapDrawerListener {
if (clr != 0 && sf.getModifiableGpxFile() != null) { if (clr != 0 && sf.getModifiableGpxFile() != null) {
sf.getModifiableGpxFile().setColor(clr); sf.getModifiableGpxFile().setColor(clr);
if (getGpxDataItem() != null) { if (getGpxDataItem() != null) {
app.getGpxDatabase().updateColor(getGpxDataItem(), clr); app.getGpxDbHelper().updateColor(getGpxDataItem(), clr);
} }
} }
} }
} else if (getGpxDataItem() != null) { } else if (getGpxDataItem() != null) {
app.getGpxDatabase().updateColor(getGpxDataItem(), clr); app.getGpxDbHelper().updateColor(getGpxDataItem(), clr);
} }
if (gpx != null && gpx.showCurrentTrack) { if (gpx != null && gpx.showCurrentTrack) {
app.getSettings().CURRENT_TRACK_COLOR.set(clr); app.getSettings().CURRENT_TRACK_COLOR.set(clr);
@ -846,7 +846,7 @@ public class TrackActivityFragmentAdapter implements TrackBitmapDrawerListener {
} }
GpxDataItem item = getGpxDataItem(); GpxDataItem item = getGpxDataItem();
if (item != null) { if (item != null) {
app.getGpxDatabase().updateSplit(item, splitType, splitInterval); app.getGpxDbHelper().updateSplit(item, splitType, splitInterval);
} }
} }

View file

@ -10,7 +10,6 @@ import android.widget.ImageView;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.TextView; import android.widget.TextView;
import net.osmand.AndroidUtils;
import net.osmand.GPXUtilities.GPXFile; import net.osmand.GPXUtilities.GPXFile;
import net.osmand.plus.GPXDatabase.GpxDataItem; import net.osmand.plus.GPXDatabase.GpxDataItem;
import net.osmand.plus.R; import net.osmand.plus.R;
@ -28,7 +27,6 @@ public class TracksCard extends BaseCard {
private List<GPXFile> gpxFiles; private List<GPXFile> gpxFiles;
private boolean showLimited = true; private boolean showLimited = true;
private List<GpxDataItem> dataItems;
private static class GpxItem { private static class GpxItem {
String title; String title;
@ -45,7 +43,6 @@ public class TracksCard extends BaseCard {
public TracksCard(MapActivity mapActivity, List<GPXFile> gpxFiles) { public TracksCard(MapActivity mapActivity, List<GPXFile> gpxFiles) {
super(mapActivity); super(mapActivity);
this.gpxFiles = gpxFiles; this.gpxFiles = gpxFiles;
this.dataItems = app.getGpxDatabase().getItems();
} }
@Override @Override
@ -54,12 +51,7 @@ public class TracksCard extends BaseCard {
} }
private GpxDataItem getDataItem(GPXInfo info) { private GpxDataItem getDataItem(GPXInfo info) {
for (GpxDataItem item : dataItems) { return app.getGpxDbHelper().getItem(new File(info.getFileName()));
if (item.getFile().getAbsolutePath().endsWith(info.getFileName())) {
return item;
}
}
return null;
} }
@SuppressLint("DefaultLocale") @SuppressLint("DefaultLocale")