From cb80fc14303edb18a8e6cffcea760ba677e7e4f1 Mon Sep 17 00:00:00 2001 From: Victor Shcherb Date: Sat, 31 Jul 2010 10:38:16 +0000 Subject: [PATCH] implement import/export favorite points git-svn-id: https://osmand.googlecode.com/svn/trunk@419 e29c36b1-1cfa-d876-8d93-3434fc2bb7b8 --- .../src/com/osmand/ToDoConstants.java | 22 ++-- OsmAnd/res/values-de/strings.xml | 2 +- OsmAnd/res/values-ru/strings.xml | 9 +- OsmAnd/res/values/strings.xml | 9 +- .../activities/DownloadIndexActivity.java | 2 +- .../osmand/activities/FavouritesActivity.java | 93 +++++++++++++++- .../osmand/activities/MainMenuActivity.java | 11 ++ .../osmand/activities/SavingTrackHelper.java | 104 +++++++++++++++++- 8 files changed, 224 insertions(+), 28 deletions(-) diff --git a/DataExtractionOSM/src/com/osmand/ToDoConstants.java b/DataExtractionOSM/src/com/osmand/ToDoConstants.java index aa28510dd3..e1f19801d7 100644 --- a/DataExtractionOSM/src/com/osmand/ToDoConstants.java +++ b/DataExtractionOSM/src/com/osmand/ToDoConstants.java @@ -8,23 +8,18 @@ package com.osmand; */ public class ToDoConstants { - // TODO - // 80. Export/import favorite points - // 81. Add some objects to POI category (1) to add them into OSM 2) to help navigation) - // highway (?), traffic_calming (?), barrier(?), military(?-), landuse (?), office(?), man_made(?), power(?). + // TODO max 85 + // ! 81. Add some objects to POI category (1) to add them into OSM 2) to help navigation) + // highway (?), traffic_calming (?), barrier(?), military(?-), landuse (?), office(?), man_made(?), power(?), + // railway( station, subway?) - issue 17 // TODO BUGS Android - // 3. different screens better support + // ! 3. different screens better support - // 2. GPS - network switch (+?) - // 5. route bug show further (+) - // 4. save state yandex traffic (+) - // 1. Alert no addresses (+) - // Improvements - // ! Download with wget - // ! progress while map is loading + // ! Download with wget + // ! progress while map is loading // Not clear if it is really needed // 69. Add phone information to POI @@ -42,12 +37,13 @@ public class ToDoConstants { // TODO swing // 9. Fix issues with big files (such as netherlands) - save memory (!) - very slow due to transport index ! // Current result : for big file (1 - task 60-80% time, 90% memory) (?) - // 10. Improve address indexing (use relations). (?) // SLOBODSKAYA 157, 95 + // ! 10. Improve address indexing (use relations). (?) // SLOBODSKAYA 157, 95 // use relation "a6" (to accumulate streets!), "a3" to read all cities & define boundaries for city (& define that street in city). // BUGS Swing // DONE ANDROID : + // 80. Export/import favorite points // 84. Send letter to developer when app crashes // 78. Add ruler to the main tile view (100m, 200m,...) (+) // 82. Add overzoom +2 for Mapnik diff --git a/OsmAnd/res/values-de/strings.xml b/OsmAnd/res/values-de/strings.xml index be1e605f15..b6828c32c5 100644 --- a/OsmAnd/res/values-de/strings.xml +++ b/OsmAnd/res/values-de/strings.xml @@ -121,7 +121,7 @@ {0} Gesamtentfernung\n{1}:{2}Reisezeit Dienst zur Streckenberechnung wählen Streckenberechnungsdienst - Directory on SD card to save index is not accessible + Directory on SD card to save is not accessible Do you want to download {0} - {1} ? Index for {0} already exists ({1}). Do you want to update it ({2}) ? Adresse diff --git a/OsmAnd/res/values-ru/strings.xml b/OsmAnd/res/values-ru/strings.xml index 564b58f5a3..1119ca2ba5 100644 --- a/OsmAnd/res/values-ru/strings.xml +++ b/OsmAnd/res/values-ru/strings.xml @@ -1,5 +1,12 @@ + Избранные точки успешно импортированы + GPX файл, содержащий точки, не был найден в {0} + Избранные точки сохранены в {0} + Нет избранных точек для сохранения + Импортировать + Экспортировать + Произошла ошибка во время загрузки gpx Отправить отчет Не найден ни один индекс на SD карточке. Можете загрузить их с интернета. Введите запрос для поиска POI @@ -123,7 +130,7 @@ Общая протяженность = {0}, время в пути = {1} ч. {2} мин. Выберите сервис для прокладки маршрута Прокладка маршрута - Директория на SD карточка не доступна для сохранения + Директория на SD карточке не доступна для сохранения Вы хотите загрузить {0} - {1} ? Индекс для {0} уже существует ({1}). Вы хотите его обновить ({2}) ? Адрес diff --git a/OsmAnd/res/values/strings.xml b/OsmAnd/res/values/strings.xml index 0050eed2a7..e45ccb6676 100644 --- a/OsmAnd/res/values/strings.xml +++ b/OsmAnd/res/values/strings.xml @@ -1,5 +1,12 @@ + Favorite points were succesfully imported + GPX file to load favorite points is not found at {0} + Favorite points were succesfully saved to {0} + No favorite points to save + Import + Export + Error occurred while loading gpx Send report None region were found on SD card. Try to download region from internet. Input search query to find POI @@ -123,7 +130,7 @@ Overall distance = {0}, travelling time = {1} h {2} m. Choose routing service Routing - Directory on SD card to save index is not accessible + Directory on SD card to save is not accessible Do you want to download {0} - {1} ? Index for {0} already exists ({1}). Do you want to update it ({2}) ? Address diff --git a/OsmAnd/src/com/osmand/activities/DownloadIndexActivity.java b/OsmAnd/src/com/osmand/activities/DownloadIndexActivity.java index d5d8d25558..bae69841b2 100644 --- a/OsmAnd/src/com/osmand/activities/DownloadIndexActivity.java +++ b/OsmAnd/src/com/osmand/activities/DownloadIndexActivity.java @@ -169,7 +169,7 @@ public class DownloadIndexActivity extends ListActivity { parent.mkdirs(); } if(parent == null || !parent.exists()){ - Toast.makeText(DownloadIndexActivity.this, getString(R.string.download_sd_dir_not_accessible), Toast.LENGTH_LONG).show(); + Toast.makeText(DownloadIndexActivity.this, getString(R.string.sd_dir_not_accessible), Toast.LENGTH_LONG).show(); return null; } File file = new File(parent, regionName); diff --git a/OsmAnd/src/com/osmand/activities/FavouritesActivity.java b/OsmAnd/src/com/osmand/activities/FavouritesActivity.java index d2bc558d46..553e2f177e 100644 --- a/OsmAnd/src/com/osmand/activities/FavouritesActivity.java +++ b/OsmAnd/src/com/osmand/activities/FavouritesActivity.java @@ -3,9 +3,12 @@ */ package com.osmand.activities; +import java.io.File; import java.text.MessageFormat; import java.util.ArrayList; +import java.util.LinkedHashSet; import java.util.List; +import java.util.Set; import android.app.AlertDialog; import android.app.ListActivity; @@ -18,8 +21,10 @@ import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.os.Bundle; +import android.os.Environment; import android.view.ContextMenu; import android.view.LayoutInflater; +import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; @@ -34,6 +39,8 @@ import android.widget.AdapterView.AdapterContextMenuInfo; import com.osmand.OsmandSettings; import com.osmand.R; +import com.osmand.ResourceManager; +import com.osmand.activities.SavingTrackHelper.WptPt; import com.osmand.osm.LatLon; import com.osmand.osm.MapUtils; @@ -46,6 +53,11 @@ public class FavouritesActivity extends ListActivity { public static final int DELETE_ITEM = 1; public static final int EDIT_ITEM = 2; + public static final int EXPORT_ID = 0; + public static final int IMPORT_ID = 1; + + public static final String FILE_TO_SAVE = "favourites.gpx"; //$NON-NLS-1$ + private List favouritesList; private FavouritesDbHelper helper; @@ -86,15 +98,15 @@ public class FavouritesActivity extends ListActivity { } @Override - public boolean onContextItemSelected(MenuItem aItem) { + public boolean onContextItemSelected(MenuItem aItem) { AdapterContextMenuInfo menuInfo = (AdapterContextMenuInfo) aItem.getMenuInfo(); final FavouritePoint point = (FavouritePoint) favouritesList.get(menuInfo.position); - if(aItem.getItemId() == NAVIGATE_TO){ -// OsmandSettings.setMapLocationToShow(this, point.getLatitude(), point.getLongitude(), getString(R.string.favorite)+" : " + point.getName()); //$NON-NLS-1$ + if (aItem.getItemId() == NAVIGATE_TO) { + //OsmandSettings.setMapLocationToShow(this, point.getLatitude(), point.getLongitude(), getString(R.string.favorite)+" : " + point.getName()); //$NON-NLS-1$ OsmandSettings.setPointToNavigate(this, point.getLatitude(), point.getLongitude()); Intent newIntent = new Intent(FavouritesActivity.this, MapActivity.class); startActivity(newIntent); - } else if(aItem.getItemId() == EDIT_ITEM){ + } else if (aItem.getItemId() == EDIT_ITEM) { Builder builder = new AlertDialog.Builder(this); builder.setTitle(R.string.favourites_edit_dialog_title); final EditText editText = new EditText(this); @@ -113,7 +125,8 @@ public class FavouritesActivity extends ListActivity { }); builder.create().show(); return true; - } if(aItem.getItemId() == DELETE_ITEM){ + } + if (aItem.getItemId() == DELETE_ITEM) { final Resources resources = this.getResources(); Builder builder = new AlertDialog.Builder(this); builder.setMessage(R.string.favourites_remove_dialog_title); @@ -123,7 +136,8 @@ public class FavouritesActivity extends ListActivity { public void onClick(DialogInterface dialog, int which) { boolean deleted = helper.deleteFavourite(point); if (deleted) { - Toast.makeText(FavouritesActivity.this, MessageFormat.format(resources.getString(R.string.favourites_remove_dialog_success), point.getName()), + Toast.makeText(FavouritesActivity.this, + MessageFormat.format(resources.getString(R.string.favourites_remove_dialog_success), point.getName()), Toast.LENGTH_SHORT).show(); favouritesList.remove(point); favouritesAdapter.notifyDataSetChanged(); @@ -137,6 +151,73 @@ public class FavouritesActivity extends ListActivity { return false; } + @Override + public boolean onCreateOptionsMenu(Menu menu) { + super.onCreateOptionsMenu(menu); + MenuItem item = menu.add(0, EXPORT_ID, 0, R.string.export_fav); + item.setIcon(android.R.drawable.ic_menu_save); + item = menu.add(0, IMPORT_ID, 0, R.string.import_fav); + item.setIcon(android.R.drawable.ic_menu_upload); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + if(item.getItemId() == EXPORT_ID){ + File appDir = new File(Environment.getExternalStorageDirectory(), ResourceManager.APP_DIR); + if(favouritesList == null || favouritesList.isEmpty()){ + Toast.makeText(this, R.string.no_fav_to_save, Toast.LENGTH_LONG).show(); + } else if(!appDir.exists()){ + Toast.makeText(this, R.string.sd_dir_not_accessible, Toast.LENGTH_LONG).show(); + } else { + File f = new File(appDir, FILE_TO_SAVE); + List wpt = new ArrayList(); + for(FavouritePoint p : favouritesList){ + WptPt pt = new WptPt(); + pt.lat = p.latitude; + pt.lon = p.longitude; + pt.name = p.name; + wpt.add(pt); + } + if(SavingTrackHelper.saveToXMLFiles(f, wpt, this)){ + Toast.makeText(this, MessageFormat.format(getString(R.string.fav_saved_sucessfully), f.getAbsolutePath()), + Toast.LENGTH_LONG).show(); + } + } + } else if(item.getItemId() == IMPORT_ID){ + File appDir = new File(Environment.getExternalStorageDirectory(), ResourceManager.APP_DIR); + File f = new File(appDir, FILE_TO_SAVE); + if(!f.exists()){ + Toast.makeText(this, MessageFormat.format(getString(R.string.fav_file_to_load_not_found), f.getAbsolutePath()), Toast.LENGTH_LONG).show(); + } else { + Set existedPoints = new LinkedHashSet(); + if(favouritesList != null){ + for(FavouritePoint fp : favouritesList){ + existedPoints.add(fp.name); + } + } + List points = new ArrayList(); + if(SavingTrackHelper.readWptPtFromFile(f, points, this)){ + for(WptPt p : points){ + if(!existedPoints.contains(p.name)){ + FavouritePoint fp = new FavouritePoint(); + fp.name = p.name; + fp.latitude = p.lat; + fp.longitude = p.lon; + helper.addFavourite(fp); + favouritesList.add(fp); + } + } + Toast.makeText(this, R.string.fav_imported_sucessfully, Toast.LENGTH_SHORT).show(); + favouritesAdapter.notifyDataSetChanged(); + } + } + } else { + return false; + } + return true; + } + public static class FavouritesDbHelper extends SQLiteOpenHelper { private static final int DATABASE_VERSION = 1; diff --git a/OsmAnd/src/com/osmand/activities/MainMenuActivity.java b/OsmAnd/src/com/osmand/activities/MainMenuActivity.java index b985706dfd..7ad07abaf7 100644 --- a/OsmAnd/src/com/osmand/activities/MainMenuActivity.java +++ b/OsmAnd/src/com/osmand/activities/MainMenuActivity.java @@ -16,6 +16,8 @@ import android.app.AlertDialog.Builder; import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager.NameNotFoundException; import android.net.Uri; import android.os.Build; import android.os.Bundle; @@ -33,6 +35,7 @@ import com.osmand.LogUtil; import com.osmand.ProgressDialogImplementation; import com.osmand.R; import com.osmand.ResourceManager; +import com.osmand.Version; import com.osmand.activities.search.SearchActivity; import com.osmand.voice.CommandPlayer; @@ -112,6 +115,14 @@ public class MainMenuActivity extends Activity { text.append("\nProduct : ").append(Build.PRODUCT); //$NON-NLS-1$ text.append("\nBuild : ").append(Build.DISPLAY); //$NON-NLS-1$ text.append("\nVersion : ").append(Build.VERSION.RELEASE); //$NON-NLS-1$ + text.append("\nApp Version : ").append(Version.APP_NAME_VERSION); //$NON-NLS-1$ + try { + PackageInfo info = getPackageManager().getPackageInfo(getPackageResourcePath(), 0); + if (info != null) { + text.append("\nApk Version : ").append(info.versionName).append(" ").append(info.versionCode); //$NON-NLS-1$ //$NON-NLS-2$ + } + } catch (NameNotFoundException e) { + } intent.putExtra(Intent.EXTRA_TEXT, text.toString()); startActivity(Intent.createChooser(intent, getString(R.string.send_report))); } diff --git a/OsmAnd/src/com/osmand/activities/SavingTrackHelper.java b/OsmAnd/src/com/osmand/activities/SavingTrackHelper.java index 31a8c2fbc1..71665f282f 100644 --- a/OsmAnd/src/com/osmand/activities/SavingTrackHelper.java +++ b/OsmAnd/src/com/osmand/activities/SavingTrackHelper.java @@ -1,6 +1,7 @@ package com.osmand.activities; import java.io.File; +import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.text.SimpleDateFormat; @@ -11,6 +12,8 @@ import java.util.List; import java.util.Map; import org.apache.commons.logging.Log; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; import android.content.Context; @@ -64,7 +67,7 @@ public class SavingTrackHelper extends SQLiteOpenHelper { public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { } - private static class TrkPt { + public static class TrkPt { public double lat; public double lon; public double ele; @@ -72,8 +75,99 @@ public class SavingTrackHelper extends SQLiteOpenHelper { public long time; } + public static class WptPt { + public double lat; + public double lon; + public String name; + } - protected void saveToXMLFiles(File dir, Map>> data ){ + public static boolean readWptPtFromFile(File fout, List readTo, Context ctx){ + try { + XmlPullParser parser = Xml.newPullParser(); + parser.setInput(new FileInputStream(fout), "UTF-8"); //$NON-NLS-1$ + int tok; + WptPt current = null; + while((tok=parser.next()) != XmlPullParser.END_DOCUMENT){ + if(tok == XmlPullParser.START_TAG){ + if(parser.getName().equals("wpt")){ //$NON-NLS-1$ + try { + current = new WptPt(); + current.lat = Double.parseDouble(parser.getAttributeValue("", "lat")); //$NON-NLS-1$ //$NON-NLS-2$ + current.lon = Double.parseDouble(parser.getAttributeValue("", "lon")); //$NON-NLS-1$ //$NON-NLS-2$ + } catch (NumberFormatException e) { + current= null; + + } + } else if(current != null && parser.getName().equals("name")){ //$NON-NLS-1$ + if(parser.next() == XmlPullParser.TEXT){ + current.name = parser.getText(); + } + } + } else if(tok == XmlPullParser.END_TAG){ + if(parser.getName().equals("wpt")){ //$NON-NLS-1$ + if(current != null && current.name != null){ + readTo.add(current); + } + current = null; + } + } + } + return true; + } catch (IOException e) { + log.error("Error loading gpx", e); //$NON-NLS-1$ + Toast.makeText(ctx, ctx.getString(R.string.error_occurred_loading_gpx), Toast.LENGTH_LONG).show(); + return false; + } catch (XmlPullParserException e) { + log.error("Error loading gpx", e); //$NON-NLS-1$ + Toast.makeText(ctx, ctx.getString(R.string.error_occurred_loading_gpx), Toast.LENGTH_LONG).show(); + return false; + } + + } + + + public static boolean saveToXMLFiles(File fout, List data, Context ctx ){ + try { + FileOutputStream output = new FileOutputStream(fout); + XmlSerializer serializer = Xml.newSerializer(); + serializer.setOutput(output, "UTF-8"); //$NON-NLS-1$ + serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true); //$NON-NLS-1$ + serializer.startDocument("UTF-8", true); //$NON-NLS-1$ + serializer.startTag(null, "gpx"); //$NON-NLS-1$ + serializer.attribute(null, "version", "1.1"); //$NON-NLS-1$ //$NON-NLS-2$ + serializer.attribute(null, "creator", Version.APP_NAME_VERSION); //$NON-NLS-1$ + serializer.attribute("xmlns", "xsi", "http://www.w3.org/2001/XMLSchema-instance"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + serializer.attribute("xsi", "schemaLocation", "http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + serializer.attribute(null, "xmlns", "http://www.topografix.com/GPX/1/1"); //$NON-NLS-1$ //$NON-NLS-2$ + + for (WptPt l : data) { + serializer.startTag(null, "wpt"); //$NON-NLS-1$ + serializer.attribute(null, "lat", l.lat + ""); //$NON-NLS-1$ //$NON-NLS-2$ + serializer.attribute(null, "lon", l.lon + ""); //$NON-NLS-1$ //$NON-NLS-2$ + serializer.startTag(null, "name"); //$NON-NLS-1$ + serializer.text(l.name); + serializer.endTag(null, "name"); //$NON-NLS-1$ + serializer.endTag(null, "wpt"); //$NON-NLS-1$ + } + + serializer.endTag(null, "gpx"); //$NON-NLS-1$ + serializer.flush(); + serializer.endDocument(); + + return true; + } catch (RuntimeException e) { + log.error("Error saving gpx", e); //$NON-NLS-1$ + Toast.makeText(ctx, ctx.getString(R.string.error_occurred_saving_gpx), Toast.LENGTH_LONG).show(); + return false; + } catch (IOException e) { + log.error("Error saving gpx", e); //$NON-NLS-1$ + Toast.makeText(ctx, ctx.getString(R.string.error_occurred_saving_gpx), Toast.LENGTH_LONG).show(); + return false; + } + + } + + public static void saveToXMLFiles(File dir, Map>> data, Context ctx){ SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); //$NON-NLS-1$ try { for (String f : data.keySet()) { @@ -127,10 +221,10 @@ public class SavingTrackHelper extends SQLiteOpenHelper { } } catch (RuntimeException e) { log.error("Error saving gpx", e); //$NON-NLS-1$ - Toast.makeText(ctx, ctx.getString(R.string.error_occurred_saving_gpx), Toast.LENGTH_LONG); + Toast.makeText(ctx, ctx.getString(R.string.error_occurred_saving_gpx), Toast.LENGTH_LONG).show(); } catch (IOException e) { log.error("Error saving gpx", e); //$NON-NLS-1$ - Toast.makeText(ctx, ctx.getString(R.string.error_occurred_saving_gpx), Toast.LENGTH_LONG); + Toast.makeText(ctx, ctx.getString(R.string.error_occurred_saving_gpx), Toast.LENGTH_LONG).show(); } } @@ -199,7 +293,7 @@ public class SavingTrackHelper extends SQLiteOpenHelper { } while (query.moveToNext()); } query.close(); - saveToXMLFiles(file, data); + saveToXMLFiles(file, data, ctx); } }