diff --git a/DataExtractionOSM/src/com/osmand/ToDoConstants.java b/DataExtractionOSM/src/com/osmand/ToDoConstants.java index f81db5b6a1..d4a58bacd7 100644 --- a/DataExtractionOSM/src/com/osmand/ToDoConstants.java +++ b/DataExtractionOSM/src/com/osmand/ToDoConstants.java @@ -13,27 +13,28 @@ public class ToDoConstants { public int DESCRIBE_ABOUT_AUTHORS = 8; // TODO ANDROID -// 1. POI search near to map location (show categories & type). First cut. (implement incremental search) -// 3. Revise osmand UI. Preparing new icons. -// 2. Showing compass on the map : use device compass if exists(?) -// 5. Search for city/streets/buildings -// 9. Configure file log & see log from file (when exception happened to see from device) -// 11. Print out additional info speed, altitude, number of satellites -// 8. Enable change POI directly on map (requires OSM login) +// 25. POI search near to map location (show categories & type). Second cut. (implement incremental search) + +// 3. Revise osmand UI. Preparing new icons (revise UI 18, 2, ). // 13. Save point as favorite & introduce favorite points dialog // 14. Show zoom level on map + +// 24. Implement ResourceManager, load cities/streets/buildings on Low memory (clear previous all addresses cities). +// 5. Search for city/streets/buildings +// 9. Configure file log & see log from file (when exception happened to see from device) // 15. Investigate interruption of any long running operation & implement where it is needed -// 16. Support open street bugs api. -// 17. Enable go to location by specifying coordinates -// 18. Implement go to point -// 19. Show how map is rotated where north/south on map (do not consider compass) -// 20. Implement save track/route to gpx (?) -// 21. Implement zooming tile (if tile doesn't exist local, we can zoom in previous tile). -// 23. Implement moving point from center to bottom (for rotating map). -// It is not very useful to see what was before. -// 24. Implement ResourceManager on Low memory (clear previous all addresses cities, remove all amenities cache) -// Use async loading tile thread, to preload amenities also. +// 17. Enable go to location by specifying coordinates +// 11. Print out additional info speed, altitude, number of satellites +// 19. Show how map is rotated where north/south on map (do not consider compass) +// 23. Implement moving point from center to bottom (for rotating map). (+) + +// 21. Implement zooming tile (if tile doesn't exist local, we can zoom in previous tile). + + +// 8. Enable change POI directly on map (requires OSM login) +// 16. Support open street bugs api. +// 20. Implement save track/route to gpx (?) // FIXME Bugs Android : // 0. FIX TODO for partial loading rotated map @@ -41,6 +42,11 @@ public class ToDoConstants { // No chance to close application // 3. Fix progress information (loading indices) for android version // 4. Fix when POI selected & enable button backToLocation + // 5. Call ResourceManager.close when it is needed + // 6. Understand concept of application where to save/restore global setting + // (for example reset navigate to point, reset link map with location). It should be reset after user call exit. + // 7. Implement search amenities by type (!). + // Rewrite search activity in order to limit amenities not to all types. // TODO SWING: // 1. Download tiles without using dir tiles @@ -49,16 +55,9 @@ public class ToDoConstants { // DONE ANDROID : -// 12. Show information of where are you going (the arrow on the map) -// 10. Specify auto-rotating map (bearing of your direction) -// 22. Investigate 3D tile view (how it is done in osmand). Looking not very good, because of -// angle of perspective (best perspective angle = 60) use -// android.graphics.Camera.rotateX(60), getMatrix(m), canvas.concat(m) (find example in internet) -// Problems : to calculate how to drag point on map, to calculate how many tiles are needed, is location visible .... -// 0. Minimize memory used for index & improve time for reading index +// 18. Implement go to point +// 2. Showing compass on the map : use device compass if exists(?) // DONE SWING - // 3. Reinvent index mechanism (save in zip file with tile indexes, save city/town addresses separately, read partially !) - // 4. Invent different file extensions for poi.index, address.index,... } diff --git a/OsmAnd/res/values/strings.xml b/OsmAnd/res/values/strings.xml index f3e1528740..32680fdfbe 100644 --- a/OsmAnd/res/values/strings.xml +++ b/OsmAnd/res/values/strings.xml @@ -1,5 +1,7 @@ + Show aspect of vew based on compass + Show aspect of view Unmark location Mark location Enable 3D view of the map diff --git a/OsmAnd/res/xml/settings_pref.xml b/OsmAnd/res/xml/settings_pref.xml index 0e75b493de..69faa58729 100644 --- a/OsmAnd/res/xml/settings_pref.xml +++ b/OsmAnd/res/xml/settings_pref.xml @@ -6,6 +6,7 @@ + diff --git a/OsmAnd/src/com/osmand/AmenityIndexRepository.java b/OsmAnd/src/com/osmand/AmenityIndexRepository.java index feaebb0467..c7374fe8f9 100644 --- a/OsmAnd/src/com/osmand/AmenityIndexRepository.java +++ b/OsmAnd/src/com/osmand/AmenityIndexRepository.java @@ -58,7 +58,7 @@ public class AmenityIndexRepository { } } while(query.moveToNext()); } - query.deactivate(); + query.close(); if (log.isDebugEnabled()) { log.debug(String.format("Search for %s done in %s ms found %s.", @@ -128,6 +128,12 @@ public class AmenityIndexRepository { } + public void close(){ + if(db != null){ + db.close(); + } + } + public String getName() { return name; } diff --git a/OsmAnd/src/com/osmand/OsmandSettings.java b/OsmAnd/src/com/osmand/OsmandSettings.java index 63b09d8e2e..eca8706ad3 100644 --- a/OsmAnd/src/com/osmand/OsmandSettings.java +++ b/OsmAnd/src/com/osmand/OsmandSettings.java @@ -30,6 +30,13 @@ public class OsmandSettings { return prefs.getBoolean(SHOW_POI_OVER_MAP, false); } + // this value string is synchronized with android.xml preference name + public static final String SHOW_VIEW_ANGLE = "show_view_angle"; + public static boolean isShowingViewAngle(Context ctx){ + SharedPreferences prefs = ctx.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_WORLD_READABLE); + return prefs.getBoolean(SHOW_VIEW_ANGLE, true); + } + // this value string is synchronized with android.xml preference name public static final String ROTATE_MAP_TO_BEARING = "rotate_map_to_bearing"; public static boolean isRotateMapToBearing(Context ctx){ diff --git a/OsmAnd/src/com/osmand/ResourceManager.java b/OsmAnd/src/com/osmand/ResourceManager.java index c308793ac6..761264af1f 100644 --- a/OsmAnd/src/com/osmand/ResourceManager.java +++ b/OsmAnd/src/com/osmand/ResourceManager.java @@ -148,7 +148,7 @@ public class ResourceManager { // POI INDEX // public void indexingPoi(final IProgress progress) { File file = new File(Environment.getExternalStorageDirectory(), POI_PATH); - amenityRepositories.clear(); + clearAmenities(); if (file.exists() && file.canRead()) { for (File f : file.listFiles()) { if (f.getName().endsWith(IndexConstants.POI_INDEX_EXT)) { @@ -164,7 +164,7 @@ public class ResourceManager { public void indexingAddresses(final IProgress progress){ File file = new File(Environment.getExternalStorageDirectory(), ADDRESS_PATH); - addressMap.clear(); + clearAddresses(); if (file.exists() && file.canRead()) { for (File f : file.listFiles()) { if (f.getName().endsWith(IndexConstants.ADDRESS_INDEX_EXT)) { @@ -207,7 +207,24 @@ public class ResourceManager { } ////////////////////////////////////////////// Working with amenities //////////////////////////////////////////////// + + public void clearAmenities(){ + for(AmenityIndexRepository r : amenityRepositories){ + r.close(); + } + amenityRepositories.clear(); + } + + public void clearAddresses(){ + // TODO close db connections + addressMap.clear(); + } + public synchronized void close(){ + clearAmenities(); + clearAddresses(); + } + /// On low memory method /// public void onLowMemory() { log.info("On low memory : cleaning tiles - size = " + cacheOfImages.size()); diff --git a/OsmAnd/src/com/osmand/activities/MapActivity.java b/OsmAnd/src/com/osmand/activities/MapActivity.java index e4f0c44645..6e1267c00d 100644 --- a/OsmAnd/src/com/osmand/activities/MapActivity.java +++ b/OsmAnd/src/com/osmand/activities/MapActivity.java @@ -5,6 +5,10 @@ import java.text.MessageFormat; import android.app.Activity; import android.content.Intent; import android.content.SharedPreferences; +import android.hardware.Sensor; +import android.hardware.SensorEvent; +import android.hardware.SensorEventListener; +import android.hardware.SensorManager; import android.location.Location; import android.location.LocationListener; import android.location.LocationManager; @@ -33,13 +37,12 @@ import com.osmand.views.POIMapLayer; import com.osmand.views.PointLocationLayer; import com.osmand.views.PointNavigationLayer; -public class MapActivity extends Activity implements LocationListener, IMapLocationListener { +public class MapActivity extends Activity implements LocationListener, IMapLocationListener, SensorEventListener { /** Called when the activity is first created. */ private OsmandMapTileView mapView; - private boolean linkLocationWithMap = true; private ImageButton backToLocation; private ImageButton backToMenu; @@ -48,7 +51,16 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat private POIMapLayer poiMapLayer; private WakeLock wakeLock; + private boolean sensorRegistered = false; + private final static String BACK_TO_LOCATION = "BACK_TO_LOCATION"; + private final static String POINT_NAVIGATE_LAT = "POINT_NAVIGATE_LAT"; + private final static String POINT_NAVIGATE_LON = "POINT_NAVIGATE_LON"; + + + private boolean getBackToLocation(){ + return getPreferences(MODE_WORLD_READABLE).getBoolean(BACK_TO_LOCATION, true); + } @Override public void onCreate(Bundle savedInstanceState) { @@ -58,7 +70,6 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat // getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, // WindowManager.LayoutParams.FLAG_FULLSCREEN); - setContentView(R.layout.main); mapView = (OsmandMapTileView) findViewById(R.id.MapView); MapTileDownloader.getInstance().addDownloaderCallback(mapView); @@ -69,6 +80,11 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat mapView.addLayer(navigationLayer); locationLayer = new PointLocationLayer(); mapView.addLayer(locationLayer); + SharedPreferences lprefs = getPreferences(MODE_WORLD_READABLE); + if(lprefs.contains(POINT_NAVIGATE_LAT)){ + navigationLayer.setPointToNavigate(new LatLon(lprefs.getFloat(POINT_NAVIGATE_LAT, 0), + lprefs.getFloat(POINT_NAVIGATE_LON, 0))); + } SharedPreferences prefs = getSharedPreferences(OsmandSettings.SHARED_PREFERENCES_NAME, MODE_WORLD_READABLE); if(prefs != null && prefs.contains(OsmandSettings.LAST_KNOWN_MAP_LAT)){ @@ -99,14 +115,13 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat mapView.setZoom(mapView.getZoom() - 1); } }); - backToLocation = (ImageButton)findViewById(R.id.BackToLocation); - backToLocation.setVisibility(linkLocationWithMap ? View.INVISIBLE : View.VISIBLE); + backToLocation.setVisibility(View.INVISIBLE); backToLocation.setOnClickListener(new OnClickListener(){ @Override public void onClick(View v) { - if(!linkLocationWithMap){ - linkLocationWithMap = true; + if(!getBackToLocation()){ + getPreferences(MODE_WORLD_READABLE).edit().putBoolean(BACK_TO_LOCATION, true).commit(); backToLocation.setVisibility(View.INVISIBLE); if(locationLayer.getLastKnownLocation() != null){ Location lastKnownLocation = locationLayer.getLastKnownLocation(); @@ -132,14 +147,41 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat @Override protected void onDestroy() { super.onDestroy(); + SharedPreferences lprefs = getPreferences(MODE_WORLD_READABLE); + if(navigationLayer.getPointToNavigate() == null){ + lprefs.edit().remove(POINT_NAVIGATE_LAT).remove(POINT_NAVIGATE_LON).commit(); + } else { + LatLon p = navigationLayer.getPointToNavigate(); + lprefs.edit().putFloat(POINT_NAVIGATE_LAT, (float) p.getLatitude()). + putFloat(POINT_NAVIGATE_LON, (float) p.getLongitude()).commit(); + } MapTileDownloader.getInstance().removeDownloaderCallback(mapView); } public void setLocation(Location location){ // Do very strange manipulation to call redraw only once + + // show point view only if gps enabled + if(location == null){ + if(sensorRegistered) { + ((SensorManager) getSystemService(SENSOR_SERVICE)).unregisterListener(this); + sensorRegistered = false; + locationLayer.setHeading(null, true); + } + } else { + if(!sensorRegistered && OsmandSettings.isShowingViewAngle(this)){ + SensorManager sensorMgr = (SensorManager) getSystemService(SENSOR_SERVICE); + Sensor s = sensorMgr.getDefaultSensor(Sensor.TYPE_ORIENTATION); + if (s != null) { + sensorMgr.registerListener(this, s, SensorManager.SENSOR_DELAY_UI); + } + sensorRegistered = true; + } + } + locationLayer.setLastKnownLocation(location, true); if (location != null) { - if (linkLocationWithMap) { + if (getBackToLocation()) { if (location.hasBearing() && OsmandSettings.isRotateMapToBearing(this)) { mapView.setRotateWithLocation(-location.getBearing(), location.getLatitude(), location.getLongitude()); } else { @@ -149,7 +191,7 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat mapView.prepareImage(); } } else { - if (!linkLocationWithMap) { + if (!getBackToLocation()) { backToLocation.setVisibility(View.VISIBLE); } } @@ -195,6 +237,11 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat super.onPause(); LocationManager service = (LocationManager) getSystemService(LOCATION_SERVICE); service.removeUpdates(this); + + SensorManager sensorMgr = (SensorManager) getSystemService(SENSOR_SERVICE); + sensorMgr.unregisterListener(this); + sensorRegistered = false; + OsmandSettings.setLastKnownMapLocation(this, (float) mapView.getLatitude(), (float) mapView.getLongitude()); OsmandSettings.setLastKnownMapZoom(this, mapView.getZoom()); if (wakeLock != null) { @@ -212,6 +259,7 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat if(!OsmandSettings.isRotateMapToBearing(this)){ mapView.setRotate(0); } + if(mapView.getLayers().contains(poiMapLayer) != OsmandSettings.isShowingPoiOverMap(this)){ if(OsmandSettings.isShowingPoiOverMap(this)){ mapView.addLayer(poiMapLayer); @@ -222,6 +270,7 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat LocationManager service = (LocationManager) getSystemService(LOCATION_SERVICE); service.requestLocationUpdates(LocationManager.GPS_PROVIDER, 2000, 0, this); + if (wakeLock == null) { PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE); wakeLock = powerManager.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "com.osmand.map"); @@ -242,7 +291,7 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat public void locationChanged(double newLatitude, double newLongitude, Object source) { // when user start dragging if(locationLayer.getLastKnownLocation() != null){ - linkLocationWithMap = false; + getPreferences(MODE_WORLD_READABLE).edit().putBoolean(BACK_TO_LOCATION, false).commit(); if (backToLocation.getVisibility() != View.VISIBLE) { runOnUiThread(new Runnable() { @Override @@ -284,5 +333,14 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat } return super.onOptionsItemSelected(item); } + + @Override + public void onAccuracyChanged(Sensor sensor, int accuracy) { + } + + @Override + public void onSensorChanged(SensorEvent event) { + locationLayer.setHeading(event.values[0], false); + } } \ No newline at end of file diff --git a/OsmAnd/src/com/osmand/activities/SearchActivity.java b/OsmAnd/src/com/osmand/activities/SearchActivity.java index 2751eba32f..8a8a3feff3 100644 --- a/OsmAnd/src/com/osmand/activities/SearchActivity.java +++ b/OsmAnd/src/com/osmand/activities/SearchActivity.java @@ -70,7 +70,7 @@ public class SearchActivity extends ListActivity { filter = new TreeMap>(); LatLon lastKnownMapLocation = OsmandSettings.getLastKnownMapLocation(this); List closestAmenities = resourceManager.searchAmenities(lastKnownMapLocation.getLatitude(), - lastKnownMapLocation.getLongitude(), 13, 500); + lastKnownMapLocation.getLongitude(), 12, 500); MapUtils.sortListOfMapObject(closestAmenities, lastKnownMapLocation.getLatitude(), lastKnownMapLocation.getLongitude()); for (Amenity n : closestAmenities) { AmenityType type = n.getType(); diff --git a/OsmAnd/src/com/osmand/activities/SettingsActivity.java b/OsmAnd/src/com/osmand/activities/SettingsActivity.java index 4c3794c293..c19a266dea 100644 --- a/OsmAnd/src/com/osmand/activities/SettingsActivity.java +++ b/OsmAnd/src/com/osmand/activities/SettingsActivity.java @@ -24,6 +24,7 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference private CheckBoxPreference useInternetToDownloadTiles; private ListPreference tileSourcePreference; private CheckBoxPreference rotateMapToBearing; + private CheckBoxPreference showViewAngle; @Override public void onCreate(Bundle savedInstanceState) { @@ -36,6 +37,8 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference showPoiOnMap.setOnPreferenceChangeListener(this); rotateMapToBearing =(CheckBoxPreference) screen.findPreference(OsmandSettings.ROTATE_MAP_TO_BEARING); rotateMapToBearing.setOnPreferenceChangeListener(this); + showViewAngle =(CheckBoxPreference) screen.findPreference(OsmandSettings.SHOW_VIEW_ANGLE); + showViewAngle.setOnPreferenceChangeListener(this); tileSourcePreference =(ListPreference) screen.findPreference(OsmandSettings.MAP_TILE_SOURCES); tileSourcePreference.setOnPreferenceChangeListener(this); @@ -49,6 +52,7 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference useInternetToDownloadTiles.setChecked(OsmandSettings.isUsingInternetToDownloadTiles(this)); showPoiOnMap.setChecked(OsmandSettings.isShowingPoiOverMap(this)); rotateMapToBearing.setChecked(OsmandSettings.isRotateMapToBearing(this)); + showViewAngle.setChecked(OsmandSettings.isShowingViewAngle(this)); List list = TileSourceManager.getKnownSourceTemplates(); String[] entries = new String[list.size()]; @@ -77,6 +81,9 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference } else if(preference == rotateMapToBearing){ edit.putBoolean(OsmandSettings.ROTATE_MAP_TO_BEARING, (Boolean) newValue); edit.commit(); + } else if(preference == showViewAngle){ + edit.putBoolean(OsmandSettings.SHOW_VIEW_ANGLE, (Boolean) newValue); + edit.commit(); } else if (preference == tileSourcePreference) { edit.putString(OsmandSettings.MAP_TILE_SOURCES, (String) newValue); edit.commit(); diff --git a/OsmAnd/src/com/osmand/views/PointLocationLayer.java b/OsmAnd/src/com/osmand/views/PointLocationLayer.java index c81a85875e..edcd5d7601 100644 --- a/OsmAnd/src/com/osmand/views/PointLocationLayer.java +++ b/OsmAnd/src/com/osmand/views/PointLocationLayer.java @@ -5,6 +5,7 @@ import android.graphics.Color; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.Path; +import android.graphics.RectF; import android.graphics.Paint.Style; import android.location.Location; import android.view.MotionEvent; @@ -12,14 +13,22 @@ import android.view.MotionEvent; import com.osmand.osm.MapUtils; public class PointLocationLayer implements OsmandMapLayer { + protected final static int RADIUS = 7; + protected final static int HEADING_RADIUS = 60; + protected final static float HEADING_ANGLE = 60; + private Paint location; private Paint bearing; private Paint area; + private Paint headingPaint; + private Path pathForDirection; protected Location lastKnownLocation = null; - protected final static int RADIUS = 7; + private OsmandMapTileView view; - private Path pathForDirection; + + private Float heading = null; + private void initUI() { location = new Paint(); @@ -31,6 +40,12 @@ public class PointLocationLayer implements OsmandMapLayer { area.setColor(Color.BLUE); area.setAlpha(40); + headingPaint = new Paint(); + headingPaint.setColor(Color.BLUE); + headingPaint.setAlpha(50); + headingPaint.setAntiAlias(true); + headingPaint.setStyle(Style.FILL); + bearing = new Paint(); bearing.setColor(Color.BLUE); bearing.setAlpha(150); @@ -51,6 +66,10 @@ public class PointLocationLayer implements OsmandMapLayer { return false; } + private RectF getHeadingRect(int locationX, int locationY){ + int rad = Math.min(3*view.getWidth()/8, 3*view.getHeight()/8); + return new RectF(locationX - rad, locationY - rad, locationX + rad, locationY + rad); + } // TODO simplify calculation if possible @Override @@ -67,6 +86,11 @@ public class PointLocationLayer implements OsmandMapLayer { if (radius > RADIUS) { canvas.drawCircle(locationX, locationY, radius, area); } + if(heading != null){ + canvas.drawArc(getHeadingRect(locationX, locationY), + heading - HEADING_ANGLE/ 2 - 90, HEADING_ANGLE, true, headingPaint); + } + if(lastKnownLocation.hasBearing()){ float bearing = lastKnownLocation.getBearing(); int radiusBearing = 30; @@ -84,7 +108,7 @@ public class PointLocationLayer implements OsmandMapLayer { pathForDirection.lineTo(0, 0); Matrix m = new Matrix(); m.reset(); - m.postScale(1, radiusBearing*0.5f); + m.postScale(1, radiusBearing * 0.5f); m.postTranslate(0, -radiusBearing); m.postTranslate(locationX, locationY); m.postRotate(bearing, locationX, locationY); @@ -93,8 +117,6 @@ public class PointLocationLayer implements OsmandMapLayer { canvas.drawPath(pathForDirection, this.bearing); } - - } } @@ -110,6 +132,17 @@ public class PointLocationLayer implements OsmandMapLayer { return lastKnownLocation; } + public void setHeading(Float heading, boolean doNotRedraw){ + this.heading = heading; + if(!doNotRedraw && isLocationVisible(this.lastKnownLocation)){ + view.prepareImage(); + } + } + + public Float getHeading() { + return heading; + } + public void setLastKnownLocation(Location lastKnownLocation, boolean doNotRedraw) { this.lastKnownLocation = lastKnownLocation; if (!doNotRedraw) { diff --git a/OsmAnd/src/com/osmand/views/PointNavigationLayer.java b/OsmAnd/src/com/osmand/views/PointNavigationLayer.java index d5a3888102..0f99e87a3a 100644 --- a/OsmAnd/src/com/osmand/views/PointNavigationLayer.java +++ b/OsmAnd/src/com/osmand/views/PointNavigationLayer.java @@ -64,8 +64,8 @@ public class PointNavigationLayer implements OsmandMapLayer { float bearing = calculations[1]; pathForDirection.reset(); pathForDirection.moveTo(0, 0); - pathForDirection.lineTo(0.5f, 1f); - pathForDirection.lineTo(-0.5f, 1f); + pathForDirection.lineTo(0.5f, 1.5f); + pathForDirection.lineTo(-0.5f, 1.5f); pathForDirection.lineTo(0, 0); float radiusBearing = DIST_TO_SHOW ; Matrix m = new Matrix();