diff --git a/OsmAnd/res/values/strings.xml b/OsmAnd/res/values/strings.xml
index e3d5789d18..755164e655 100644
--- a/OsmAnd/res/values/strings.xml
+++ b/OsmAnd/res/values/strings.xml
@@ -1940,4 +1940,5 @@ Afghanistan, Albania, Algeria, Andorra, Angola, Anguilla, Antigua and Barbuda, A
Choose whether to play a sound when shooting photos
Invalid format: %s
Remove all
+ Announce nearby favorites
diff --git a/OsmAnd/src/net/osmand/plus/OsmAndLocationProvider.java b/OsmAnd/src/net/osmand/plus/OsmAndLocationProvider.java
index 86e83784fc..f4a1f8dab4 100644
--- a/OsmAnd/src/net/osmand/plus/OsmAndLocationProvider.java
+++ b/OsmAnd/src/net/osmand/plus/OsmAndLocationProvider.java
@@ -1,16 +1,16 @@
package net.osmand.plus;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CopyOnWriteArrayList;
+import android.widget.ListView;
import net.osmand.GeoidAltitudeCorrection;
import net.osmand.PlatformUtil;
import net.osmand.access.NavigationInfo;
import net.osmand.binary.RouteDataObject;
import net.osmand.data.LatLon;
+import net.osmand.data.LocationPoint;
import net.osmand.data.QuadPoint;
import net.osmand.plus.OsmandSettings.OsmandPreference;
import net.osmand.plus.routing.RoutingHelper;
@@ -66,9 +66,7 @@ public class OsmAndLocationProvider implements SensorEventListener {
private float[] mGravs = new float[3];
private float[] mGeoMags = new float[3];
private float previousCorrectionValue = 360;
-
-
-
+
private static final boolean USE_KALMAN_FILTER = true;
private static final float KALMAN_COEFFICIENT = 0.04f;
@@ -104,8 +102,114 @@ public class OsmAndLocationProvider implements SensorEventListener {
private float[] mRotationM = new float[9];
private OsmandPreference USE_MAGNETIC_FIELD_SENSOR_COMPASS;
private OsmandPreference USE_FILTER_FOR_COMPASS;
-
-
+
+ private static final int NOT_ANNOUNCED = 0;
+ private static final int ANNOUNCED_ONCE = 1;
+ private static final int ANNOUNCED_TWICE = 2;
+
+ private ConcurrentHashMap locationPointsStates = new ConcurrentHashMap();
+ private List visibleLocationPoints = new CopyOnWriteArrayList();
+ private long locationPointsModified;
+
+ public List getVisibleLocationPoints() {
+ return visibleLocationPoints;
+ }
+
+ public void setVisibleLocationPoints(List points) {
+ locationPointsStates.clear();
+ visibleLocationPoints.clear();
+ if (points == null) {
+ return;
+ }
+ for (LocationPoint p : points) {
+ locationPointsStates.put(p, NOT_ANNOUNCED);
+ visibleLocationPoints.add(p);
+ }
+ sortVisibleLocationPoints();
+
+ }
+
+ public void addVisibleLocationPoint(LocationPoint lp) {
+ this.locationPointsStates.put(lp, NOT_ANNOUNCED);
+ this.locationPointsModified = System.currentTimeMillis();
+ sortVisibleLocationPoints();
+ }
+
+ public void clearAllVisiblePoints() {
+ this.locationPointsStates.clear();
+ this.visibleLocationPoints.clear();
+ this.locationPointsModified = System.currentTimeMillis();
+ }
+
+ public void sortVisibleLocationPoints() {
+ net.osmand.Location lastLocation = getLastKnownLocation();
+ if (lastLocation != null) {
+ Object[] loc = visibleLocationPoints.toArray();
+ Arrays.sort(loc, getComparator(lastLocation));
+ visibleLocationPoints.clear();
+ for (Object aLoc : loc) {
+ visibleLocationPoints.add((LocationPoint) aLoc);
+ }
+ }
+ }
+ private Comparator