diff --git a/DataExtractionOSM/src/net/osmand/IProgress.java b/DataExtractionOSM/src/net/osmand/IProgress.java
index 68cd736ee5..3f349573ef 100644
--- a/DataExtractionOSM/src/net/osmand/IProgress.java
+++ b/DataExtractionOSM/src/net/osmand/IProgress.java
@@ -26,5 +26,32 @@ public interface IProgress {
public boolean isIndeterminate();
public boolean isInterrupted();
+
+ public IProgress EMPTY_PROGRESS = new IProgress() {
+
+ @Override
+ public void startWork(int work) {}
+
+ @Override
+ public void startTask(String taskName, int work) {}
+
+ @Override
+ public void setGeneralProgress(String genProgress) {}
+
+ @Override
+ public void remaining(int remainingWork) {}
+
+ @Override
+ public void progress(int deltaWork) {}
+
+ @Override
+ public boolean isInterrupted() {return false;}
+
+ @Override
+ public boolean isIndeterminate() {return false;}
+
+ @Override
+ public void finishTask() {}
+ };
}
diff --git a/DataExtractionOSM/src/net/osmand/binary/BinaryMapIndexReader.java b/DataExtractionOSM/src/net/osmand/binary/BinaryMapIndexReader.java
index f9896d0f27..0f52483af5 100644
--- a/DataExtractionOSM/src/net/osmand/binary/BinaryMapIndexReader.java
+++ b/DataExtractionOSM/src/net/osmand/binary/BinaryMapIndexReader.java
@@ -67,7 +67,7 @@ public class BinaryMapIndexReader {
}
init();
}
-
+
private void init() throws IOException {
boolean initCorrectly = false;
while(true){
diff --git a/OsmAnd/AndroidManifest.xml b/OsmAnd/AndroidManifest.xml
index 5350b6a8db..0db446109b 100644
--- a/OsmAnd/AndroidManifest.xml
+++ b/OsmAnd/AndroidManifest.xml
@@ -48,6 +48,7 @@
+
diff --git a/OsmAnd/res/layout/local_index.xml b/OsmAnd/res/layout/local_index.xml
new file mode 100644
index 0000000000..53f78d3671
--- /dev/null
+++ b/OsmAnd/res/layout/local_index.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OsmAnd/res/layout/local_index_list_item.xml b/OsmAnd/res/layout/local_index_list_item.xml
new file mode 100644
index 0000000000..f48f117879
--- /dev/null
+++ b/OsmAnd/res/layout/local_index_list_item.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/OsmAnd/res/layout/local_index_list_item_category.xml b/OsmAnd/res/layout/local_index_list_item_category.xml
new file mode 100644
index 0000000000..2cb1120acf
--- /dev/null
+++ b/OsmAnd/res/layout/local_index_list_item_category.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
diff --git a/OsmAnd/res/values/strings.xml b/OsmAnd/res/values/strings.xml
index a231da1c4b..7f7ca8b470 100644
--- a/OsmAnd/res/values/strings.xml
+++ b/OsmAnd/res/values/strings.xml
@@ -1,7 +1,33 @@
- TTS Voice
+ Subtracks : %1$d\nTotal Points : %2$d\nWay points : %3$d
+ Installed
+ %1$d items of %2$d were succesfully backuped.
+ %1$d items of %2$d were succesfully deleted.
+ %1$d items of %2$d were succesfully restored.
+ No items to %1$s
+ You are about to %1$s %2$s items. Are you sure?
+ Offline data available on the phone.\n You can download new or backup and delete existing data.
+ Restore
+ Backup
+ Delete
+ Reload
+ Download
+ Tile data: %1$s \nMinimum zoom : %2$d\nMaximum zoom : %3$d\nDownloadable : %4$s \nZooms downloaded : %5$s
+ POI data
+ Address data
+ Transport data
+ Map data
+ items
+ Backup
+ TTS data
+ Voice data
+ GPX data
+ Tile data
+ Map data
+ POI data
+ TTS Voice
New Search
Select text size for names on the map
Text size
diff --git a/OsmAnd/res/xml/settings_pref.xml b/OsmAnd/res/xml/settings_pref.xml
index 6d44529d50..20007fabaf 100644
--- a/OsmAnd/res/xml/settings_pref.xml
+++ b/OsmAnd/res/xml/settings_pref.xml
@@ -30,10 +30,7 @@
-
-
-
-
+
diff --git a/OsmAnd/src/net/osmand/plus/OsmandSettings.java b/OsmAnd/src/net/osmand/plus/OsmandSettings.java
index dd99bb6b4d..5dc142d6bc 100644
--- a/OsmAnd/src/net/osmand/plus/OsmandSettings.java
+++ b/OsmAnd/src/net/osmand/plus/OsmandSettings.java
@@ -452,8 +452,7 @@ public class OsmandSettings {
// this value string is synchronized with settings_pref.xml preference name
public static final String SAVE_CURRENT_TRACK = "save_current_track"; //$NON-NLS-1$
- public static final String RELOAD_INDEXES = "reload_indexes"; //$NON-NLS-1$
- public static final String DOWNLOAD_INDEXES = "download_indexes"; //$NON-NLS-1$
+ public static final String LOCAL_INDEXES = "local_indexes"; //$NON-NLS-1$
// this value string is synchronized with settings_pref.xml preference name
public final CommonPreference SAVE_TRACK_TO_GPX = new BooleanPreference("save_track_to_gpx", false, false);
diff --git a/OsmAnd/src/net/osmand/plus/ResourceManager.java b/OsmAnd/src/net/osmand/plus/ResourceManager.java
index dbd4833a38..57a7fbc403 100644
--- a/OsmAnd/src/net/osmand/plus/ResourceManager.java
+++ b/OsmAnd/src/net/osmand/plus/ResourceManager.java
@@ -60,7 +60,9 @@ public class ResourceManager {
public static final String APP_DIR = "osmand/"; //$NON-NLS-1$
public static final String POI_PATH = APP_DIR + IndexConstants.POI_INDEX_DIR;
public static final String VOICE_PATH = APP_DIR + IndexConstants.VOICE_INDEX_DIR;
+ public static final String GPX_PATH = APP_DIR + "tracks";
public static final String MAPS_PATH = APP_DIR;
+ public static final String BACKUP_PATH = APP_DIR + "backup/";
public static final String TILES_PATH = APP_DIR+"tiles/"; //$NON-NLS-1$
public static final String TEMP_SOURCE_TO_LOAD = "temp"; //$NON-NLS-1$
public static final String VECTOR_MAP = "#vector_map"; //$NON-NLS-1$
@@ -69,6 +71,7 @@ public class ResourceManager {
private static final Log log = LogUtil.getLog(ResourceManager.class);
+
protected static ResourceManager manager = null;
// it is not good investigated but no more than 64 (satellite images)
diff --git a/OsmAnd/src/net/osmand/plus/SQLiteTileSource.java b/OsmAnd/src/net/osmand/plus/SQLiteTileSource.java
index 22ce3f4924..569cf167c4 100644
--- a/OsmAnd/src/net/osmand/plus/SQLiteTileSource.java
+++ b/OsmAnd/src/net/osmand/plus/SQLiteTileSource.java
@@ -150,6 +150,21 @@ public class SQLiteTileSource implements ITileSource {
return db;
}
+ public boolean exists(int zoom) {
+ SQLiteDatabase db = getDatabase();
+ if(db == null){
+ return false;
+ }
+ Cursor cursor = db.rawQuery("SELECT 1 FROM tiles WHERE z = ?", new String[] {(17 - zoom)+""}); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$//$NON-NLS-4$
+ try {
+ boolean e = cursor.moveToFirst();
+ cursor.close();
+ return e;
+ } catch (SQLiteDiskIOException e) {
+ return false;
+ }
+ }
+
public boolean exists(int x, int y, int zoom) {
SQLiteDatabase db = getDatabase();
if(db == null){
diff --git a/OsmAnd/src/net/osmand/plus/activities/LocalIndexHelper.java b/OsmAnd/src/net/osmand/plus/activities/LocalIndexHelper.java
new file mode 100644
index 0000000000..b96f6bc5d7
--- /dev/null
+++ b/OsmAnd/src/net/osmand/plus/activities/LocalIndexHelper.java
@@ -0,0 +1,436 @@
+package net.osmand.plus.activities;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+
+import net.osmand.GPXUtilities;
+import net.osmand.GPXUtilities.GPXFileResult;
+import net.osmand.binary.BinaryIndexPart;
+import net.osmand.binary.BinaryMapIndexReader;
+import net.osmand.binary.BinaryMapAddressReaderAdapter.AddressRegion;
+import net.osmand.binary.BinaryMapIndexReader.MapIndex;
+import net.osmand.binary.BinaryMapIndexReader.MapRoot;
+import net.osmand.binary.BinaryMapTransportReaderAdapter.TransportIndex;
+import net.osmand.data.IndexConstants;
+import net.osmand.map.TileSourceManager;
+import net.osmand.map.TileSourceManager.TileSourceTemplate;
+import net.osmand.osm.MapUtils;
+import net.osmand.plus.OsmandSettings;
+import net.osmand.plus.R;
+import net.osmand.plus.ResourceManager;
+import net.osmand.plus.SQLiteTileSource;
+import net.osmand.plus.activities.LocalIndexesActivity.LoadLocalIndexTask;
+import net.osmand.plus.voice.MediaCommandPlayerImpl;
+import net.osmand.plus.voice.TTSCommandPlayerImpl;
+import android.content.Context;
+import android.database.sqlite.SQLiteDatabase;
+import android.os.Build;
+
+public class LocalIndexHelper {
+
+ private final OsmandApplication app;
+
+ private MessageFormat dateformat = new MessageFormat("{0,date,dd.MM.yyyy}", Locale.US);
+
+ public LocalIndexHelper(OsmandApplication app){
+ this.app = app;
+ }
+
+ public List getAllLocalIndexData(LoadLocalIndexTask loadTask){
+ return getLocalIndexData(null, loadTask);
+ }
+
+ public String getInstalledDate(File f){
+ return app.getString(R.string.local_index_installed) + " : " + dateformat.format(new Object[]{new Date(f.lastModified())});
+ }
+
+ @SuppressWarnings("unchecked")
+ public void updateDescription(LocalIndexInfo info){
+ File f = new File(info.getPathToData());
+ if(info.getType() == LocalIndexType.MAP_DATA){
+ updateObfFileInformation(info, f);
+ info.setDescription(info.getDescription() + getInstalledDate(f));
+ } else if(info.getType() == LocalIndexType.POI_DATA){
+ info.setDescription(getInstalledDate(f));
+ } else if(info.getType() == LocalIndexType.GPX_DATA){
+ GPXFileResult result = GPXUtilities.loadGPXFile(app, f);
+ if(result.error != null){
+ info.setCorrupted(true);
+ info.setDescription(result.error);
+ } else {
+ int points = 0;
+ for(int i =0; i< result.locations.size() ; i++){
+ points += result.locations.get(i).size();
+ }
+ info.setDescription(app.getString(R.string.local_index_gpx_info, result.locations.size(), points,
+ result.wayPoints.size()));
+ }
+ } else if(info.getType() == LocalIndexType.VOICE_DATA){
+ info.setDescription(getInstalledDate(f));
+ } else if(info.getType() == LocalIndexType.TTS_VOICE_DATA){
+ info.setDescription(getInstalledDate(f));
+ } else if(info.getType() == LocalIndexType.TILES_DATA){
+ if(f.isDirectory() && TileSourceManager.isTileSourceMetaInfoExist(f)){
+ TileSourceTemplate template = TileSourceManager.createTileSourceTemplate(new File(info.getPathToData()));
+ Set zooms = new TreeSet();
+ for(String s : f.list()){
+ try {
+ zooms.add(Integer.parseInt(s));
+ } catch (NumberFormatException e) {
+ }
+ }
+
+ String descr = app.getString(R.string.local_index_tile_data,
+ template.getName(), template.getMinimumZoomSupported(), template.getMaximumZoomSupported(),
+ template.getUrlTemplate() != null, zooms.toString());
+ info.setDescription(descr);
+ } else if(f.isFile() && f.getName().endsWith(SQLiteTileSource.EXT)){
+ SQLiteTileSource template = new SQLiteTileSource(f, Collections.EMPTY_LIST);
+ Set zooms = new TreeSet();
+ for(int i=1; i<22; i++){
+ if(template.exists(i)){
+ zooms.add(i);
+ }
+ }
+ String descr = app.getString(R.string.local_index_tile_data,
+ template.getName(), template.getMinimumZoomSupported(), template.getMaximumZoomSupported(),
+ template.couldBeDownloadedFromInternet(), zooms.toString());
+ info.setDescription(descr);
+ }
+ }
+ }
+
+ public List getLocalIndexData(LocalIndexType type, LoadLocalIndexTask loadTask){
+ OsmandSettings settings = OsmandSettings.getOsmandSettings(app.getApplicationContext());
+ Map loadedMaps = app.getResourceManager().getIndexFileNames();
+ List result = new ArrayList();
+
+ loadVoiceData(settings.extendOsmandPath(ResourceManager.VOICE_PATH), result, false, loadTask);
+ loadObfData(settings.extendOsmandPath(ResourceManager.MAPS_PATH), result, false, loadTask, loadedMaps);
+ loadPoiData(settings.extendOsmandPath(ResourceManager.POI_PATH), result, false, loadTask);
+ loadGPXData(settings.extendOsmandPath(ResourceManager.GPX_PATH), result, false, loadTask);
+ loadTilesData(settings.extendOsmandPath(ResourceManager.TILES_PATH), result, false, loadTask);
+
+ loadVoiceData(settings.extendOsmandPath(ResourceManager.BACKUP_PATH), result, true, loadTask);
+ loadObfData(settings.extendOsmandPath(ResourceManager.BACKUP_PATH), result, true, loadTask, loadedMaps);
+ loadPoiData(settings.extendOsmandPath(ResourceManager.BACKUP_PATH), result, true, loadTask);
+ loadGPXData(settings.extendOsmandPath(ResourceManager.BACKUP_PATH), result, true, loadTask);
+ loadTilesData(settings.extendOsmandPath(ResourceManager.BACKUP_PATH), result, false, loadTask);
+
+ return result;
+ }
+
+
+
+ private void loadVoiceData(File voiceDir, List result, boolean backup, LoadLocalIndexTask loadTask) {
+ if (voiceDir.canRead()) {
+ for (File voiceF : voiceDir.listFiles()) {
+ if (voiceF.isDirectory()) {
+ LocalIndexInfo info = null;
+ if (MediaCommandPlayerImpl.isMyData(voiceF)) {
+ info = new LocalIndexInfo(LocalIndexType.VOICE_DATA, voiceF, backup);
+ } else if (Integer.parseInt(Build.VERSION.SDK) >= 4) {
+ if (TTSCommandPlayerImpl.isMyData(voiceF)) {
+ info = new LocalIndexInfo(LocalIndexType.TTS_VOICE_DATA, voiceF, backup);
+ }
+ }
+ if(info != null){
+ result.add(info);
+ loadTask.loadFile(info);
+ }
+ }
+ }
+ }
+ }
+
+ private void loadTilesData(File tilesPath, List result, boolean backup, LoadLocalIndexTask loadTask) {
+ if (tilesPath.canRead()) {
+ for (File tileFile : tilesPath.listFiles()) {
+ if (tileFile.isFile() && tileFile.getName().endsWith(SQLiteTileSource.EXT)) {
+ LocalIndexInfo info = new LocalIndexInfo(LocalIndexType.TILES_DATA, tileFile, backup);
+ result.add(info);
+ loadTask.loadFile(info);
+ } else if (tileFile.isDirectory()) {
+ LocalIndexInfo info = new LocalIndexInfo(LocalIndexType.TILES_DATA, tileFile, backup);
+
+ if(!TileSourceManager.isTileSourceMetaInfoExist(tileFile)){
+ info.setCorrupted(true);
+ } else {
+ // updateTileSourceInfo(tileFile, info);
+ }
+ result.add(info);
+ loadTask.loadFile(info);
+
+ }
+ }
+ }
+ }
+
+
+ private void loadObfData(File mapPath, List result, boolean backup, LoadLocalIndexTask loadTask, Map loadedMaps) {
+ if (mapPath.canRead()) {
+ for (File mapFile : mapPath.listFiles()) {
+ if (mapFile.isFile() && mapFile.getName().endsWith(IndexConstants.BINARY_MAP_INDEX_EXT)) {
+ LocalIndexInfo info = new LocalIndexInfo(LocalIndexType.MAP_DATA, mapFile, backup);
+ if(loadedMaps.containsKey(mapFile.getName()) && !backup){
+ info.setLoaded(true);
+ }
+ result.add(info);
+ loadTask.loadFile(info);
+ }
+ }
+ }
+ }
+
+ private void loadGPXData(File mapPath, List result, boolean backup, LoadLocalIndexTask loadTask) {
+ if (mapPath.canRead()) {
+ for (File gpxFile : mapPath.listFiles()) {
+ if (gpxFile.isFile() && gpxFile.getName().endsWith(".gpx")) {
+ LocalIndexInfo info = new LocalIndexInfo(LocalIndexType.GPX_DATA, gpxFile, backup);
+ result.add(info);
+ loadTask.loadFile(info);
+ }
+ }
+ }
+ }
+
+ private void loadPoiData(File mapPath, List result, boolean backup, LoadLocalIndexTask loadTask) {
+ if (mapPath.canRead()) {
+ for (File poiFile : mapPath.listFiles()) {
+ if (poiFile.isFile() && poiFile.getName().endsWith(IndexConstants.POI_INDEX_EXT)) {
+ LocalIndexInfo info = new LocalIndexInfo(LocalIndexType.POI_DATA, poiFile, backup);
+ if (!backup) {
+ checkPoiFileVersion(info, poiFile);
+ }
+ result.add(info);
+ loadTask.loadFile(info);
+ }
+ }
+ }
+ }
+
+
+
+ private void checkPoiFileVersion(LocalIndexInfo info, File poiFile) {
+ try {
+ SQLiteDatabase db = SQLiteDatabase.openDatabase(poiFile.getPath(), null, SQLiteDatabase.OPEN_READONLY);
+ int version = db.getVersion();
+ info.setNotSupported(version != IndexConstants.POI_TABLE_VERSION);
+ db.close();
+ } catch(RuntimeException e){
+ info.setCorrupted(true);
+ }
+
+ }
+
+ private MessageFormat format = new MessageFormat("\t {0}, {1} NE \n\t {2}, {3} NE", Locale.US);
+
+ private String formatLatLonBox(int left, int right, int top, int bottom) {
+ double l = MapUtils.get31LongitudeX(left);
+ double r = MapUtils.get31LongitudeX(right);
+ double t = MapUtils.get31LatitudeY(top);
+ double b = MapUtils.get31LatitudeY(bottom);
+ return format.format(new Object[] { l, t, r, b });
+ }
+
+ private void updateObfFileInformation(LocalIndexInfo info, File mapFile) {
+ try {
+ RandomAccessFile mf = new RandomAccessFile(mapFile, "r");
+ BinaryMapIndexReader reader = new BinaryMapIndexReader(mf, false);
+
+ info.setNotSupported(reader.getVersion() != IndexConstants.BINARY_MAP_VERSION);
+ List indexes = reader.getIndexes();
+ StringBuilder builder = new StringBuilder();
+ for(BinaryIndexPart part : indexes){
+ if(part instanceof MapIndex){
+ MapIndex mi = ((MapIndex) part);
+ builder.append(app.getString(R.string.local_index_map_data)).append(": ").
+ append(mi.getName()).append("\n");
+ if(mi.getRoots().size() > 0){
+ MapRoot mapRoot = mi.getRoots().get(0);
+ String box = formatLatLonBox(mapRoot.getLeft(), mapRoot.getRight(), mapRoot.getTop(), mapRoot.getBottom());
+ builder.append(box).append("\n");
+ }
+ } else if(part instanceof TransportIndex){
+ TransportIndex mi = ((TransportIndex) part);
+ int sh = (31 - BinaryMapIndexReader.TRANSPORT_STOP_ZOOM);
+ builder.append(app.getString(R.string.local_index_transport_data)).append(": ").
+ append(mi.getName()).append("\n");
+ String box = formatLatLonBox(mi.getLeft() << sh, mi.getRight() << sh, mi.getTop() << sh, mi.getBottom() << sh);
+ builder.append(box).append("\n");
+ } else if(part instanceof AddressRegion){
+ AddressRegion mi = ((AddressRegion) part);
+ builder.append(app.getString(R.string.local_index_address_data)).append(": ").
+ append(mi.getName()).append("\n");
+ }
+ }
+ info.setDescription(builder.toString());
+ reader.close();
+ } catch (IOException e) {
+ info.setCorrupted(true);
+ }
+
+ }
+
+
+
+ public enum LocalIndexType {
+ VOICE_DATA(R.string.local_indexes_cat_voice),
+ TTS_VOICE_DATA(R.string.local_indexes_cat_tts),
+ TILES_DATA(R.string.local_indexes_cat_tile),
+ GPX_DATA(R.string.local_indexes_cat_gpx),
+ MAP_DATA(R.string.local_indexes_cat_map),
+ POI_DATA(R.string.local_indexes_cat_poi);
+
+ private final int resId;
+
+ private LocalIndexType(int resId){
+ this.resId = resId;
+
+ }
+ public String getHumanString(Context ctx){
+ return ctx.getString(resId);
+ }
+ }
+
+ public static class LocalIndexInfo {
+
+ private LocalIndexType type;
+ private String description = "";
+ private String name;
+
+ private boolean backupedData;
+ private boolean corrupted = false;
+ private boolean notSupported = false;
+ private boolean loaded;
+ private String pathToData;
+ private String fileName;
+ private boolean singleFile;
+ private int kbSize = -1;
+
+ // UI state expanded
+ private boolean expanded;
+
+ public LocalIndexInfo(LocalIndexType type, File f, boolean backuped){
+ pathToData = f.getAbsolutePath();
+ fileName = f.getName();
+ name = formatName(f.getName());
+ this.type = type;
+ singleFile = !f.isDirectory();
+ if(singleFile){
+ kbSize = (int) (f.length() >> 10);
+ }
+ this.backupedData = backuped;
+ }
+
+ private String formatName(String name) {
+ int ext = name.indexOf('.');
+ if(ext != -1){
+ name = name.substring(0, ext);
+ }
+ return name.replace('_', ' ');
+ }
+
+ // Special domain object represents category
+ public LocalIndexInfo(LocalIndexType type, boolean backup){
+ this.type = type;
+ backupedData = backup;
+ }
+
+ public void setCorrupted(boolean corrupted) {
+ this.corrupted = corrupted;
+ if(corrupted){
+ this.loaded = false;
+ }
+ }
+
+ public void setBackupedData(boolean backupedData) {
+ this.backupedData = backupedData;
+ }
+
+ public void setSize(int size) {
+ this.kbSize = size;
+ }
+
+ public boolean isExpanded() {
+ return expanded;
+ }
+
+ public void setExpanded(boolean expanded) {
+ this.expanded = expanded;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public void setLoaded(boolean loaded) {
+ this.loaded = loaded;
+ }
+
+ public void setNotSupported(boolean notSupported) {
+ this.notSupported = notSupported;
+ if(notSupported){
+ this.loaded = false;
+ }
+ }
+
+ public int getSize() {
+ return kbSize;
+ }
+
+ public boolean isNotSupported() {
+ return notSupported;
+ }
+
+
+ public String getName() {
+ return name;
+ }
+
+ public LocalIndexType getType() {
+ return type;
+ }
+
+ public boolean isSingleFile() {
+ return singleFile;
+ }
+
+ public boolean isLoaded() {
+ return loaded;
+ }
+
+ public boolean isCorrupted() {
+ return corrupted;
+ }
+
+ public boolean isBackupedData() {
+ return backupedData;
+ }
+
+ public String getPathToData() {
+ return pathToData;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public String getFileName() {
+ return fileName;
+ }
+
+ }
+
+
+}
diff --git a/OsmAnd/src/net/osmand/plus/activities/LocalIndexesActivity.java b/OsmAnd/src/net/osmand/plus/activities/LocalIndexesActivity.java
new file mode 100644
index 0000000000..ca3690c43f
--- /dev/null
+++ b/OsmAnd/src/net/osmand/plus/activities/LocalIndexesActivity.java
@@ -0,0 +1,666 @@
+package net.osmand.plus.activities;
+
+import java.io.File;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import net.osmand.Algoritms;
+import net.osmand.IProgress;
+import net.osmand.plus.OsmandSettings;
+import net.osmand.plus.R;
+import net.osmand.plus.ResourceManager;
+import net.osmand.plus.activities.LocalIndexHelper.LocalIndexInfo;
+import net.osmand.plus.activities.LocalIndexHelper.LocalIndexType;
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.ExpandableListActivity;
+import android.app.AlertDialog.Builder;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.graphics.Color;
+import android.graphics.Typeface;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.os.AsyncTask.Status;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.Window;
+import android.view.View.OnClickListener;
+import android.widget.BaseExpandableListAdapter;
+import android.widget.Button;
+import android.widget.CheckBox;
+import android.widget.ExpandableListView;
+import android.widget.TextView;
+import android.widget.Toast;
+
+public class LocalIndexesActivity extends ExpandableListActivity {
+
+ private AsyncTask> asyncLoader;
+ private LocalIndexesAdapter listAdapter;
+ private LoadLocalIndexDescriptionTask descriptionLoader;
+ private LocalIndexOperationTask operationTask;
+
+ private boolean selectionMode = false;
+ private Set selectedItems = new LinkedHashSet();
+
+ protected static int DELETE_OPERATION = 1;
+ protected static int BACKUP_OPERATION = 2;
+ protected static int RESTORE_OPERATION = 3;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ requestWindowFeature(Window.FEATURE_NO_TITLE);
+ setContentView(R.layout.local_index);
+
+ LoadLocalIndexTask task = new LoadLocalIndexTask();
+ asyncLoader = task.execute(this);
+ descriptionLoader = new LoadLocalIndexDescriptionTask();
+ listAdapter = new LocalIndexesAdapter();
+ findViewById(R.id.DownloadButton).setOnClickListener(new View.OnClickListener() {
+
+ @Override
+ public void onClick(View v) {
+ startActivity(new Intent(LocalIndexesActivity.this, DownloadIndexActivity.class));
+ }
+ });
+
+ setListAdapter(listAdapter);
+ }
+
+ public class LoadLocalIndexTask extends AsyncTask> {
+ List progress = new ArrayList();
+
+ @Override
+ protected List doInBackground(Activity... params) {
+ LocalIndexHelper helper = new LocalIndexHelper((OsmandApplication) getApplication());
+ progress.clear();
+ return helper.getAllLocalIndexData(this);
+ }
+
+ public void loadFile(LocalIndexInfo loaded) {
+ publishProgress(loaded);
+ }
+
+ @Override
+ protected void onPreExecute() {
+ findViewById(R.id.ProgressBar).setVisibility(View.VISIBLE);
+ }
+
+ @Override
+ protected void onProgressUpdate(LocalIndexInfo... values) {
+ for (LocalIndexInfo v : values) {
+ listAdapter.addLocalIndexInfo(v);
+ }
+ listAdapter.notifyDataSetChanged();
+ }
+
+ @Override
+ protected void onPostExecute(List result) {
+ findViewById(R.id.ProgressBar).setVisibility(View.GONE);
+ }
+
+ }
+
+ public class LocalIndexOperationTask extends AsyncTask {
+
+ private final int operation;
+ private OsmandSettings settings;
+
+ public LocalIndexOperationTask(int operation){
+ this.operation = operation;
+ settings = ((OsmandApplication) getApplication()).getSettings();
+ }
+
+ public File getFileToRestore(LocalIndexInfo i){
+ if(i.isBackupedData()){
+ File parent = new File(i.getPathToData()).getParentFile();
+ if(i.getType() == LocalIndexType.GPX_DATA){
+ parent = settings.extendOsmandPath(ResourceManager.GPX_PATH);
+ } else if(i.getType() == LocalIndexType.MAP_DATA){
+ parent = settings.extendOsmandPath(ResourceManager.MAPS_PATH);
+ } else if(i.getType() == LocalIndexType.POI_DATA){
+ parent = settings.extendOsmandPath(ResourceManager.POI_PATH);
+ } else if(i.getType() == LocalIndexType.TILES_DATA){
+ parent = settings.extendOsmandPath(ResourceManager.TILES_PATH);
+ } else if(i.getType() == LocalIndexType.VOICE_DATA){
+ parent = settings.extendOsmandPath(ResourceManager.VOICE_PATH);
+ } else if(i.getType() == LocalIndexType.TTS_VOICE_DATA){
+ parent = settings.extendOsmandPath(ResourceManager.VOICE_PATH);
+ }
+ return new File(parent, i.getFileName());
+ }
+ return new File(i.getPathToData());
+ }
+
+ private File getFileToBackup(LocalIndexInfo i) {
+ if(!i.isBackupedData()){
+ return new File(settings.extendOsmandPath(ResourceManager.BACKUP_PATH), i.getFileName());
+ }
+ return new File(i.getPathToData());
+ }
+
+ private boolean move(File from, File to){
+ if(!to.getParentFile().exists()){
+ to.getParentFile().mkdirs();
+ }
+ return from.renameTo(to);
+ }
+
+ @Override
+ protected String doInBackground(LocalIndexInfo... params) {
+ int count = 0;
+ int total = 0;
+ for(LocalIndexInfo info : params) {
+ if(!isCancelled()){
+ boolean successfull = false;
+ if(operation == DELETE_OPERATION){
+ File f = new File(info.getPathToData());
+ successfull = Algoritms.removeAllFiles(f);
+ } else if(operation == RESTORE_OPERATION){
+ successfull = move(new File(info.getPathToData()), getFileToRestore(info));
+ if(successfull){
+ info.setBackupedData(false);
+ }
+ } else if(operation == BACKUP_OPERATION){
+ successfull = move(new File(info.getPathToData()), getFileToBackup(info));
+ if(successfull){
+ info.setBackupedData(true);
+ }
+ }
+ total ++;
+ if(successfull){
+ count++;
+ publishProgress(info);
+ }
+ }
+ }
+ if(operation == DELETE_OPERATION){
+ return getString(R.string.local_index_items_deleted, count, total);
+ } else if(operation == BACKUP_OPERATION){
+ return getString(R.string.local_index_items_backuped, count, total);
+ } else if(operation == RESTORE_OPERATION){
+ return getString(R.string.local_index_items_restored, count, total);
+ }
+ return "";
+ }
+
+
+ @Override
+ protected void onProgressUpdate(LocalIndexInfo... values) {
+ if(operation == DELETE_OPERATION){
+ listAdapter.delete(values);
+ } else if(operation == BACKUP_OPERATION){
+ listAdapter.move(values, false);
+ } else if(operation == RESTORE_OPERATION){
+ listAdapter.move(values, true);
+ }
+
+ }
+
+ @Override
+ protected void onPreExecute() {
+ findViewById(R.id.ProgressBar).setVisibility(View.VISIBLE);
+ }
+
+ @Override
+ protected void onPostExecute(String result) {
+ findViewById(R.id.ProgressBar).setVisibility(View.GONE);
+ Toast.makeText(LocalIndexesActivity.this, result, Toast.LENGTH_LONG).show();
+ reloadIndexes();
+ }
+
+ }
+
+ public class LoadLocalIndexDescriptionTask extends AsyncTask {
+
+ @Override
+ protected LocalIndexInfo[] doInBackground(LocalIndexInfo... params) {
+ LocalIndexHelper helper = new LocalIndexHelper((OsmandApplication) getApplication());
+ for (LocalIndexInfo i : params) {
+ helper.updateDescription(i);
+ }
+ return params;
+ }
+
+ @Override
+ protected void onPreExecute() {
+ }
+
+ @Override
+ protected void onProgressUpdate(LocalIndexInfo... values) {
+ listAdapter.notifyDataSetChanged();
+ }
+
+ @Override
+ protected void onPostExecute(LocalIndexInfo[] result) {
+ listAdapter.notifyDataSetChanged();
+ }
+
+ }
+
+ @Override
+ public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
+ LocalIndexInfo item = listAdapter.getChild(groupPosition, childPosition);
+ item.setExpanded(!item.isExpanded());
+ if (item.isExpanded()) {
+ descriptionLoader = new LoadLocalIndexDescriptionTask();
+ descriptionLoader.execute(item);
+ }
+ if(selectionMode){
+ selectedItems.add(item);
+ }
+ listAdapter.notifyDataSetInvalidated();
+ return true;
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ if(operationTask != null){
+ operationTask.cancel(true);
+ }
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ asyncLoader.cancel(true);
+ descriptionLoader.cancel(true);
+ }
+
+
+
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ menu.add(0, R.string.local_index_mi_backup, 0, R.string.local_index_mi_backup);
+ menu.add(0, R.string.local_index_mi_reload, 1, R.string.local_index_mi_reload);
+ menu.add(0, R.string.local_index_mi_delete, 2, R.string.local_index_mi_delete);
+ menu.add(0, R.string.local_index_mi_restore, 3, R.string.local_index_mi_restore);
+ return true;
+ }
+
+ @Override
+ public boolean onPrepareOptionsMenu(Menu menu) {
+ if(operationTask == null || operationTask.getStatus() == Status.FINISHED){
+ menu.setGroupVisible(0, true);
+ } else {
+ menu.setGroupVisible(0, false);
+ }
+ return true;
+ }
+
+ public void doAction(int actionResId){
+ if(actionResId == R.string.local_index_mi_backup){
+ operationTask = new LocalIndexOperationTask(BACKUP_OPERATION);
+ } else if(actionResId == R.string.local_index_mi_delete){
+ operationTask = new LocalIndexOperationTask(DELETE_OPERATION);
+ } else if(actionResId == R.string.local_index_mi_restore){
+ operationTask = new LocalIndexOperationTask(RESTORE_OPERATION);
+ } else {
+ operationTask = null;
+ }
+ if(operationTask != null){
+ operationTask.execute(selectedItems.toArray(new LocalIndexInfo[selectedItems.size()]));
+ }
+ closeSelectionMode();
+ }
+
+ private void openSelectionMode(final int actionResId){
+ final String actionButton = getString(actionResId);
+ if(listAdapter.getGroupCount() == 0){
+ listAdapter.cancelFilter();
+ Toast.makeText(LocalIndexesActivity.this, getString(R.string.local_index_no_items_to_do, actionButton.toLowerCase()), Toast.LENGTH_SHORT).show();
+ return;
+ }
+
+
+ selectionMode = true;
+ selectedItems.clear();
+ Button action = (Button) findViewById(R.id.ActionButton);
+ action.setVisibility(View.VISIBLE);
+ action.setText(actionButton);
+ action.setOnClickListener(new OnClickListener() {
+
+ @Override
+ public void onClick(View v) {
+ if(selectedItems.isEmpty()){
+ Toast.makeText(LocalIndexesActivity.this, getString(R.string.local_index_no_items_to_do, actionButton.toLowerCase()), Toast.LENGTH_SHORT).show();
+ return;
+ }
+
+ Builder builder = new AlertDialog.Builder(LocalIndexesActivity.this);
+ builder.setMessage(getString(R.string.local_index_action_do, actionButton.toLowerCase(), selectedItems.size()));
+ builder.setPositiveButton(actionButton, new DialogInterface.OnClickListener() {
+
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ doAction(actionResId);
+ }
+ });
+ builder.setNegativeButton(R.string.default_buttons_cancel, null);
+ builder.show();
+
+ }
+ });
+ Button cancel = (Button) findViewById(R.id.CancelButton);
+ cancel.setVisibility(View.VISIBLE);
+ cancel.setOnClickListener(new View.OnClickListener() {
+
+ @Override
+ public void onClick(View v) {
+ closeSelectionMode();
+ }
+ });
+ findViewById(R.id.DownloadButton).setVisibility(View.GONE);
+ findViewById(R.id.DescriptionText).setVisibility(View.GONE);
+ findViewById(R.id.FillLayoutStart).setVisibility(View.VISIBLE);
+ findViewById(R.id.FillLayoutEnd).setVisibility(View.VISIBLE);
+ listAdapter.notifyDataSetChanged();
+ }
+
+ private void closeSelectionMode(){
+ selectionMode = false;
+ findViewById(R.id.DownloadButton).setVisibility(View.VISIBLE);
+ findViewById(R.id.DescriptionText).setVisibility(View.VISIBLE);
+ findViewById(R.id.FillLayoutStart).setVisibility(View.GONE);
+ findViewById(R.id.FillLayoutEnd).setVisibility(View.GONE);
+ findViewById(R.id.CancelButton).setVisibility(View.GONE);
+ findViewById(R.id.ActionButton).setVisibility(View.GONE);
+ listAdapter.cancelFilter();
+ listAdapter.notifyDataSetChanged();
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ if(item.getItemId() == R.string.local_index_mi_reload){
+ reloadIndexes();
+ } else if(item.getItemId() == R.string.local_index_mi_delete){
+ openSelectionMode(R.string.local_index_mi_delete);
+ } else if(item.getItemId() == R.string.local_index_mi_backup){
+ listAdapter.filterCategories(false);
+ listAdapter.filterCategories(LocalIndexType.MAP_DATA, LocalIndexType.POI_DATA);
+ openSelectionMode(R.string.local_index_mi_backup);
+ } else if(item.getItemId() == R.string.local_index_mi_restore){
+ listAdapter.filterCategories(true);
+ openSelectionMode(R.string.local_index_mi_restore);
+ } else {
+ return super.onOptionsItemSelected(item);
+ }
+ return true;
+ }
+
+
+ public void reloadIndexes() {
+ AsyncTask> task = new AsyncTask>(){
+
+ @Override
+ protected void onPostExecute(List warnings) {
+ findViewById(R.id.ProgressBar).setVisibility(View.GONE);
+ if (!warnings.isEmpty()) {
+ final StringBuilder b = new StringBuilder();
+ boolean f = true;
+ for (String w : warnings) {
+ if (f) {
+ f = false;
+ } else {
+ b.append('\n');
+ }
+ b.append(w);
+ }
+ Toast.makeText(LocalIndexesActivity.this, b.toString(), Toast.LENGTH_LONG).show();
+ }
+ }
+
+ @Override
+ protected void onPreExecute() {
+ super.onPreExecute();
+ findViewById(R.id.ProgressBar).setVisibility(View.VISIBLE);
+ }
+ @Override
+ protected List doInBackground(Void... params) {
+ return ((OsmandApplication) getApplication()).getResourceManager().reloadIndexes(IProgress.EMPTY_PROGRESS);
+ }
+
+ };
+ task.execute();
+
+ }
+
+
+
+ protected class LocalIndexesAdapter extends BaseExpandableListAdapter {
+ Map> data = new LinkedHashMap>();
+ List category = new ArrayList();
+ List filterCategory = null;
+
+ private MessageFormat formatMb;
+
+ public LocalIndexesAdapter() {
+ formatMb = new MessageFormat("{0, number,##.#} MB");
+ }
+
+ public LocalIndexInfo findCategory(LocalIndexInfo val, boolean backuped){
+ for(LocalIndexInfo i : category){
+ if(i.isBackupedData() == backuped && val.getType() == i.getType() ){
+ return i;
+ }
+ }
+ LocalIndexInfo newCat = new LocalIndexInfo(val.getType(), backuped);
+ category.add(newCat);
+ data.put(newCat, new ArrayList());
+ return newCat;
+ }
+
+ public void delete(LocalIndexInfo[] values) {
+ for(LocalIndexInfo i : values){
+ LocalIndexInfo c = findCategory(i, i.isBackupedData());
+ if(c != null){
+ data.get(c).remove(i);
+ }
+ }
+ listAdapter.notifyDataSetChanged();
+ }
+
+ public void move(LocalIndexInfo[] values, boolean oldBackupState) {
+ for(LocalIndexInfo i : values){
+ LocalIndexInfo c = findCategory(i, oldBackupState);
+ if(c != null){
+ data.get(c).remove(i);
+ }
+ c = findCategory(i, !oldBackupState);
+ if(c != null){
+ data.get(c).add(i);
+ }
+ }
+ listAdapter.notifyDataSetChanged();
+ }
+
+ public void cancelFilter(){
+ filterCategory = null;
+ notifyDataSetChanged();
+ }
+
+ public void filterCategories(LocalIndexType... types) {
+ List filter = new ArrayList();
+ List source = filterCategory == null ? category : filterCategory;
+ for (LocalIndexInfo info : source) {
+ for (LocalIndexType ts : types) {
+ if (info.getType() == ts) {
+ filter.add(info);
+ }
+ }
+ }
+ filterCategory = filter;
+ notifyDataSetChanged();
+ }
+
+ public void filterCategories(boolean backup) {
+ List filter = new ArrayList();
+ List source = filterCategory == null ? category : filterCategory;
+ for (LocalIndexInfo info : source) {
+ if (info.isBackupedData() == backup) {
+ filter.add(info);
+ }
+ }
+ filterCategory = filter;
+ notifyDataSetChanged();
+ }
+
+ public void addLocalIndexInfo(LocalIndexInfo info) {
+ int found = -1;
+ // search from end
+ for (int i = category.size() - 1; i >= 0; i--) {
+ LocalIndexInfo cat = category.get(i);
+ if (cat.getType() == info.getType() && info.isBackupedData() == cat.isBackupedData()) {
+ found = i;
+ break;
+ }
+ }
+ if (found == -1) {
+ found = category.size();
+ category.add(new LocalIndexInfo(info.getType(), info.isBackupedData()));
+ }
+ if (!data.containsKey(category.get(found))) {
+ data.put(category.get(found), new ArrayList());
+ }
+ data.get(category.get(found)).add(info);
+ }
+
+ @Override
+ public LocalIndexInfo getChild(int groupPosition, int childPosition) {
+ LocalIndexInfo cat = filterCategory != null ? filterCategory.get(groupPosition) : category.get(groupPosition);
+ return data.get(cat).get(childPosition);
+ }
+
+ @Override
+ public long getChildId(int groupPosition, int childPosition) {
+ // it would be unusable to have 10000 local indexes
+ return groupPosition * 10000 + childPosition;
+ }
+
+ @Override
+ public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
+ View v = convertView;
+ final LocalIndexInfo child = (LocalIndexInfo) getChild(groupPosition, childPosition);
+ if (v == null ) {
+ LayoutInflater inflater = getLayoutInflater();
+ v = inflater.inflate(net.osmand.plus.R.layout.local_index_list_item, parent, false);
+ }
+ TextView viewName = ((TextView) v.findViewById(R.id.local_index_name));
+ viewName.setText(child.getName());
+ if (child.isNotSupported()) {
+ viewName.setTextColor(Color.RED);
+ } else if (child.isCorrupted()) {
+ viewName.setTextColor(Color.MAGENTA);
+ } else if (child.isLoaded()) {
+ viewName.setTextColor(Color.GREEN);
+ } else {
+ viewName.setTextColor(Color.LTGRAY);
+ }
+ if (child.getSize() >= 0) {
+ String size;
+ if (child.getSize() > 100) {
+ size = formatMb.format(new Object[] { (float) child.getSize() / (1 << 10) });
+ } else {
+ size = child.getSize() + " Kb";
+ }
+ ((TextView) v.findViewById(R.id.local_index_size)).setText(size);
+ } else {
+ ((TextView) v.findViewById(R.id.local_index_size)).setText("");
+ }
+ TextView descr = ((TextView) v.findViewById(R.id.local_index_descr));
+ if (child.isExpanded()) {
+ descr.setVisibility(View.VISIBLE);
+ descr.setText(child.getDescription());
+ } else {
+ descr.setVisibility(View.GONE);
+ }
+ final CheckBox checkbox = (CheckBox) v.findViewById(R.id.check_local_index);
+ checkbox.setVisibility(selectionMode ? View.VISIBLE : View.GONE);
+ if (selectionMode) {
+ checkbox.setChecked(selectedItems.contains(child));
+ checkbox.setOnClickListener(new View.OnClickListener() {
+
+ @Override
+ public void onClick(View v) {
+ if(checkbox.isChecked()){
+ selectedItems.add(child);
+ } else {
+ selectedItems.remove(child);
+ }
+ }
+ });
+ }
+
+
+ return v;
+ }
+
+ @Override
+ public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
+ View v = convertView;
+ LocalIndexInfo group = getGroup(groupPosition);
+ if (v == null) {
+ LayoutInflater inflater = getLayoutInflater();
+ v = inflater.inflate(net.osmand.plus.R.layout.local_index_list_item_category, parent, false);
+ }
+ StringBuilder t = new StringBuilder(group.getType().getHumanString(LocalIndexesActivity.this));
+ if (group.isBackupedData()) {
+ t.append("* ");
+ }
+ TextView nameView = ((TextView) v.findViewById(R.id.local_index_category_name));
+ t.append(" [").append(getChildrenCount(groupPosition)).append(" ").append(getString(R.string.local_index_items)).append("]");
+ nameView.setText(t.toString());
+ if (!group.isBackupedData()) {
+ nameView.setTypeface(Typeface.DEFAULT, Typeface.NORMAL);
+ } else {
+ nameView.setTypeface(Typeface.DEFAULT, Typeface.ITALIC);
+ }
+
+ return v;
+ }
+
+ @Override
+ public int getChildrenCount(int groupPosition) {
+ LocalIndexInfo cat = filterCategory != null ? filterCategory.get(groupPosition) : category.get(groupPosition);
+ return data.get(cat).size();
+ }
+
+ @Override
+ public LocalIndexInfo getGroup(int groupPosition) {
+ return filterCategory == null ? category.get(groupPosition) : filterCategory.get(groupPosition);
+ }
+
+ @Override
+ public int getGroupCount() {
+ return filterCategory == null ? category.size() : filterCategory.size();
+ }
+
+ @Override
+ public long getGroupId(int groupPosition) {
+ return groupPosition;
+ }
+
+ @Override
+ public boolean hasStableIds() {
+ return false;
+ }
+
+ @Override
+ public boolean isChildSelectable(int groupPosition, int childPosition) {
+ return true;
+ }
+ }
+
+}
diff --git a/OsmAnd/src/net/osmand/plus/activities/MapActivityLayers.java b/OsmAnd/src/net/osmand/plus/activities/MapActivityLayers.java
index e7b1546c0f..6ba952b797 100644
--- a/OsmAnd/src/net/osmand/plus/activities/MapActivityLayers.java
+++ b/OsmAnd/src/net/osmand/plus/activities/MapActivityLayers.java
@@ -353,7 +353,7 @@ public class MapActivityLayers {
public void selectGPXFileLayer(final CallbackWithObject callbackWithObject) {
final List list = new ArrayList();
final OsmandSettings settings = getApplication().getSettings();
- final File dir = settings.extendOsmandPath(ResourceManager.APP_DIR + SavingTrackHelper.TRACKS_PATH);
+ final File dir = settings.extendOsmandPath(ResourceManager.GPX_PATH);
if (dir != null && dir.canRead()) {
File[] files = dir.listFiles();
if (files != null) {
diff --git a/OsmAnd/src/net/osmand/plus/activities/SavingTrackHelper.java b/OsmAnd/src/net/osmand/plus/activities/SavingTrackHelper.java
index 3acb0b17d7..cf9aa8b78d 100644
--- a/OsmAnd/src/net/osmand/plus/activities/SavingTrackHelper.java
+++ b/OsmAnd/src/net/osmand/plus/activities/SavingTrackHelper.java
@@ -25,7 +25,6 @@ import android.database.sqlite.SQLiteOpenHelper;
import android.text.format.DateFormat;
public class SavingTrackHelper extends SQLiteOpenHelper {
- public final static String TRACKS_PATH = "tracks"; //$NON-NLS-1$
public final static String DATABASE_NAME = "tracks"; //$NON-NLS-1$
public final static int DATABASE_VERSION = 2;
@@ -116,7 +115,7 @@ public class SavingTrackHelper extends SQLiteOpenHelper {
List warnings = new ArrayList();
File dir = OsmandSettings.getOsmandSettings(ctx).getExternalStorageDirectory();
if(db != null && dir.canWrite()){
- dir = new File(dir, ResourceManager.APP_DIR + TRACKS_PATH);
+ dir = new File(dir, ResourceManager.GPX_PATH);
dir.mkdirs();
if (dir.exists()) {
diff --git a/OsmAnd/src/net/osmand/plus/activities/SettingsActivity.java b/OsmAnd/src/net/osmand/plus/activities/SettingsActivity.java
index 188fa86254..1853a00a23 100644
--- a/OsmAnd/src/net/osmand/plus/activities/SettingsActivity.java
+++ b/OsmAnd/src/net/osmand/plus/activities/SettingsActivity.java
@@ -58,8 +58,6 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference
private static final String MORE_VALUE = "MORE_VALUE";
private Preference saveCurrentTrack;
- private Preference reloadIndexes;
- private Preference downloadIndexes;
private EditTextPreference applicationDir;
private ListPreference tileSourcePreference;
@@ -278,10 +276,8 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference
underlayPreference.setOnPreferenceChangeListener(this);
- reloadIndexes =(Preference) screen.findPreference(OsmandSettings.RELOAD_INDEXES);
- reloadIndexes.setOnPreferenceClickListener(this);
- downloadIndexes =(Preference) screen.findPreference(OsmandSettings.DOWNLOAD_INDEXES);
- downloadIndexes.setOnPreferenceClickListener(this);
+ Preference localIndexes =(Preference) screen.findPreference(OsmandSettings.LOCAL_INDEXES);
+ localIndexes.setOnPreferenceClickListener(this);
saveCurrentTrack =(Preference) screen.findPreference(OsmandSettings.SAVE_CURRENT_TRACK);
saveCurrentTrack.setOnPreferenceClickListener(this);
routeServiceEnabled =(CheckBoxPreference) screen.findPreference(OsmandSettings.SERVICE_OFF_ENABLED);
@@ -637,11 +633,8 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference
@Override
public boolean onPreferenceClick(Preference preference) {
- if(preference == downloadIndexes){
- startActivity(new Intent(this, DownloadIndexActivity.class));
- return true;
- } else if(preference == reloadIndexes){
- reloadIndexes();
+ if(preference.getKey().equals(OsmandSettings.LOCAL_INDEXES)){
+ startActivity(new Intent(this, LocalIndexesActivity.class));
return true;
} else if(preference == saveCurrentTrack){
SavingTrackHelper helper = new SavingTrackHelper(this);
diff --git a/OsmAnd/src/net/osmand/plus/render/MapRenderRepositories.java b/OsmAnd/src/net/osmand/plus/render/MapRenderRepositories.java
index 08ed3b8555..3a0db8b7f8 100644
--- a/OsmAnd/src/net/osmand/plus/render/MapRenderRepositories.java
+++ b/OsmAnd/src/net/osmand/plus/render/MapRenderRepositories.java
@@ -1051,4 +1051,7 @@ public class MapRenderRepositories {
}
+ public Map getMetaInfoFiles() {
+ return files;
+ }
}
diff --git a/OsmAnd/src/net/osmand/plus/voice/TTSCommandPlayerImpl.java b/OsmAnd/src/net/osmand/plus/voice/TTSCommandPlayerImpl.java
index 6f897cbbd0..2df42b8f47 100644
--- a/OsmAnd/src/net/osmand/plus/voice/TTSCommandPlayerImpl.java
+++ b/OsmAnd/src/net/osmand/plus/voice/TTSCommandPlayerImpl.java
@@ -161,7 +161,7 @@ public class TTSCommandPlayerImpl extends AbstractPrologCommandPlayer {
internalClear();
}
- public static boolean isMyData(File voiceDir) throws CommandPlayerException {
+ public static boolean isMyData(File voiceDir) {
return new File(voiceDir, CONFIG_FILE).exists();
}