fixing bugs with routing

implementing features

git-svn-id: https://osmand.googlecode.com/svn/trunk@188 e29c36b1-1cfa-d876-8d93-3434fc2bb7b8
This commit is contained in:
Victor Shcherb 2010-06-20 22:15:47 +00:00
parent caedaf92ab
commit 571f93a573
14 changed files with 274 additions and 95 deletions

View file

@ -7,14 +7,6 @@ package com.osmand;
* Do not worry to put ugly code here (just a little piece) * Do not worry to put ugly code here (just a little piece)
*/ */
public class ToDoConstants { public class ToDoConstants {
// FIXES for 0.1 versions :
// 1. Map tile downloader :
// while(!threadPoolExecutor.getQueue().isEmpty()){
// try {
// threadPoolExecutor.getQueue().take();
// } catch (InterruptedException e) {
// }
// }
/** /**
* Write activity to show something about authors / donation .... * Write activity to show something about authors / donation ....
@ -22,7 +14,6 @@ public class ToDoConstants {
public int DESCRIBE_ABOUT_AUTHORS = 8; public int DESCRIBE_ABOUT_AUTHORS = 8;
// TODO ANDROID // TODO ANDROID
// 42. Revise UI (icons/layouts). Support different devices. Add inactive/focus(!) icon versions. // 42. Revise UI (icons/layouts). Support different devices. Add inactive/focus(!) icon versions.
// Some icons are not fine (as back menu from map - it is blured). // Some icons are not fine (as back menu from map - it is blured).
@ -38,27 +29,25 @@ public class ToDoConstants {
// FUTURE RELEASES // FUTURE RELEASES
// 49. Calculate route from specified point (not from your location only)
// 48. Enable change favorite point : (for example fav - "car") means last point you left car. It is not static point, // 48. Enable change favorite point : (for example fav - "car") means last point you left car. It is not static point,
// you can always use the same name for different locations. // you can always use the same name for different locations.
// 50. Invent opening hours editor in order to edit POI hours better on device // 51. Implement console application that prepare indexes to upload on server...
// 48. Implement console application that prepare indexes to upload on server...
// 0) run in background 1) download from internet 2) generates indices for Europe (take care about memory) 3) upload? // 0) run in background 1) download from internet 2) generates indices for Europe (take care about memory) 3) upload?
// 50. Invent opening hours editor in order to edit POI hours better on device
// 52. Make good distribution of POI on map (when POI a lot they are coupling in one place on the south)
// 43. Enable poi filter by name // 43. Enable poi filter by name
// 46. Implement downloading strategy for tiles : select max zoom to download [16,15,14,...]
// That means you can save internet because from [16 -> zoom -> 18], [14 -> zoom -> 16 - suitable for speed > 40], ...
// 45. Get clear <Use internet> settings. Move that setting on top settings screen. // 45. Get clear <Use internet> settings. Move that setting on top settings screen.
// That setting should rule all activities that use internet. It should ask whenever internet is used // That setting should rule all activities that use internet. It should ask whenever internet is used
// (would you like to use internet for that operation - if using internet is not checked). // (would you like to use internet for that operation - if using internet is not checked).
// Internet using now for : edit POI osm, show osm bugs layer, download tiles. // Internet using now for : edit POI osm, show osm bugs layer, download tiles.
// 47. Internet connectivity could be checked before trying to use // 47. Internet connectivity could be checked before trying to use
// 46. Implement downloading strategy for tiles (do not load 17 zoom, load only 16 for example) - try to scale 15 zoom for 17 (?)
// 40. Support simple vector road rendering (require new index file) (?) // 40. Support simple vector road rendering (require new index file) (?)
// 26. Show the whole street on map (when it is chosen in search activity). Possibly extend that story to show layer with streets. (?) // 26. Show the whole street on map (when it is chosen in search activity). Possibly extend that story to show layer with streets. (?)
// BUGS Android // BUGS Android
// 5. Improvement : Implement caching files existing on FS, implement specific method in RM
// Introducing cache of file names that are on disk (creating new File() consumes a lot of memory)
// TODO swing // TODO swing
// 9. Fix issues with big files (such as netherlands) - save memory (!) - very slow due to transport index ! // 9. Fix issues with big files (such as netherlands) - save memory (!) - very slow due to transport index !
@ -70,6 +59,7 @@ public class ToDoConstants {
// BUGS Swing // BUGS Swing
// DONE ANDROID : // DONE ANDROID :
// 49. Calculate route from specified point (not from your location only)
// 37. Get rid of exit button (!). Think about when notification should go & how clear resources if it is necessary // 37. Get rid of exit button (!). Think about when notification should go & how clear resources if it is necessary
// DONE : add to app settings preference (Refresh indexes). // DONE : add to app settings preference (Refresh indexes).
// 31. Translation. // 31. Translation.

View file

@ -58,7 +58,8 @@ public class TileSourceManager {
@Override @Override
public String getUrlToLoad(int x, int y, int zoom) { public String getUrlToLoad(int x, int y, int zoom) {
return MessageFormat.format(urlToLoad, zoom, x, y); // use int to string not format numbers! (non-nls)
return MessageFormat.format(urlToLoad, zoom+"", x+"", y+""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
} }

View file

@ -45,4 +45,6 @@ poi_filter_for_tourists = For tourists
poi_filter_fuel = Fuel poi_filter_fuel = Fuel
reading_cached_tiles = Reading cached tiles...
version_index_is_not_supported = The version of index ''{0}'' is not supported version_index_is_not_supported = The version of index ''{0}'' is not supported

View file

@ -45,4 +45,6 @@ poi_filter_for_tourists = \u0414\u043B\u044F \u0442\u0443\u0440\u0438\u0441\u044
poi_filter_fuel = \u0417\u0430\u043F\u0440\u0430\u0432\u043A\u0438 poi_filter_fuel = \u0417\u0430\u043F\u0440\u0430\u0432\u043A\u0438
reading_cached_tiles = \u0427\u0442\u0435\u043D\u0438\u0435 \u043A\u044D\u0448\u0438\u0440\u043E\u0432\u0430\u043D\u043D\u044B\u0445 \u0442\u0430\u0439\u043B\u043E\u0432...
version_index_is_not_supported = \u0412\u0435\u0440\u0441\u0438\u044F \u0438\u043D\u0434\u0435\u043A\u0441\u0430 ''{0}'' \u043D\u0435 \u043F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044F version_index_is_not_supported = \u0412\u0435\u0440\u0441\u0438\u044F \u0438\u043D\u0434\u0435\u043A\u0441\u0430 ''{0}'' \u043D\u0435 \u043F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044F

View file

@ -5,7 +5,7 @@
<item android:title="@string/mark_point" android:id="@+id/map_mark_point" android:icon="@android:drawable/ic_menu_mylocation"></item> <item android:title="@string/mark_point" android:id="@+id/map_mark_point" android:icon="@android:drawable/ic_menu_mylocation"></item>
<item android:title="@string/show_gps_status" android:id="@+id/map_show_gps_status" android:icon="@android:drawable/ic_menu_compass"></item> <item android:title="@string/show_gps_status" android:id="@+id/map_show_gps_status" android:icon="@android:drawable/ic_menu_compass"></item>
<item android:id="@+id/map_navigate_to_point" android:title="@string/stop_navigation" android:visible="false" android:icon="@android:drawable/ic_menu_close_clear_cancel"></item> <item android:id="@+id/map_navigate_to_point" android:title="@string/stop_navigation" android:visible="false" android:icon="@android:drawable/ic_menu_close_clear_cancel"></item>
<item android:id="@+id/map_reload_tile" android:title="@string/update_tile" android:icon="@android:drawable/ic_menu_view"></item> <item android:id="@+id/map_get_directions" android:title="@string/get_directions" android:icon="@android:drawable/ic_menu_directions"></item>
<item android:title="@string/map_specify_point" android:id="@+id/map_specify_point" android:icon="@android:drawable/ic_menu_search"></item> <item android:title="@string/map_specify_point" android:id="@+id/map_specify_point" android:icon="@android:drawable/ic_menu_search"></item>
<item android:id="@+id/map_show_settings" android:title="@string/settings_Button" android:icon="@android:drawable/ic_menu_preferences"></item> <item android:id="@+id/map_show_settings" android:title="@string/settings_Button" android:icon="@android:drawable/ic_menu_preferences"></item>
</group> </group>

View file

@ -1,5 +1,11 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<string name="only_show">Только показать</string>
<string name="follow">Следовать</string>
<string name="recalculate_route_to_your_location">Пересчитывать маршрут в зависимости от местоположения</string>
<string name="follow_route">Следовать по маршруту</string>
<string name="mark_final_location_first">Отметьте сначала точку назначения</string>
<string name="get_directions">Маршрут</string>
<string name="gps_status_app_not_found">Приложение Gps status не найдено</string> <string name="gps_status_app_not_found">Приложение Gps status не найдено</string>
<string name="show_gps_status">GPS статус</string> <string name="show_gps_status">GPS статус</string>
<string name="opening_hours">Рабочие часы: </string> <string name="opening_hours">Рабочие часы: </string>
@ -128,7 +134,7 @@
<string name="interval_30_seconds">30 секунд</string> <string name="interval_30_seconds">30 секунд</string>
<string name="interval_1_minute">1 минута</string> <string name="interval_1_minute">1 минута</string>
<string name="interval_5_minutes">5 минут</string> <string name="interval_5_minutes">5 минут</string>
<string name="navigate_point_top_text">Введите широту и долготу в выбранном формате (Г - градусы, М - минуты, С - секунды)</string> <string name="navigate_point_top_text">Введите широту и долготу в формате (Г - градусы, М - минуты, С - секунды)</string>
<string name="navigate_point_latitude">Широта</string> <string name="navigate_point_latitude">Широта</string>
<string name="navigate_point_longitude">Долгота</string> <string name="navigate_point_longitude">Долгота</string>
<string name="navigate_point_format_D">ГГГ.ГГГГ</string> <string name="navigate_point_format_D">ГГГ.ГГГГ</string>
@ -158,7 +164,7 @@
<string name="add_favorite_dialog_favourite_added_template">Точка '{0}' была успешно добавлена к Избранным.</string> <string name="add_favorite_dialog_favourite_added_template">Точка '{0}' была успешно добавлена к Избранным.</string>
<string name="favourites_context_menu_title">Контекстное меню</string> <string name="favourites_context_menu_title">Контекстное меню</string>
<string name="favourites_context_menu_navigate">Показать</string> <string name="favourites_context_menu_navigate">Идти к</string>
<string name="favourites_context_menu_edit">Редактировать точку</string> <string name="favourites_context_menu_edit">Редактировать точку</string>
<string name="favourites_context_menu_delete">Удалить точку</string> <string name="favourites_context_menu_delete">Удалить точку</string>
<string name="favourites_edit_dialog_title">Введите новое имя точки</string> <string name="favourites_edit_dialog_title">Введите новое имя точки</string>

View file

@ -1,5 +1,11 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<string name="only_show">Only show</string>
<string name="follow">Follow</string>
<string name="recalculate_route_to_your_location">Recalculate route according to your location</string>
<string name="follow_route">Follow to the route</string>
<string name="mark_final_location_first">Please mark point navigate to first</string>
<string name="get_directions">Directions</string>
<string name="gps_status_app_not_found">Gps status app could not be found</string> <string name="gps_status_app_not_found">Gps status app could not be found</string>
<string name="show_gps_status">Show gps status</string> <string name="show_gps_status">Show gps status</string>
<string name="opening_hours">Opening hours : </string> <string name="opening_hours">Opening hours : </string>

View file

@ -55,6 +55,7 @@ public class ResourceManager {
protected final int maxImgCacheSize = 64; protected final int maxImgCacheSize = 64;
protected Map<String, Bitmap> cacheOfImages = new LinkedHashMap<String, Bitmap>(); protected Map<String, Bitmap> cacheOfImages = new LinkedHashMap<String, Bitmap>();
protected Map<String, Boolean> imagesOnFS = new LinkedHashMap<String, Boolean>() ;
protected File dirWithTiles ; protected File dirWithTiles ;
@ -82,52 +83,99 @@ public class ResourceManager {
////////////////////////////////////////////// Working with tiles //////////////////////////////////////////////// ////////////////////////////////////////////// Working with tiles ////////////////////////////////////////////////
public Bitmap getTileImageForMapAsync(ITileSource map, int x, int y, int zoom, boolean loadFromInternetIfNeeded) { public void indexingImageTiles(IProgress progress){
return getTileImageForMap(map, x, y, zoom, loadFromInternetIfNeeded, false, true); progress.startTask(Messages.getMessage("reading_cached_tiles"), -1); //$NON-NLS-1$
imagesOnFS.clear();
for(File c : dirWithTiles.listFiles()){
indexImageTilesFS("", c); //$NON-NLS-1$
}
}
private void indexImageTilesFS(String prefix, File f){
if(f.isDirectory()){
for(File c : f.listFiles()){
indexImageTilesFS(prefix +f.getName() +"/" , c); //$NON-NLS-1$
}
} else if(f.getName().endsWith(".tile")){ //$NON-NLS-1$
imagesOnFS.put(prefix + f.getName(), Boolean.TRUE);
}
} }
public Bitmap getTileImageFromCache(ITileSource map, int x, int y, int zoom){ public Bitmap getTileImageForMapAsync(String file, ITileSource map, int x, int y, int zoom, boolean loadFromInternetIfNeeded) {
return getTileImageForMap(map, x, y, zoom, false, false, false); return getTileImageForMap(file, map, x, y, zoom, loadFromInternetIfNeeded, false, true);
} }
public Bitmap getTileImageForMapSync(ITileSource map, int x, int y, int zoom, boolean loadFromInternetIfNeeded) {
return getTileImageForMap(map, x, y, zoom, loadFromInternetIfNeeded, true, true); public Bitmap getTileImageFromCache(String file){
return cacheOfImages.get(file);
} }
public boolean tileExistOnFileSystem(ITileSource map, int x, int y, int zoom){
// TODO implement public Bitmap getTileImageForMapSync(String file, ITileSource map, int x, int y, int zoom, boolean loadFromInternetIfNeeded) {
return false; return getTileImageForMap(file, map, x, y, zoom, loadFromInternetIfNeeded, true, true);
} }
public void clearTileImageForMap(ITileSource map, int x, int y, int zoom){ public synchronized void tileDownloaded(String file){
getTileImageForMap(map, x, y, zoom, true, false, false, true); imagesOnFS.put(file, Boolean.TRUE);
} }
protected Bitmap getTileImageForMap(ITileSource map, int x, int y, int zoom,
public synchronized boolean tileExistOnFileSystem(String file){
if(!imagesOnFS.containsKey(file)){
if(new File(dirWithTiles, file).exists()){
imagesOnFS.put(file, Boolean.TRUE);
} else {
imagesOnFS.put(file, null);
}
}
return imagesOnFS.get(file) != null;
}
public void clearTileImageForMap(String file, ITileSource map, int x, int y, int zoom){
getTileImageForMap(file, map, x, y, zoom, true, false, true, true);
}
/**
* @param file - null could be passed if you do not call very often with that param
*/
protected Bitmap getTileImageForMap(String file, ITileSource map, int x, int y, int zoom,
boolean loadFromInternetIfNeeded, boolean sync, boolean loadFromFs) { boolean loadFromInternetIfNeeded, boolean sync, boolean loadFromFs) {
return getTileImageForMap(map, x, y, zoom, loadFromInternetIfNeeded, sync, loadFromFs, false); return getTileImageForMap(file, map, x, y, zoom, loadFromInternetIfNeeded, sync, loadFromFs, false);
} }
// introduce cache in order save memory // introduce cache in order save memory
protected StringBuilder builder = new StringBuilder(40); protected StringBuilder builder = new StringBuilder(40);
protected synchronized Bitmap getTileImageForMap(ITileSource map, int x, int y, int zoom, public synchronized String calculateTileId(ITileSource map, int x, int y, int zoom){
boolean loadFromInternetIfNeeded, boolean sync, boolean loadFromFs, boolean deleteBefore) {
if (map == null) {
return null;
}
builder.setLength(0); builder.setLength(0);
builder.append(map.getName()).append('/').append(zoom). append('/').append(x). builder.append(map.getName()).append('/').append(zoom). append('/').append(x).
append('/').append(y).append(map.getTileFormat()).append(".tile"); //$NON-NLS-1$ append('/').append(y).append(map.getTileFormat()).append(".tile"); //$NON-NLS-1$
String file = builder.toString(); String file = builder.toString();
return file;
}
protected synchronized Bitmap getTileImageForMap(String file, ITileSource map, int x, int y, int zoom,
boolean loadFromInternetIfNeeded, boolean sync, boolean loadFromFs, boolean deleteBefore) {
if (file == null) {
file = calculateTileId(map, x, y, zoom);
if(file == null){
return null;
}
}
if(deleteBefore){ if(deleteBefore){
cacheOfImages.remove(file); cacheOfImages.remove(file);
File f = new File(dirWithTiles, file); File f = new File(dirWithTiles, file);
if(f.exists()){ if(f.exists()){
f.delete(); f.delete();
imagesOnFS.put(file, null);
} }
} }
if (loadFromFs && cacheOfImages.get(file) == null) { if (loadFromFs && cacheOfImages.get(file) == null) {
if(!loadFromInternetIfNeeded && !tileExistOnFileSystem(file)){
return null;
}
String url = loadFromInternetIfNeeded ? map.getUrlToLoad(x, y, zoom) : null; String url = loadFromInternetIfNeeded ? map.getUrlToLoad(x, y, zoom) : null;
TileLoadDownloadRequest req = new TileLoadDownloadRequest(dirWithTiles, file, url, new File(dirWithTiles, file), TileLoadDownloadRequest req = new TileLoadDownloadRequest(dirWithTiles, file, url, new File(dirWithTiles, file),
x, y, zoom); x, y, zoom);
@ -177,6 +225,8 @@ public class ResourceManager {
public List<String> reloadIndexes(IProgress progress){ public List<String> reloadIndexes(IProgress progress){
close(); close();
// do it lazy
// indexingImageTiles(progress);
List<String> warnings = new ArrayList<String>(); List<String> warnings = new ArrayList<String>();
warnings.addAll(indexingPoi(progress)); warnings.addAll(indexingPoi(progress));
warnings.addAll(indexingAddresses(progress)); warnings.addAll(indexingAddresses(progress));
@ -296,6 +346,7 @@ public class ResourceManager {
} }
public synchronized void close(){ public synchronized void close(){
imagesOnFS.clear();
closeAmenities(); closeAmenities();
closeAddresses(); closeAddresses();
} }

View file

@ -24,6 +24,7 @@ import android.location.Location;
import android.location.LocationListener; import android.location.LocationListener;
import android.location.LocationManager; import android.location.LocationManager;
import android.location.LocationProvider; import android.location.LocationProvider;
import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.os.PowerManager; import android.os.PowerManager;
import android.os.PowerManager.WakeLock; import android.os.PowerManager.WakeLock;
@ -50,6 +51,8 @@ import com.osmand.activities.FavouritesActivity.FavouritePoint;
import com.osmand.activities.FavouritesActivity.FavouritesDbHelper; import com.osmand.activities.FavouritesActivity.FavouritesDbHelper;
import com.osmand.activities.search.SearchActivity; import com.osmand.activities.search.SearchActivity;
import com.osmand.data.preparation.MapTileDownloader; import com.osmand.data.preparation.MapTileDownloader;
import com.osmand.data.preparation.MapTileDownloader.DownloadRequest;
import com.osmand.data.preparation.MapTileDownloader.IMapDownloaderCallback;
import com.osmand.map.IMapLocationListener; import com.osmand.map.IMapLocationListener;
import com.osmand.osm.LatLon; import com.osmand.osm.LatLon;
import com.osmand.osm.MapUtils; import com.osmand.osm.MapUtils;
@ -65,7 +68,12 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat
private static final String GPS_STATUS_ACTIVITY = "com.eclipsim.gpsstatus2.GPSStatus"; //$NON-NLS-1$ private static final String GPS_STATUS_ACTIVITY = "com.eclipsim.gpsstatus2.GPSStatus"; //$NON-NLS-1$
private static final String GPS_STATUS_COMPONENT = "com.eclipsim.gpsstatus2"; //$NON-NLS-1$ private static final String GPS_STATUS_COMPONENT = "com.eclipsim.gpsstatus2"; //$NON-NLS-1$
// private static final String GPS_STATUS_ACTIVITY = "com.eclipsim.gpsstatus2"; //$NON-NLS-1$
private static final int GPS_TIMEOUT_REQUEST = 2000;
private static final int GPS_DIST_REQUEST = 5;
private boolean providerSupportsBearing = false;
private boolean providerSupportsSpeed = false;
/** Called when the activity is first created. */ /** Called when the activity is first created. */
private OsmandMapTileView mapView; private OsmandMapTileView mapView;
@ -80,13 +88,13 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat
private OsmBugsLayer osmBugsLayer; private OsmBugsLayer osmBugsLayer;
private SavingTrackHelper savingTrackHelper; private SavingTrackHelper savingTrackHelper;
private RoutingHelper routingHelper; private RoutingHelper routingHelper;
private boolean calculateRouteOnGps = true;
private RouteLayer routeLayer; private RouteLayer routeLayer;
private WakeLock wakeLock; private WakeLock wakeLock;
private boolean sensorRegistered = false; private boolean sensorRegistered = false;
private MenuItem navigateToPointMenu; private MenuItem navigateToPointMenu;
private NotificationManager mNotificationManager; private NotificationManager mNotificationManager;
private int APP_NOTIFICATION_ID; private int APP_NOTIFICATION_ID;
@ -120,7 +128,18 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat
setContentView(R.layout.main); setContentView(R.layout.main);
mapView = (OsmandMapTileView) findViewById(R.id.MapView); mapView = (OsmandMapTileView) findViewById(R.id.MapView);
MapTileDownloader.getInstance().addDownloaderCallback(mapView); MapTileDownloader.getInstance().addDownloaderCallback(new IMapDownloaderCallback(){
@Override
public void tileDownloaded(DownloadRequest request) {
if(request != null && !request.error && request.fileToSave != null){
ResourceManager mgr = ResourceManager.getResourceManager();
String tile = mgr.calculateTileId(mapView.getMap(), request.xTile, request.yTile, request.zoom);
mgr.tileDownloaded(tile);
}
mapView.tileDownloaded(request);
}
});
mapView.setMapLocationListener(this); mapView.setMapLocationListener(this);
poiMapLayer = new POIMapLayer(); poiMapLayer = new POIMapLayer();
mapView.addLayer(poiMapLayer); mapView.addLayer(poiMapLayer);
@ -145,7 +164,10 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat
LatLon pointToNavigate = OsmandSettings.getPointToNavigate(this); LatLon pointToNavigate = OsmandSettings.getPointToNavigate(this);
if(OsmandSettings.isUsingInternetToCalculateRoute(this)){ if(OsmandSettings.isUsingInternetToCalculateRoute(this)){
routingHelper.setAppMode(OsmandSettings.getApplicationMode(this)); routingHelper.setAppMode(OsmandSettings.getApplicationMode(this));
calculateRouteOnGps = true;
routingHelper.setFinalLocation(pointToNavigate); routingHelper.setFinalLocation(pointToNavigate);
} else {
routingHelper.setFinalLocation(null);
} }
navigationLayer.setPointToNavigate(pointToNavigate); navigationLayer.setPointToNavigate(pointToNavigate);
@ -279,8 +301,7 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat
public void setLocation(Location location){ private void registerUnregisterSensor(Location location){
// show point view only if gps enabled // show point view only if gps enabled
if(location == null){ if(location == null){
if(sensorRegistered) { if(sensorRegistered) {
@ -300,22 +321,35 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat
sensorRegistered = true; sensorRegistered = true;
} }
} }
// TODO delete !!! (only for test purposes) devices support that information (possibly keep for other providers?) }
if(!location.hasSpeed() && locationLayer.getLastKnownLocation() != null){
private void updateSpeedBearing(Location location) {
// For gps it's bad way. It's widely used for testing purposes
if(!providerSupportsSpeed && locationLayer.getLastKnownLocation() != null){
if (locationLayer.getLastKnownLocation().distanceTo(location) > 3) {
float d = location.distanceTo(locationLayer.getLastKnownLocation()); float d = location.distanceTo(locationLayer.getLastKnownLocation());
if(d > 100){ if (d > 100) {
d = 100; d = 100;
} }
location.setSpeed(d); location.setSpeed(d);
} }
if(!location.hasBearing() && locationLayer.getLastKnownLocation() != null){ }
if(!providerSupportsBearing && locationLayer.getLastKnownLocation() != null){
if(locationLayer.getLastKnownLocation().distanceTo(location) > 10){ if(locationLayer.getLastKnownLocation().distanceTo(location) > 10){
location.setBearing(locationLayer.getLastKnownLocation().bearingTo(location)); location.setBearing(locationLayer.getLastKnownLocation().bearingTo(location));
} }
} }
}
public void setLocation(Location location){
registerUnregisterSensor(location);
updateSpeedBearing(location);
locationLayer.setLastKnownLocation(location); locationLayer.setLastKnownLocation(location);
if(calculateRouteOnGps){
routingHelper.setCurrentLocation(location); routingHelper.setCurrentLocation(location);
}
if (location != null) { if (location != null) {
if (isMapLinkedToLocation()) { if (isMapLinkedToLocation()) {
if(OsmandSettings.isAutoZoomEnabled(this) && location.hasSpeed()){ if(OsmandSettings.isAutoZoomEnabled(this) && location.hasSpeed()){
@ -344,13 +378,15 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat
speed *= 3.6; speed *= 3.6;
if(speed < 4){ if(speed < 4){
return currentZoom; return currentZoom;
} else if(speed < 20){ } else if(speed < 30){
// less than 30 - show 17
return 17; return 17;
} else if(speed < 45){ } else if(speed < 50){
return 16; return 16;
} else if(speed < 80){ } else if(speed < 80){
return 15; return 15;
} }
// more than 80 - show 14 (it is slow)
return 14; return 14;
} }
@ -360,10 +396,11 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat
} else { } else {
OsmandSettings.clearPointToNavigate(this); OsmandSettings.clearPointToNavigate(this);
} }
if(OsmandSettings.isUsingInternetToCalculateRoute(this)){
calculateRouteOnGps = true;
routingHelper.setFinalLocation(point); routingHelper.setFinalLocation(point);
// TODO do it more clear } else {
if(routingHelper.getLastFixedLocation() != null){ routingHelper.setFinalLocation(null);
routingHelper.setCurrentLocation(routingHelper.getLastFixedLocation());
} }
navigationLayer.setPointToNavigate(point); navigationLayer.setPointToNavigate(point);
updateNavigateToPointMenu(); updateNavigateToPointMenu();
@ -404,11 +441,34 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat
public void onProviderEnabled(String provider) { public void onProviderEnabled(String provider) {
} }
private boolean isRunningOnEmulator(){
if (Build.DEVICE.equals("generic")) { //$NON-NLS-1$
return true;
}
return false;
}
@Override @Override
public void onStatusChanged(String provider, int status, Bundle extras) { public void onStatusChanged(String provider, int status, Bundle extras) {
LocationManager service = (LocationManager) getSystemService(LOCATION_SERVICE);
if (LocationManager.GPS_PROVIDER.equals(provider)) {
LocationProvider prov = service.getProvider(LocationManager.NETWORK_PROVIDER);
if (LocationProvider.OUT_OF_SERVICE == status || LocationProvider.TEMPORARILY_UNAVAILABLE == status) {
if(LocationProvider.OUT_OF_SERVICE == status){ if(LocationProvider.OUT_OF_SERVICE == status){
setLocation(null); setLocation(null);
} }
service.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, GPS_TIMEOUT_REQUEST, GPS_DIST_REQUEST, this);
providerSupportsBearing = prov == null ? false : prov.supportsBearing() && !isRunningOnEmulator();
providerSupportsSpeed = prov == null ? false : prov.supportsSpeed() && !isRunningOnEmulator();
} else if (LocationProvider.AVAILABLE == status) {
service.removeUpdates(this);
service.requestLocationUpdates(LocationManager.GPS_PROVIDER, GPS_TIMEOUT_REQUEST, GPS_DIST_REQUEST, this);
prov = service.getProvider(LocationManager.GPS_PROVIDER);
providerSupportsBearing = prov == null ? false : prov.supportsBearing() && !isRunningOnEmulator();
providerSupportsSpeed = prov == null ? false : prov.supportsSpeed() && !isRunningOnEmulator();
}
}
} }
@ -470,7 +530,16 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat
} }
LocationManager service = (LocationManager) getSystemService(LOCATION_SERVICE); LocationManager service = (LocationManager) getSystemService(LOCATION_SERVICE);
service.requestLocationUpdates(LocationManager.GPS_PROVIDER, 2000, 0, this);
service.requestLocationUpdates(LocationManager.GPS_PROVIDER, GPS_TIMEOUT_REQUEST, GPS_DIST_REQUEST, this);
LocationProvider prov = service.getProvider(LocationManager.GPS_PROVIDER);
if(!service.isProviderEnabled(LocationManager.GPS_PROVIDER)){
service.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, GPS_TIMEOUT_REQUEST, GPS_DIST_REQUEST, this);
prov = service.getProvider(LocationManager.NETWORK_PROVIDER);
}
providerSupportsBearing = prov == null ? false : prov.supportsBearing() && !isRunningOnEmulator();
providerSupportsSpeed = prov == null ? false : prov.supportsSpeed() && !isRunningOnEmulator();
if (wakeLock == null) { if (wakeLock == null) {
@ -559,8 +628,8 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat
} else if (item.getItemId() == R.id.map_mark_point) { } else if (item.getItemId() == R.id.map_mark_point) {
contextMenuPoint(mapView.getLatitude(), mapView.getLongitude(), true); contextMenuPoint(mapView.getLatitude(), mapView.getLongitude(), true);
return true; return true;
} else if (item.getItemId() == R.id.map_reload_tile) { } else if (item.getItemId() == R.id.map_get_directions) {
reloadTile(mapView.getZoom(), mapView.getLatitude(), mapView.getLongitude()); getDirections(mapView.getLatitude(), mapView.getLongitude());
return true; return true;
} else if (item.getItemId() == R.id.map_specify_point) { } else if (item.getItemId() == R.id.map_specify_point) {
openChangeLocationDialog(); openChangeLocationDialog();
@ -575,6 +644,40 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat
return super.onOptionsItemSelected(item); return super.onOptionsItemSelected(item);
} }
protected void getDirections(final double lat, final double lon){
if(navigationLayer.getPointToNavigate() == null){
Toast.makeText(this, R.string.mark_final_location_first, Toast.LENGTH_LONG).show();
return;
}
Builder builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.follow_route);
builder.setMessage(R.string.recalculate_route_to_your_location);
builder.setPositiveButton(R.string.follow, new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface dialog, int which) {
routingHelper.setFinalLocation(navigationLayer.getPointToNavigate());
Location map = new Location("map"); //$NON-NLS-1$
map.setLatitude(lat);
map.setLongitude(lon);
calculateRouteOnGps = true;
routingHelper.setFinalAndCurrentLocation(navigationLayer.getPointToNavigate(), map);
}
});
builder.setNegativeButton(R.string.only_show, new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface dialog, int which) {
Location map = new Location("map"); //$NON-NLS-1$
map.setLatitude(lat);
map.setLongitude(lon);
calculateRouteOnGps = false;
routingHelper.setFinalAndCurrentLocation(navigationLayer.getPointToNavigate(), map);
}
});
builder.show();
}
protected void reloadTile(final int zoom, final double latitude, final double longitude){ protected void reloadTile(final int zoom, final double latitude, final double longitude){
Builder builder = new AlertDialog.Builder(this); Builder builder = new AlertDialog.Builder(this);
builder.setMessage(R.string.context_menu_item_update_map_confirm); builder.setMessage(R.string.context_menu_item_update_map_confirm);
@ -584,7 +687,7 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
int x = (int) MapUtils.getTileNumberX(zoom, longitude); int x = (int) MapUtils.getTileNumberX(zoom, longitude);
int y = (int) MapUtils.getTileNumberY(zoom, latitude); int y = (int) MapUtils.getTileNumberY(zoom, latitude);
ResourceManager.getResourceManager().clearTileImageForMap(mapView.getMap(), x, y, zoom); ResourceManager.getResourceManager().clearTileImageForMap(null, mapView.getMap(), x, y, zoom);
mapView.refreshMap(); mapView.refreshMap();
} }
}); });
@ -594,23 +697,13 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat
protected void contextMenuPoint(final double latitude, final double longitude, boolean menu){ protected void contextMenuPoint(final double latitude, final double longitude, boolean menu){
Builder builder = new AlertDialog.Builder(this); Builder builder = new AlertDialog.Builder(this);
Resources resources = this.getResources(); Resources resources = this.getResources();
String[] res; String[] res = new String[]{
if(menu){
res = new String[]{
resources.getString(R.string.context_menu_item_navigate_point),
resources.getString(R.string.context_menu_item_add_favorite),
resources.getString(R.string.context_menu_item_open_bug),
resources.getString(R.string.context_menu_item_create_poi),
};
} else {
res = new String[]{
resources.getString(R.string.context_menu_item_navigate_point), resources.getString(R.string.context_menu_item_navigate_point),
resources.getString(R.string.context_menu_item_add_favorite), resources.getString(R.string.context_menu_item_add_favorite),
resources.getString(R.string.context_menu_item_open_bug), resources.getString(R.string.context_menu_item_open_bug),
resources.getString(R.string.context_menu_item_create_poi), resources.getString(R.string.context_menu_item_create_poi),
resources.getString(R.string.context_menu_item_update_map), resources.getString(R.string.context_menu_item_update_map),
}; };
}
builder.setItems(res, new DialogInterface.OnClickListener(){ builder.setItems(res, new DialogInterface.OnClickListener(){
@Override @Override

View file

@ -68,8 +68,16 @@ public class RoutingHelper {
} }
public void setFinalLocation(LatLon finalLocation){
public void setFinalAndCurrentLocation(LatLon finalLocation, Location currentLocation){
this.finalLocation = finalLocation; this.finalLocation = finalLocation;
evalWaitInterval = 3000;
// to update route
setCurrentLocation(currentLocation);
}
public void setFinalLocation(LatLon finalLocation){
setFinalAndCurrentLocation(finalLocation, getLastFixedLocation());
} }
public void setAppMode(ApplicationMode mode){ public void setAppMode(ApplicationMode mode){
@ -94,13 +102,12 @@ public class RoutingHelper {
Location lastPoint = routeNodes.get(routeNodes.size() - 1); Location lastPoint = routeNodes.get(routeNodes.size() - 1);
if(currentRoute > routeNodes.size() - 3 && currentLocation.distanceTo(lastPoint) < 60){ if(currentRoute > routeNodes.size() - 3 && currentLocation.distanceTo(lastPoint) < 60){
if(lastFixedLocation != null && lastFixedLocation.distanceTo(lastPoint) < 60){ if(lastFixedLocation != null && lastFixedLocation.distanceTo(lastPoint) < 60){
// TODO mark as finished
showMessage(activity.getString(R.string.arrived_at_destination)); showMessage(activity.getString(R.string.arrived_at_destination));
currentRoute = routeNodes.size() - 1; currentRoute = routeNodes.size() - 1;
// clear final location to prevent all time showing message
finalLocation = null;
} }
lastFixedLocation = currentLocation; lastFixedLocation = currentLocation;
// ??? even if you go away from place you can't navigate once time
// finalLocation = null
return true; return true;
} }
return false; return false;
@ -234,7 +241,7 @@ public class RoutingHelper {
// reset error wait interval // reset error wait interval
evalWaitInterval = 3000; evalWaitInterval = 3000;
} else { } else {
evalWaitInterval = evalWaitInterval * 3 / 2; evalWaitInterval = evalWaitInterval * 4 / 3;
if(evalWaitInterval > 120000){ if(evalWaitInterval > 120000){
evalWaitInterval = 120000; evalWaitInterval = 120000;
} }

View file

@ -64,7 +64,7 @@ public class MapInfoLayer implements OsmandMapLayer {
paintAlphaGray = new Paint(); paintAlphaGray = new Paint();
paintAlphaGray.setStyle(Style.FILL_AND_STROKE); paintAlphaGray.setStyle(Style.FILL_AND_STROKE);
paintAlphaGray.setColor(Color.LTGRAY); paintAlphaGray.setColor(Color.LTGRAY);
paintAlphaGray.setAlpha(150); paintAlphaGray.setAlpha(180); // do not make very transparent (to hide route)
fillBlack = new Paint(); fillBlack = new Paint();
fillBlack.setStyle(Style.FILL_AND_STROKE); fillBlack.setStyle(Style.FILL_AND_STROKE);
@ -90,7 +90,7 @@ public class MapInfoLayer implements OsmandMapLayer {
boundsForMiniRoute = new RectF(0, 64, 96, 196); boundsForMiniRoute = new RectF(0, 64, 96, 196);
centerMiniRouteX = 48; centerMiniRouteX = 48;
centerMiniRouteY= 160; centerMiniRouteY= 160;
scaleMiniRoute = 0.1f; scaleMiniRoute = 0.15f;
pathForCompass = new Path(); pathForCompass = new Path();
pathForCompass.moveTo(9, 15.5f); pathForCompass.moveTo(9, 15.5f);

View file

@ -376,21 +376,42 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall
for (int j = 0; j< height; j++) { for (int j = 0; j< height; j++) {
float x1 = (i + left - tileX) * tileSize + w; float x1 = (i + left - tileX) * tileSize + w;
float y1 = (j + top - tileY) * tileSize + h; float y1 = (j + top - tileY) * tileSize + h;
String ordImgTile = mgr.calculateTileId(map, left + i, top + j, zoom);
// asking tile image async // asking tile image async
Bitmap bmp = mgr.getTileImageForMapAsync(map, left + i, top + j, zoom, useInternet); boolean imgExist = mgr.tileExistOnFileSystem(ordImgTile);
if (bmp == null) { Bitmap bmp = null;
// asking if there is small version of the map (in cache) if (imgExist || useInternet) {
if(useInternet){ bmp = mgr.getTileImageForMapAsync(ordImgTile, map, left + i, top + j, zoom, useInternet);
bmp = mgr.getTileImageFromCache(map, (left + i) / 2, (top + j) / 2, zoom - 1);
} else if(!mgr.tileExistOnFileSystem(map, left + i, top + j, zoom)){
bmp = mgr.getTileImageForMapAsync(map, (left + i) / 2, (top + j) / 2, zoom - 1, false);
} }
if (bmp == null) {
int div = 2;
// asking if there is small version of the map (in cache)
String imgTile2 = mgr.calculateTileId(map, (left + i) / 2, (top + j) / 2, zoom - 1);
String imgTile4 = mgr.calculateTileId(map, (left + i) / 4, (top + j) / 4, zoom - 2);
if(useInternet || imgExist){
bmp = mgr.getTileImageFromCache(imgTile2);
div = 2;
if(bmp == null){
bmp = mgr.getTileImageFromCache(imgTile4);
div = 4;
}
}
if(!useInternet && !imgExist){
if(mgr.tileExistOnFileSystem(imgTile2)){
bmp = mgr.getTileImageForMapAsync(imgTile2, map, (left + i) / 2, (top + j) / 2, zoom - 1, false);
div = 2;
} else if(mgr.tileExistOnFileSystem(imgTile4)){
bmp = mgr.getTileImageForMapAsync(imgTile4, map, (left + i) / 4, (top + j) / 4, zoom - 2, false);
div = 4;
}
}
if(bmp == null){ if(bmp == null){
drawEmptyTile(canvas, (int) x1, (int) y1); drawEmptyTile(canvas, (int) x1, (int) y1);
} else { } else {
int xZoom = (left + i) % 2 == 0 ? 0 : tileSize / 2; int xZoom = ((left + i) % div) * tileSize / div;
int yZoom = (top + j) % 2 == 0 ? 0 : tileSize / 2;; int yZoom = ((top + j) % div) * tileSize / div;;
bitmapToZoom.set(xZoom, yZoom, xZoom + tileSize / 2, yZoom + tileSize / 2); bitmapToZoom.set(xZoom, yZoom, xZoom + tileSize / div, yZoom + tileSize / div);
bitmapToDraw.set(x1, y1, x1 + tileSize, y1 + tileSize); bitmapToDraw.set(x1, y1, x1 + tileSize, y1 + tileSize);
canvas.drawBitmap(bmp, bitmapToZoom, bitmapToDraw, paintBitmap); canvas.drawBitmap(bmp, bitmapToZoom, bitmapToDraw, paintBitmap);
} }
@ -458,7 +479,7 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall
canvas.rotate(rotate, w , h); canvas.rotate(rotate, w , h);
try { try {
ResourceManager mgr = ResourceManager.getResourceManager(); ResourceManager mgr = ResourceManager.getResourceManager();
Bitmap bmp = mgr.getTileImageForMapSync(map, request.xTile, request.yTile, zoom, false); Bitmap bmp = mgr.getTileImageForMapSync(null, map, request.xTile, request.yTile, request.zoom, false);
float x = (request.xTile - tileX) * getTileSize() + w; float x = (request.xTile - tileX) * getTileSize() + w;
float y = (request.yTile - tileY) * getTileSize() + h; float y = (request.yTile - tileY) * getTileSize() + h;
if (bmp == null) { if (bmp == null) {

View file

@ -119,8 +119,8 @@ public class POIMapLayer implements OsmandMapLayer {
this.view = view; this.view = view;
pointAltUI = new Paint(); pointAltUI = new Paint();
pointAltUI.setColor(Color.GREEN); pointAltUI.setColor(Color.rgb(255, 128, 0));
pointAltUI.setAlpha(150); pointAltUI.setAlpha(200);
pointAltUI.setAntiAlias(true); pointAltUI.setAntiAlias(true);
resourceManager = ResourceManager.getResourceManager(); resourceManager = ResourceManager.getResourceManager();
pixRect.set(0, 0, view.getWidth(), view.getHeight()); pixRect.set(0, 0, view.getWidth(), view.getHeight());

View file

@ -79,7 +79,7 @@ public class RouteLayer implements OsmandMapLayer {
int px = view.getMapXForPoint(points.get(0).getLongitude()); int px = view.getMapXForPoint(points.get(0).getLongitude());
int py = view.getMapYForPoint(points.get(0).getLatitude()); int py = view.getMapYForPoint(points.get(0).getLatitude());
path.moveTo(px, py); path.moveTo(px, py);
for (int i=1; i<points.size(); i++) { for (int i = 1; i < points.size(); i++) {
Location o = points.get(i); Location o = points.get(i);
int x = view.getMapXForPoint(o.getLongitude()); int x = view.getMapXForPoint(o.getLongitude());
int y = view.getMapYForPoint(o.getLatitude()); int y = view.getMapYForPoint(o.getLatitude());