Implement offline indexes manager in application. Issue 366

This commit is contained in:
Victor Shcherb 2011-08-20 22:56:40 +02:00
commit 7aec6b168a
18 changed files with 1243 additions and 23 deletions

View file

@ -27,4 +27,31 @@ public interface IProgress {
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() {}
};
}

View file

@ -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>

View 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>

View 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>

View 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>

View file

@ -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>

View file

@ -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">

View file

@ -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);

View file

@ -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)

View file

@ -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){

View 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;
}
}
}

View 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;
}
}
}

View file

@ -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) {

View file

@ -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()) {

View file

@ -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);

View file

@ -1051,4 +1051,7 @@ public class MapRenderRepositories {
}
public Map<String, BinaryMapIndexReader> getMetaInfoFiles() {
return files;
}
}

View file

@ -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();
}