Implement offline indexes manager in application. Issue 366
This commit is contained in:
commit
7aec6b168a
18 changed files with 1243 additions and 23 deletions
|
@ -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() {}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@ public class BinaryMapIndexReader {
|
|||
}
|
||||
init();
|
||||
}
|
||||
|
||||
|
||||
private void init() throws IOException {
|
||||
boolean initCorrectly = false;
|
||||
while(true){
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
<data android:scheme="geo"></data>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name=".activities.LocalIndexesActivity"></activity>
|
||||
<service android:process="net.osmand.plus" android:label="@string/process_navigation_service" android:name=".NavigationService">
|
||||
<intent-filter><action android:name="net.osmand.plus.NavigationService"></action></intent-filter>
|
||||
</service>
|
||||
|
|
27
OsmAnd/res/layout/local_index.xml
Normal file
27
OsmAnd/res/layout/local_index.xml
Normal file
|
@ -0,0 +1,27 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent" android:orientation="vertical">
|
||||
|
||||
<LinearLayout android:id="@+id/LoadingPanel" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginTop="3dp">
|
||||
<Button android:id="@+id/DownloadButton" android:layout_width="wrap_content" android:layout_gravity="right" android:layout_height="wrap_content" android:text="@string/local_index_download"
|
||||
android:layout_marginLeft = "3dp" android:layout_marginTop ="3dp" android:layout_marginRight = "3dp"/>
|
||||
<TextView android:id="@+id/DescriptionText" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="1"
|
||||
android:text="@string/local_index_description"/>
|
||||
<LinearLayout android:id="@+id/FillLayoutStart" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="1" android:visibility="gone"/>
|
||||
<Button android:id="@+id/ActionButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/local_index_download"
|
||||
android:layout_marginLeft = "3dp" android:layout_marginTop ="3dp" android:layout_marginRight = "3dp" android:visibility="gone"/>
|
||||
<Button android:id="@+id/CancelButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/default_buttons_cancel"
|
||||
android:layout_marginLeft = "3dp" android:layout_marginTop ="3dp" android:layout_marginRight = "3dp" android:visibility="gone"/>
|
||||
|
||||
<LinearLayout android:id="@+id/FillLayoutEnd" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="1" android:visibility="gone"/>
|
||||
<ProgressBar android:id="@+id/ProgressBar" android:layout_marginLeft="5dp" android:indeterminate="true" android:layout_width="wrap_content" android:layout_height="wrap_content"
|
||||
android:layout_marginRight="5dp"/>
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
<ExpandableListView android:id="@android:id/list" android:layout_width="fill_parent" android:layout_weight="1" android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="3dp" android:layout_marginTop="3dp" android:layout_marginRight="3dp" ></ExpandableListView>
|
||||
|
||||
</LinearLayout>
|
20
OsmAnd/res/layout/local_index_list_item.xml
Normal file
20
OsmAnd/res/layout/local_index_list_item.xml
Normal file
|
@ -0,0 +1,20 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginLeft="15dp">
|
||||
<LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content">
|
||||
<CheckBox android:id="@+id/check_local_index" android:layout_width="wrap_content" android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical" android:focusable="false"/>
|
||||
</LinearLayout>
|
||||
<TextView android:id="@+id/local_index_name" android:gravity="center_vertical" android:layout_width="wrap_content" android:layout_height="wrap_content"
|
||||
android:layout_weight="1" android:textSize="20sp" android:layout_marginLeft="8dp"></TextView>
|
||||
|
||||
<TextView android:id="@+id/local_index_size" android:layout_marginLeft="3dp" android:gravity="center_vertical" android:layout_width="75dp"
|
||||
android:layout_height="wrap_content" android:textSize="16sp" ></TextView>
|
||||
</LinearLayout>
|
||||
|
||||
<TextView android:id="@+id/local_index_descr" android:layout_marginLeft="25dp" android:layout_marginTop="5dp"
|
||||
android:layout_marginRight="10dp" android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content" android:textSize="16sp" ></TextView>
|
||||
</LinearLayout>
|
8
OsmAnd/res/layout/local_index_list_item_category.xml
Normal file
8
OsmAnd/res/layout/local_index_list_item_category.xml
Normal file
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<TextView android:id="@+id/local_index_category_name" android:gravity="center_vertical" android:layout_width="wrap_content" android:layout_height="wrap_content"
|
||||
android:textSize="21sp" android:layout_marginLeft="40dp"></TextView>
|
||||
|
||||
</LinearLayout>
|
|
@ -1,7 +1,33 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
||||
<resources>
|
||||
<string name="ttsvoice">TTS Voice</string>
|
||||
<string name="local_index_gpx_info">Subtracks : %1$d\nTotal Points : %2$d\nWay points : %3$d</string>
|
||||
<string name="local_index_installed">Installed</string>
|
||||
<string name="local_index_items_backuped">%1$d items of %2$d were succesfully backuped.</string>
|
||||
<string name="local_index_items_deleted">%1$d items of %2$d were succesfully deleted.</string>
|
||||
<string name="local_index_items_restored">%1$d items of %2$d were succesfully restored.</string>
|
||||
<string name="local_index_no_items_to_do">No items to %1$s</string>
|
||||
<string name="local_index_action_do">You are about to %1$s %2$s items. Are you sure?</string>
|
||||
<string name="local_index_description">Offline data available on the phone.\n You can download new or backup and delete existing data.</string>
|
||||
<string name="local_index_mi_restore">Restore</string>
|
||||
<string name="local_index_mi_backup">Backup</string>
|
||||
<string name="local_index_mi_delete">Delete</string>
|
||||
<string name="local_index_mi_reload">Reload</string>
|
||||
<string name="local_index_download">Download</string>
|
||||
<string name="local_index_tile_data">Tile data: %1$s \nMinimum zoom : %2$d\nMaximum zoom : %3$d\nDownloadable : %4$s \nZooms downloaded : %5$s</string>
|
||||
<string name="local_index_poi_data">POI data</string>
|
||||
<string name="local_index_address_data">Address data</string>
|
||||
<string name="local_index_transport_data">Transport data</string>
|
||||
<string name="local_index_map_data">Map data</string>
|
||||
<string name="local_index_items">items</string>
|
||||
<string name="local_indexes_cat_backup">Backup</string>
|
||||
<string name="local_indexes_cat_tts">TTS data</string>
|
||||
<string name="local_indexes_cat_voice">Voice data</string>
|
||||
<string name="local_indexes_cat_gpx">GPX data</string>
|
||||
<string name="local_indexes_cat_tile">Tile data</string>
|
||||
<string name="local_indexes_cat_map">Map data</string>
|
||||
<string name="local_indexes_cat_poi">POI data</string>
|
||||
|
||||
<string name="ttsvoice">TTS Voice</string>
|
||||
<string name="search_offline_clear_search">New Search</string>
|
||||
<string name="map_text_size_descr">Select text size for names on the map</string>
|
||||
<string name="map_text_size">Text size</string>
|
||||
|
|
|
@ -30,10 +30,7 @@
|
|||
</PreferenceScreen>
|
||||
|
||||
|
||||
<PreferenceScreen android:key="index_settings" android:title="@string/index_settings" android:summary="@string/index_settings_descr">
|
||||
<Preference android:title="@string/reload_indexes" android:key="reload_indexes" android:summary="@string/reload_indexes_descr"></Preference>
|
||||
<Preference android:title="@string/download_indexes" android:key="download_indexes" android:summary="@string/download_indexes_descr"></Preference>
|
||||
</PreferenceScreen>
|
||||
<Preference android:title="@string/index_settings" android:key="local_indexes" android:summary="@string/index_settings_descr"></Preference>
|
||||
|
||||
|
||||
<PreferenceScreen android:key = "monitor_settings" android:title="@string/monitor_preferences" android:summary="@string/monitor_preferences_descr">
|
||||
|
|
|
@ -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<Boolean> SAVE_TRACK_TO_GPX = new BooleanPreference("save_track_to_gpx", false, false);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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){
|
||||
|
|
436
OsmAnd/src/net/osmand/plus/activities/LocalIndexHelper.java
Normal file
436
OsmAnd/src/net/osmand/plus/activities/LocalIndexHelper.java
Normal file
|
@ -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<LocalIndexInfo> 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<Integer> zooms = new TreeSet<Integer>();
|
||||
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<Integer> zooms = new TreeSet<Integer>();
|
||||
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<LocalIndexInfo> getLocalIndexData(LocalIndexType type, LoadLocalIndexTask loadTask){
|
||||
OsmandSettings settings = OsmandSettings.getOsmandSettings(app.getApplicationContext());
|
||||
Map<String, String> loadedMaps = app.getResourceManager().getIndexFileNames();
|
||||
List<LocalIndexInfo> result = new ArrayList<LocalIndexInfo>();
|
||||
|
||||
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<LocalIndexInfo> 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<LocalIndexInfo> 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<LocalIndexInfo> result, boolean backup, LoadLocalIndexTask loadTask, Map<String, String> 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<LocalIndexInfo> 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<LocalIndexInfo> 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<BinaryIndexPart> 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
666
OsmAnd/src/net/osmand/plus/activities/LocalIndexesActivity.java
Normal file
666
OsmAnd/src/net/osmand/plus/activities/LocalIndexesActivity.java
Normal file
|
@ -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<Activity, LocalIndexInfo, List<LocalIndexInfo>> asyncLoader;
|
||||
private LocalIndexesAdapter listAdapter;
|
||||
private LoadLocalIndexDescriptionTask descriptionLoader;
|
||||
private LocalIndexOperationTask operationTask;
|
||||
|
||||
private boolean selectionMode = false;
|
||||
private Set<LocalIndexInfo> selectedItems = new LinkedHashSet<LocalIndexInfo>();
|
||||
|
||||
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<Activity, LocalIndexInfo, List<LocalIndexInfo>> {
|
||||
List<LocalIndexInfo> progress = new ArrayList<LocalIndexInfo>();
|
||||
|
||||
@Override
|
||||
protected List<LocalIndexInfo> 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<LocalIndexInfo> result) {
|
||||
findViewById(R.id.ProgressBar).setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class LocalIndexOperationTask extends AsyncTask<LocalIndexInfo, LocalIndexInfo, String> {
|
||||
|
||||
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<LocalIndexInfo, LocalIndexInfo, LocalIndexInfo[]> {
|
||||
|
||||
@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<Void, String, List<String>> task = new AsyncTask<Void, String, List<String>>(){
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(List<String> 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<String> doInBackground(Void... params) {
|
||||
return ((OsmandApplication) getApplication()).getResourceManager().reloadIndexes(IProgress.EMPTY_PROGRESS);
|
||||
}
|
||||
|
||||
};
|
||||
task.execute();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected class LocalIndexesAdapter extends BaseExpandableListAdapter {
|
||||
Map<LocalIndexInfo, List<LocalIndexInfo>> data = new LinkedHashMap<LocalIndexInfo, List<LocalIndexInfo>>();
|
||||
List<LocalIndexInfo> category = new ArrayList<LocalIndexInfo>();
|
||||
List<LocalIndexInfo> 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<LocalIndexInfo>());
|
||||
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<LocalIndexInfo> filter = new ArrayList<LocalIndexInfo>();
|
||||
List<LocalIndexInfo> 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<LocalIndexInfo> filter = new ArrayList<LocalIndexInfo>();
|
||||
List<LocalIndexInfo> 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<LocalIndexInfo>());
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -353,7 +353,7 @@ public class MapActivityLayers {
|
|||
public void selectGPXFileLayer(final CallbackWithObject<GPXFileResult> callbackWithObject) {
|
||||
final List<String> list = new ArrayList<String>();
|
||||
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) {
|
||||
|
|
|
@ -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<String> warnings = new ArrayList<String>();
|
||||
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()) {
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -1051,4 +1051,7 @@ public class MapRenderRepositories {
|
|||
}
|
||||
|
||||
|
||||
public Map<String, BinaryMapIndexReader> getMetaInfoFiles() {
|
||||
return files;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue