Merge branch 'master' of ssh://github.com/osmandapp/Osmand into HEAD

This commit is contained in:
PaulStets 2018-08-01 09:15:53 +03:00
commit d0f9f3c118
73 changed files with 1277 additions and 475 deletions

View file

@ -54,7 +54,7 @@ public abstract class Entity implements Serializable {
result = prime * result + ((type == null) ? 0 : type.hashCode());
return result;
}
@Override
public String toString() {
return type + " " + id; //$NON-NLS-1$
@ -108,6 +108,8 @@ public abstract class Entity implements Serializable {
private boolean dataLoaded;
private int modify;
private int version;
private double latitude;
private double longitude;
public static final int MODIFY_UNKNOWN = 0;
public static final int MODIFY_DELETED = -1;
public static final int MODIFY_MODIFIED = 1;
@ -117,6 +119,11 @@ public abstract class Entity implements Serializable {
this.id = id;
}
public Entity(long id, double latitude, double longitude) {
this.id = id;
this.latitude = latitude;
this.longitude = longitude;
}
public Entity(Entity copy, long id) {
this.id = id;
@ -124,6 +131,8 @@ public abstract class Entity implements Serializable {
putTagNoLC(t, copy.getTag(t));
}
this.dataLoaded = copy.dataLoaded;
this.latitude = copy.latitude;
this.longitude = copy.longitude;
}
public Set<String> getChangedTags() {
@ -146,6 +155,22 @@ public abstract class Entity implements Serializable {
return id;
}
public double getLatitude() {
return latitude;
}
public double getLongitude() {
return longitude;
}
public void setLatitude(double latitude) {
this.latitude = latitude;
}
public void setLongitude(double longitude) {
this.longitude = longitude;
}
public String removeTag(String key) {
if (tags != null) {
return tags.remove(key);

View file

@ -8,42 +8,20 @@ import java.util.Map;
public class Node extends Entity implements Serializable {
private static final long serialVersionUID = -2981499160640211082L;
private double latitude;
private double longitude;
// currently not used
// private boolean visible = true;
public Node(double latitude, double longitude, long id){
super(id);
this.latitude = latitude;
this.longitude = longitude;
super(id, latitude,longitude);
}
public Node(Node n, long newId) {
super(n, newId);
this.latitude = n.latitude;
this.longitude = n.longitude;
}
public double getLatitude() {
return latitude;
}
public double getLongitude() {
return longitude;
}
public void setLatitude(double latitude) {
this.latitude = latitude;
}
public void setLongitude(double longitude) {
this.longitude = longitude;
}
@Override
public LatLon getLatLon() {
return new LatLon(latitude, longitude);
return new LatLon(getLatitude(), getLongitude());
}
@Override
@ -55,8 +33,8 @@ public class Node extends Entity implements Serializable {
@Override
public String toString() {
return "Node{" +
"latitude=" + latitude +
", longitude=" + longitude +
"latitude=" + getLatitude() +
", longitude=" + getLongitude() +
", tags=" + getTags() +
'}';
}

View file

@ -39,6 +39,11 @@ public class Way extends Entity {
}
}
public Way(long id, TLongArrayList nodeIds, double lat, double lon) {
super(id, lat, lon);
this.nodeIds = nodeIds;
}
public void addNode(long id) {
if (nodeIds == null) {
nodeIds = new TLongArrayList();

View file

@ -68,7 +68,8 @@ public class GeneralRouter implements VehicleRouter {
ROUTING_OBSTACLES("obstacle"),
ONEWAY("oneway"),
PENALTY_TRANSITION("penalty_transition"),
OBSTACLE_SRTM_ALT_SPEED("obstacle_srtm_alt_speed");
OBSTACLE_SRTM_ALT_SPEED("obstacle_srtm_alt_speed"),
AREA("area");
public final String nm;
RouteDataObjectAttribute(String name) {
nm = name;
@ -344,6 +345,11 @@ public class GeneralRouter implements VehicleRouter {
return getObjContext(RouteDataObjectAttribute.ONEWAY).evaluateInt(road, 0);
}
@Override
public boolean isArea(RouteDataObject road) {
return getObjContext(RouteDataObjectAttribute.AREA).evaluateInt(road, 0) == 1;
}
@Override
public float getPenaltyTransition(RouteDataObject road) {
return getObjContext(RouteDataObjectAttribute.PENALTY_TRANSITION).evaluateInt(road, 0);

View file

@ -24,6 +24,7 @@ import net.osmand.router.BinaryRoutePlanner.RouteSegment;
import net.osmand.router.GeneralRouter.GeneralRouterProfile;
import net.osmand.router.RoutePlannerFrontEnd.RouteCalculationMode;
import net.osmand.util.Algorithms;
import net.osmand.util.MapAlgorithms;
import net.osmand.util.MapUtils;
import org.apache.commons.logging.Log;
@ -40,9 +41,121 @@ public class RouteResultPreparation {
*/
List<RouteSegmentResult> prepareResult(RoutingContext ctx, FinalRouteSegment finalSegment) throws IOException {
List<RouteSegmentResult> result = convertFinalSegmentToResults(ctx, finalSegment);
combineWayPointsForAreaRouting(ctx, result);
prepareResult(ctx, result);
return result;
}
private static class CombineAreaRoutePoint {
int x31;
int y31;
int originalIndex;
}
private void combineWayPointsForAreaRouting(RoutingContext ctx, List<RouteSegmentResult> result) {
for(int i = 0; i < result.size(); i++) {
RouteSegmentResult rsr = result.get(i);
RouteDataObject obj = rsr.getObject();
boolean area = false;
if(obj.getPoint31XTile(0) == obj.getPoint31XTile(obj.getPointsLength() - 1) &&
obj.getPoint31YTile(0) == obj.getPoint31YTile(obj.getPointsLength() - 1)) {
area = true;
}
if(!area || !ctx.getRouter().isArea(obj)) {
continue;
}
List<CombineAreaRoutePoint> originalWay = new ArrayList<CombineAreaRoutePoint>();
List<CombineAreaRoutePoint> routeWay = new ArrayList<CombineAreaRoutePoint>();
for(int j = 0; j < obj.getPointsLength(); j++) {
CombineAreaRoutePoint pnt = new CombineAreaRoutePoint();
pnt.x31 = obj.getPoint31XTile(j);
pnt.y31 = obj.getPoint31YTile(j);
pnt.originalIndex = j;
originalWay.add(pnt);
if(j >= rsr.getStartPointIndex() && j <= rsr.getEndPointIndex()) {
routeWay.add(pnt);
} else if(j <= rsr.getStartPointIndex() && j >= rsr.getEndPointIndex()) {
routeWay.add(0, pnt);
}
}
int originalSize = routeWay.size();
simplifyAreaRouteWay(routeWay, originalWay);
int newsize = routeWay.size();
if (routeWay.size() != originalSize) {
RouteDataObject nobj = new RouteDataObject(obj);
nobj.pointsX = new int[newsize];
nobj.pointsY = new int[newsize];
for (int k = 0; k < newsize; k++) {
nobj.pointsX[k] = routeWay.get(k).x31;
nobj.pointsY[k] = routeWay.get(k).y31;
}
// in future point names might be used
nobj.restrictions = null;
nobj.restrictionsVia = null;
nobj.pointTypes = null;
nobj.pointNames = null;
nobj.pointNameTypes = null;
RouteSegmentResult nrsr = new RouteSegmentResult(nobj, 0, newsize - 1);
result.set(i, nrsr);
}
}
}
private void simplifyAreaRouteWay(List<CombineAreaRoutePoint> routeWay, List<CombineAreaRoutePoint> originalWay) {
boolean changed = true;
while (changed) {
changed = false;
int connectStart = -1;
int connectLen = 0;
double dist = 0;
int length = routeWay.size() - 1;
while (length > 0 && connectLen == 0) {
for (int i = 0; i < routeWay.size() - length; i++) {
CombineAreaRoutePoint p = routeWay.get(i);
CombineAreaRoutePoint n = routeWay.get(i + length);
if (segmentLineBelongsToPolygon(p, n, originalWay)) {
double ndist = BinaryRoutePlanner.squareRootDist(p.x31, p.y31, n.x31, n.y31);
if (ndist > dist) {
ndist = dist;
connectStart = i;
connectLen = length;
}
}
}
length--;
}
while (connectLen > 1) {
routeWay.remove(connectStart + 1);
connectLen--;
changed = true;
}
}
}
private boolean segmentLineBelongsToPolygon(CombineAreaRoutePoint p, CombineAreaRoutePoint n,
List<CombineAreaRoutePoint> originalWay) {
int intersections = 0;
int mx = p.x31 / 2 + n.x31 / 2;
int my = p.y31 / 2 + n.y31 / 2;
for(int i = 1; i < originalWay.size(); i++) {
CombineAreaRoutePoint p2 = originalWay.get(i -1);
CombineAreaRoutePoint n2 = originalWay.get(i);
if(p.originalIndex != i && p.originalIndex != i - 1) {
if(n.originalIndex != i && n.originalIndex != i - 1) {
if(MapAlgorithms.linesIntersect(p.x31, p.y31, n.x31, n.y31, p2.x31, p2.y31, n2.x31, n2.y31)) {
return false;
}
}
}
int fx = MapAlgorithms.ray_intersect_x(p2.x31, p2.y31, n2.x31, n2.y31, my);
if (Integer.MIN_VALUE != fx && mx >= fx) {
intersections++;
}
}
return intersections % 2 == 1;
}
List<RouteSegmentResult> prepareResult(RoutingContext ctx, List<RouteSegmentResult> result) throws IOException {
validateAllPointsConnected(result);

View file

@ -76,6 +76,12 @@ public interface VehicleRouter {
*/
public boolean restrictionsAware();
/**
* @param obj
* @return if road supports area routing
*/
public boolean isArea(RouteDataObject obj);
/**
* Calculate turn time
*/
@ -85,5 +91,7 @@ public interface VehicleRouter {
public VehicleRouter build(Map<String, String> params);
}

View file

@ -423,6 +423,9 @@ public class GeoPointParserUtil {
if (schemeSpecific == null) {
return null;
}
if(uri.getRawSchemeSpecificPart().contains("%2B")) {
schemeSpecific = schemeSpecific.replace("+", "%2B");
}
String name = null;
final Pattern namePattern = Pattern.compile("[\\+\\s]*\\((.*)\\)[\\+\\s]*$");
@ -441,8 +444,9 @@ public class GeoPointParserUtil {
positionPart = schemeSpecific;
} else {
positionPart = schemeSpecific.substring(0, queryStartIndex);
if (queryStartIndex < schemeSpecific.length())
if (queryStartIndex < schemeSpecific.length()) {
queryPart = schemeSpecific.substring(queryStartIndex + 1);
}
}
final Pattern positionPattern = Pattern.compile(

View file

@ -291,8 +291,8 @@ public class MapAlgorithms {
return true;
}
public static boolean containsPoint(Collection<Node> polyNodes, double latitude, double longitude){
return countIntersections(polyNodes, latitude, longitude) % 2 == 1;
public static boolean containsPoint(Collection<Node> polyNodes, double latitude, double longitude) {
return countIntersections(polyNodes, latitude, longitude) % 2 == 1;
}
/**

View file

@ -1,14 +1,24 @@
package net.osmand.util;
import java.net.URI;
import java.net.URLEncoder;
import java.util.Map;
import org.junit.Assert;
import org.junit.Test;
import net.osmand.util.GeoPointParserUtil.GeoParsedPoint;
public class GeoPointParserUtilTest {
@Test
public void testGeoPointUrlDecode() {
// bug in get scheme getSchemeSpecificPart()
// equal results for : URI.create("geo:0,0?q=86HJV99P+29") && URI.create("geo:0,0?q=86HJV99P%2B29");
GeoParsedPoint test = GeoPointParserUtil.parse("geo:0,0?q=86HJV99P%2B29");
Assert.assertEquals(test.getQuery(), "86HJV99P+29");
}
@Test
public void testGeoPoint() {

View file

@ -30,6 +30,16 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data
android:host="main_activity"
android:scheme="osmand_telegram" />
</intent-filter>
</activity>
<service

View file

@ -53,7 +53,7 @@ import net.osmand.aidl.gpx.RemoveGpxParams;
import net.osmand.aidl.maplayer.point.ShowMapPointParams;
import net.osmand.aidl.navdrawer.AddOpenAppNavDrawerItemParams;
import net.osmand.aidl.navdrawer.SetNavDrawerItemsParams;
// NOTE: Add new methods at the end of file!!!
@ -108,5 +108,5 @@ interface IOsmAndAidlInterface {
boolean showMapPoint(in ShowMapPointParams params);
boolean addOpenAppNavDrawerItem(in AddOpenAppNavDrawerItemParams params);
boolean setNavDrawerItems(in SetNavDrawerItemsParams params);
}

View file

@ -1,3 +0,0 @@
package net.osmand.aidl.navdrawer;
parcelable AddOpenAppNavDrawerItemParams;

View file

@ -1,63 +0,0 @@
package net.osmand.aidl.navdrawer;
import android.os.Parcel;
import android.os.Parcelable;
public class AddOpenAppNavDrawerItemParams implements Parcelable {
private String itemName;
private String appPackage;
private int flags;
public AddOpenAppNavDrawerItemParams(String itemName, String appPackage) {
this(itemName, appPackage, -1);
}
public AddOpenAppNavDrawerItemParams(String itemName, String appPackage, int flags) {
this.itemName = itemName;
this.appPackage = appPackage;
this.flags = flags;
}
protected AddOpenAppNavDrawerItemParams(Parcel in) {
itemName = in.readString();
appPackage = in.readString();
flags = in.readInt();
}
public String getItemName() {
return itemName;
}
public String getAppPackage() {
return appPackage;
}
public int getFlags() {
return flags;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(itemName);
dest.writeString(appPackage);
dest.writeInt(flags);
}
@Override
public int describeContents() {
return 0;
}
public static final Creator<AddOpenAppNavDrawerItemParams> CREATOR = new Creator<AddOpenAppNavDrawerItemParams>() {
@Override
public AddOpenAppNavDrawerItemParams createFromParcel(Parcel in) {
return new AddOpenAppNavDrawerItemParams(in);
}
@Override
public AddOpenAppNavDrawerItemParams[] newArray(int size) {
return new AddOpenAppNavDrawerItemParams[size];
}
};
}

View file

@ -0,0 +1,3 @@
package net.osmand.aidl.navdrawer;
parcelable NavDrawerItem;

View file

@ -0,0 +1,73 @@
package net.osmand.aidl.navdrawer;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
public class NavDrawerItem implements Parcelable {
private String name;
private String uri;
private String iconName;
private int flags;
public NavDrawerItem(@NonNull String name, @NonNull String uri, @Nullable String iconName) {
this(name, uri, iconName, -1);
}
public NavDrawerItem(@NonNull String name, @NonNull String uri, @Nullable String iconName, int flags) {
this.name = name;
this.uri = uri;
this.iconName = iconName;
this.flags = flags;
}
protected NavDrawerItem(Parcel in) {
name = in.readString();
uri = in.readString();
iconName = in.readString();
flags = in.readInt();
}
public String getName() {
return name;
}
public String getUri() {
return uri;
}
public String getIconName() {
return iconName;
}
public int getFlags() {
return flags;
}
@Override
public void writeToParcel(Parcel dest, int f) {
dest.writeString(name);
dest.writeString(uri);
dest.writeString(iconName);
dest.writeInt(flags);
}
@Override
public int describeContents() {
return 0;
}
public static final Creator<NavDrawerItem> CREATOR = new Creator<NavDrawerItem>() {
@Override
public NavDrawerItem createFromParcel(Parcel in) {
return new NavDrawerItem(in);
}
@Override
public NavDrawerItem[] newArray(int size) {
return new NavDrawerItem[size];
}
};
}

View file

@ -0,0 +1,3 @@
package net.osmand.aidl.navdrawer;
parcelable SetNavDrawerItemsParams;

View file

@ -0,0 +1,56 @@
package net.osmand.aidl.navdrawer;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.NonNull;
import java.util.ArrayList;
import java.util.List;
public class SetNavDrawerItemsParams implements Parcelable {
private String appPackage;
private List<NavDrawerItem> items;
public SetNavDrawerItemsParams(@NonNull String appPackage, @NonNull List<NavDrawerItem> items) {
this.appPackage = appPackage;
this.items = items;
}
protected SetNavDrawerItemsParams(Parcel in) {
appPackage = in.readString();
items = new ArrayList<>();
in.readTypedList(items, NavDrawerItem.CREATOR);
}
public String getAppPackage() {
return appPackage;
}
public List<NavDrawerItem> getItems() {
return items;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(appPackage);
dest.writeTypedList(new ArrayList<>(items));
}
@Override
public int describeContents() {
return 0;
}
public static final Creator<SetNavDrawerItemsParams> CREATOR = new Creator<SetNavDrawerItemsParams>() {
@Override
public SetNavDrawerItemsParams createFromParcel(Parcel in) {
return new SetNavDrawerItemsParams(in);
}
@Override
public SetNavDrawerItemsParams[] newArray(int size) {
return new SetNavDrawerItemsParams[size];
}
};
}

View file

@ -41,12 +41,18 @@ class TelegramApplication : Application(), OsmandHelperListener {
settings = TelegramSettings(this)
uiUtils = UiUtils(this)
osmandAidlHelper = OsmandAidlHelper(this)
osmandAidlHelper.listener = object : OsmandAidlHelper.OsmandHelperListener {
osmandAidlHelper.listener = object : OsmandAidlHelper.OsmandHelperListener {
override fun onOsmandConnectionStateChanged(connected: Boolean) {
if (connected) {
val basePackage = "net.osmand.telegram"
val appPackage = if (BuildConfig.DEBUG) "$basePackage.debug" else basePackage
osmandAidlHelper.addOpenAppNavDrawerItem(getString(R.string.app_name), appPackage, -1)
osmandAidlHelper.setNavDrawerItems(
appPackage,
listOf(getString(R.string.app_name)),
listOf("osmand_telegram://main_activity"),
listOf("ic_action_travel"),
listOf(-1)
)
}
}
}

View file

@ -33,7 +33,8 @@ import net.osmand.aidl.mapwidget.AMapWidget
import net.osmand.aidl.mapwidget.AddMapWidgetParams
import net.osmand.aidl.mapwidget.RemoveMapWidgetParams
import net.osmand.aidl.mapwidget.UpdateMapWidgetParams
import net.osmand.aidl.navdrawer.AddOpenAppNavDrawerItemParams
import net.osmand.aidl.navdrawer.NavDrawerItem
import net.osmand.aidl.navdrawer.SetNavDrawerItemsParams
import net.osmand.aidl.navigation.NavigateGpxParams
import net.osmand.aidl.navigation.NavigateParams
import net.osmand.aidl.note.StartAudioRecordingParams
@ -868,10 +869,14 @@ class OsmandAidlHelper(private val app: Application) {
return false
}
fun addOpenAppNavDrawerItem(itemName: String, appPackage: String, flags: Int): Boolean {
fun setNavDrawerItems(appPackage: String, names: List<String>, uris: List<String>, iconNames: List<String>, flags: List<Int>): Boolean {
if (mIOsmAndAidlInterface != null) {
try {
return mIOsmAndAidlInterface!!.addOpenAppNavDrawerItem(AddOpenAppNavDrawerItemParams(itemName, appPackage, flags))
val items = mutableListOf<NavDrawerItem>()
for (i in names.indices) {
items.add(NavDrawerItem(names[i], uris[i], iconNames[i], flags[i]))
}
return mIOsmAndAidlInterface!!.setNavDrawerItems(SetNavDrawerItemsParams(appPackage, items))
} catch (e: RemoteException) {
e.printStackTrace()
}

View file

@ -6,18 +6,13 @@ APP_SHORT_COMMANDS := true
# Specify least supported Android platform version
APP_PLATFORM := android-14
# ifeq ($(wildcard $(ANDROID_NDK)/toolchains/*-4.7),)
# ifeq ($(wildcard $(ANDROID_NDK)/toolchains/*-4.8),)
# NDK_TOOLCHAIN_VERSION := 4.9
# else
# NDK_TOOLCHAIN_VERSION := 4.8
# endif
# else
# NDK_TOOLCHAIN_VERSION := 4.7
# endif
# NDK_TOOLCHAIN_VERSION := 4.7
# NDK_TOOLCHAIN_VERSION := 4.9
# NDK_TOOLCHAIN_VERSION := 4.8
NDK_TOOLCHAIN_VERSION := clang
APP_ABI := x86 armeabi-v7a arm64-v8a
# APP_ABI := armeabi-v7a
ifndef OSMAND_DEBUG_NATIVE
# Force release compilation in release optimizations, even if application is debuggable by manifest
APP_OPTIM := release

View file

@ -2897,4 +2897,5 @@
<string name="download_all">تنزيل الكل</string>
<string name="shared_string_restart">إعادة تشغيل التطبيق</string>
<string name="shared_string_bookmark">إشارة مرجعية</string>
<string name="waypoints_removed_from_map_markers">نقاط بالطريق تم إزالتها من علامات الخريطة</string>
</resources>

View file

@ -3103,4 +3103,5 @@ Praparcyjnaj pamiacі %4$s MB (Abmiežavańnie Android %5$s MB, Dalvik %6$s MB).
<string name="search_no_results_description">Niama vynikaŭ?
\nRaspaviadzicie nam ab hetym.</string>
<string name="send_search_query">Adpravić pašukovy zapyt?</string>
<string name="increase_search_radius_to">Pavialičyć radyus pošuku da %1$s</string>
</resources>

View file

@ -3154,4 +3154,5 @@
<string name="search_no_results_description">Няма вынікаў?
\nРаспавядзіце нам аб гэтым.</string>
<string name="send_search_query">Адправіць пашуковы запыт?</string>
<string name="increase_search_radius_to">Павялічыць радыус пошуку да %1$s</string>
</resources>

View file

@ -3003,4 +3003,5 @@ Abasta l\'àrea: %1$s x %2$s</string>
\n
\n</string>
<string name="increase_search_radius_to">Augmenta el radi de cerca fins %1s</string>
<string name="commiting_way">Executant via…</string>
</resources>

View file

@ -3592,7 +3592,7 @@
<string name="poi_checkpoint_type">Typ kontrolního stanoviště</string>
<string name="poi_wetland_palsa_bog">Rašeliniště</string>
<string name="poi_cuisine_sub">Housky</string>
<string name="poi_cuisine_sub">Sendvič ( plněná bageta)</string>
<string name="poi_couloir">Horský průsmyk</string>
<string name="poi_water_place_durability_durable">Zdroj vody: Odolný</string>
<string name="poi_water_place_durability_emergency">Zdroj vody: Nouzový</string>
@ -3741,4 +3741,10 @@
<string name="poi_hazard_minefield">Minové pole</string>
</resources>
<string name="poi_socket_type3">Počet konektorů typu 3</string>
<string name="poi_socket_type3_current">Maximální proud konektoru typ 3 [A]</string>
<string name="poi_socket_type3_output">Maximální výkon konektoru typ 3 [kW]</string>
<string name="poi_socket_tesla_standard">Počet stanic Tesla Destination Charger</string>
<string name="poi_socket_tesla_standard_current">Maximální proud stanice Tesla Destination Charger [A]</string>
<string name="poi_socket_tesla_standard_output">Maximální výkon stanice Tesla Destination Charger [kW]</string>
</resources>

View file

@ -3942,9 +3942,9 @@
<string name="poi_end_date">Slutdato</string>
<string name="poi_appliance">Elektronik butik</string>
<string name="poi_appliance">Butik for hårde hvidevarer</string>
<string name="poi_outcrop">Klippefremspring</string>
<string name="poi_outcrop">Blotlagt klippe</string>
<string name="poi_payment_contactless_yes">Kontaktløs</string>
<string name="poi_payment_contactless_no">Kontaktløs ikke accepteret</string>
@ -3953,7 +3953,7 @@
<string name="poi_hazard_erosion">Erosionsfare</string>
<string name="poi_hazard_avalanche">Lavinefare</string>
<string name="poi_hazard_slippery_road">Glat vejbane</string>
<string name="poi_hazard_flood">Oversvømmelse fare</string>
<string name="poi_hazard_flood">Oversvømmelsesfare</string>
<string name="poi_hazard_minefield">Minefelt</string>

View file

@ -2955,7 +2955,7 @@ Abgedeckte Fläche: %1$s x %2$s</string>
<string name="north_abbreviation">N</string>
<string name="optional_point_name">Optionaler Punktname</string>
<string name="transport_nearby_routes_within">Nahegelegene Routen innerhalb von</string>
<string name="transport_nearby_routes">Innerhalb von</string>
<string name="transport_nearby_routes">Innerhalb</string>
<string name="group_deleted">Gruppe gelöscht</string>
<string name="rendering_attr_whiteWaterSports_name">Wildwasser-Sportarten</string>
<string name="clear_all_intermediates">Alle Zwischenpunkte löschen</string>
@ -3073,4 +3073,16 @@ Abgedeckte Fläche: %1$s x %2$s</string>
<string name="send_search_query">Suchanfrage senden?</string>
<string name="shared_string_world">Welt</string>
<string name="increase_search_radius_to">Vergrößerung des Suchradius auf %1$s</string>
<string name="release_3_1">• Navigation Fix: Fortschrittsbalken, schneller Wechsel des Start- und Endpunkts der Route
\n
\n• Map-Marker Fix: Gruppen An-/Ausschalten, Möglichkeit Marker auf der Karte zu verstecken
\n
\n• OSM-Bearbeitung: Bearbeitung für Nicht-Punkt-Objekte, Behebung fehlender Kommentare zu Notizen, Sicherung von Änderungen
\n
\n• Verbessere Wikipedia und Wikivoyage Parsing, aktualisierte Dateien sind bereits verfügbar
\n
\n• Kontextmenü: fixieren Sie die Transportschilderfarbe im Nachtmodus, fixieren Sie zusätzliche Menügrößen
\n
\n• Andere Fehlerbehebungen
\n</string>
</resources>

View file

@ -4,6 +4,12 @@
This file is manually maintained in res/values-en-rGB and should ONLY contain strings where a different spelling should be used for English as used in the United Kingdom
-->
<string name="rendering_attr_currentTrackColor_name">GPX colour</string>
<string name="rendering_attr_currentTrackColor_description">GPX colour</string>
<string name="shared_string_color">Colour</string>
<string name="mapnik_render_descr">Old \'Mapnik\'-style default rendering style. Key features: colours are similar to \'Mapnik\' style.</string>
<string name="touring_view_render_descr">High detail style for touring purposes. Includes all configuration options of default style, in addition: Displays as much detail as possible, in particular all roads, paths, and other ways to travel. Clear visual distinction between all different road types, reminiscent of many touring atlases. High contrast colour scheme for outdoor use, day and night mode.</string>
<string name="unirs_render_descr">Modification of the default style to increase contrast of pedestrian and bicycle roads. Uses legacy Mapnik colours.</string>
<string name="add_favourites_group_to_markers_descr">Select a Favourite category to add to the markers.</string>
<string name="favourites_group">Favourites category</string>
<string name="add_group_descr">You can import groups from favourites or track waypoints.</string>
@ -86,4 +92,4 @@
<string name="quick_action_category_descr">Select the category to save the favourite in.</string>
<string name="analyze_on_map">Analyse on map</string>
<string name="purchase_cancelled_dialog_title">You have cancelled your OsmAnd Live subscription</string>
</resources>
</resources>

View file

@ -2956,4 +2956,5 @@ Indikas lokon: %1$s x %2$s"</string>
\n • aliaj erar-riparoj
\n</string>
<string name="increase_search_radius_to">Pliigi serĉan radiuson ĝis %1$s</string>
<string name="commiting_way">Alŝutado de linio…</string>
</resources>

View file

@ -2969,7 +2969,7 @@ Lon %2$s</string>
<string name="shared_string_gpx_files">Archivos GPX</string>
<string name="get_osmand_live">Obtén «OsmAnd Live» para desbloquear todas las características: Actualizaciones diarias de mapas con descargas ilimitadas, todos los complementos gratuitos y de pago, artículos de Wikipedia, Wikiviajes y mucho más.</string>
<string name="quick_action_edit_actions">Editar acciones</string>
<string name="error_notification_desc">Por favor, envía la captura de pantalla de esta notificación a support@osmand.net</string>
<string name="error_notification_desc">Por favor, envía una captura de pantalla de esta notificación a support@osmand.net</string>
<string name="coord_input_edit_point">Editar punto</string>
<string name="coord_input_add_point">Añadir punto</string>
<string name="coord_input_save_as_track">Guardar como traza</string>
@ -2993,4 +2993,5 @@ Lon %2$s</string>
\n • Otras correcciones de errores
\n</string>
<string name="increase_search_radius_to">Aumentar el radio de búsqueda a %1$s</string>
<string name="commiting_way">Enviando vía…</string>
</resources>

View file

@ -2969,7 +2969,7 @@ Lon %2$s</string>
<string name="shared_string_gpx_files">Archivos GPX</string>
<string name="get_osmand_live">Obtén «OsmAnd Live» para desbloquear todas las características: Actualizaciones diarias de mapas con descargas ilimitadas, todos los complementos gratuitos y de pago, artículos de Wikipedia, Wikiviajes y mucho más.</string>
<string name="quick_action_edit_actions">Editar acciones</string>
<string name="error_notification_desc">Por favor, envía la captura de pantalla de esta notificación a support@osmand.net</string>
<string name="error_notification_desc">Por favor, envía una captura de pantalla de esta notificación a support@osmand.net</string>
<string name="coord_input_edit_point">Editar punto</string>
<string name="coord_input_add_point">Añadir punto</string>
<string name="coord_input_save_as_track">Guardar como traza</string>
@ -2993,4 +2993,5 @@ Lon %2$s</string>
\n • Otras correcciones de errores
\n</string>
<string name="increase_search_radius_to">Aumentar el radio de búsqueda a %1$s</string>
<string name="commiting_way">Enviando vía…</string>
</resources>

View file

@ -3118,4 +3118,9 @@ Area honi dagokio: %1$s x %2$s</string>
<string name="coord_input_save_as_track_descr">%1$s puntu gehitu dituzu. Idatzi fitxategi-izena eta sakatu \"Gorde\".</string>
<string name="point_deleted">%1$s puntua ezabatuta</string>
<string name="shared_string_world">Mundua</string>
<string name="increase_search_radius_to">Handitu bilaketa-erradioa %1$s-ra</string>
<string name="send_search_query_description">Zure bilaketa <b>\"%1$s\"</b> eta kokapena bidaliko dugu. <br/><br/>Ez dugu informazio pertsonala bilduko, bilaketa datuak algoritmoa hobetzeko biltzen ditugu.<br/></string>
<string name="search_no_results_description">Emaitzarik ez?
\nEman iezaguzu horren berri.</string>
<string name="send_search_query">Bilaketa-kontsulta bidali?</string>
</resources>

View file

@ -705,7 +705,7 @@
<string name="poi_pump">پنجرگیری دوچرخه</string>
<string name="poi_observatory_designation">رصدخانه</string>
<string name="poi_pharmacy_dispensing">داروخانه</string>
<string name="poi_star_rating">ستاره دار</string>
<string name="poi_star_rating">رتبه‌بندی ستاره‌ای</string>
<string name="poi_clock_option">تنظیمات ساعت</string>
<string name="poi_scout_camp">کمپ گردشگری</string>
<string name="poi_backcountry">پشت صحنه</string>
@ -1016,4 +1016,6 @@
<string name="poi_emergency_infrastructure">زیرساخت فوریتی</string>
<string name="poi_enforcement_toll">اعمال قانون: عوارضی</string>
<string name="poi_start_date">تاریخ شروع</string>
<string name="poi_stars_2">۲ (استاندارد)</string>
</resources>

View file

@ -3330,4 +3330,5 @@
<string name="poi_shop_fireplace">Vente de cheminée</string>
<string name="poi_amusement_arcade">Salle d\'arcade</string>
</resources>

View file

@ -3067,4 +3067,5 @@
\nנשמח לקבל דיווח על כך.</string>
<string name="send_search_query">לשלוח את שאילתת החיפוש?</string>
<string name="increase_search_radius_to">הגדלת רדיוס החיפוש ל־%1$s</string>
<string name="commiting_way">הדרך נשלחת…</string>
</resources>

View file

@ -3848,4 +3848,11 @@
<string name="poi_payment_contactless_yes">Snertilaust</string>
<string name="poi_payment_contactless_no">Ekki tekið við snertilausum kortum</string>
<string name="poi_hazard_nuclear">Kjarnorkuvá</string>
<string name="poi_hazard_avalanche">Snjóflóðahætta</string>
<string name="poi_hazard_slippery_road">Hálka á vegi</string>
<string name="poi_hazard_flood">Flóðahætta</string>
<string name="poi_hazard_minefield">Jarðsprengjusvæði</string>
</resources>

View file

@ -2938,4 +2938,22 @@ Stendur fyrir svæði: %1$s x %2$s</string>
<string name="coord_input_save_as_track_descr">Þú bættir við %1$s punktum. Settu inn heitið á skránni og vistaðu.</string>
<string name="shared_string_world">Veröld</string>
<string name="point_deleted">Punkti %1$s eytt</string>
<string name="release_3_1">• Leiðsögn: Framvindustika lagfærð, hraðari víxl á upphafi og enda leiða
\n
\n • Kortamerki: lagfæring á að kveikja/slökkva á hópum, hægt að fela merki á korti
\n
\n • OSM-breytingar: Hægt að breyta merkjum á atriðum sem ekki eru punktar, lagfæring á þegar athugasemdir vantar á minnispunkta, öryggisafritun breytinga
\n
\n • Bæting á þáttun Wikipedia og Wikivoyage, uppfærðar skrár eru þegar tiltækar
\n
\n • Samhengisvalmynd: lagfæring á samgöngumerkingum í næturham, lagfæring á stærðum viðbótarvalmynda
\n
\n • Lagfæringar á öðrum göllum
\n
\n</string>
<string name="increase_search_radius_to">Auka radíus leitar í %1$s</string>
<string name="send_search_query_description">Við munum senda leitarfyrirspurn þína: <b>\"%1$s\"</b>, ásamt staðsetningu þinni.<br/><br/> Við söfnum ekki persónulegum upplýsingum, við þurfum einfaldlega þessi gögn til að bæta útreikninga leitarinnar.<br/></string>
<string name="search_no_results_description">Engar niðurstöður?
\nSegðu okkur meira um þetta.</string>
<string name="send_search_query">Senda leitarfyrirspurn?</string>
</resources>

View file

@ -1326,4 +1326,9 @@
<string name="poi_aeroway_fuel">Flybrenselstasjon</string>
<string name="poi_waterway_fuel">Båtbensinstasjon</string>
<string name="poi_helipad">Helikopterlandingsplass</string>
<string name="poi_fire_water_pond">Branndam</string>
<string name="poi_fuel_octane_80">80-oktan</string>
<string name="poi_communication_tower">Kommunikasjonstårn</string>
<string name="poi_observation_tower">Utkikkstårn</string>
<string name="poi_lighting_tower">Lysmast</string>
</resources>

View file

@ -3030,4 +3030,8 @@
<string name="coord_input_save_as_track_descr">Du har lagt til %1$s punkter. Skriv inn navnet på filen og trykk \"Lagre\".</string>
<string name="point_deleted">Punkt %1$s slettet</string>
<string name="shared_string_world">Verden</string>
<string name="increase_search_radius_to">Øk søkeradius til %1$s</string>
<string name="search_no_results_description">Resultatløst?
\nLa det komme oss for øre.</string>
<string name="send_search_query">Send søkeforespørsel?</string>
</resources>

View file

@ -3109,4 +3109,18 @@ Pro praghere iscrie su còdighe intreu</string>
<string name="search_no_results_description">Perunu risultadu?
\nFaghide·nos·lu ischire.</string>
<string name="send_search_query">Imbiare sos tèrmines de chirca?</string>
<string name="release_3_1">• Nàvigu: Barra de progressu acontzada, cuncàmbiu lestru intre sos puntos de incumintzu e de acabu de s\'àndala
\n
\n • Marcadores de sa mapa: acontzu de s\'allughidura/istudadura de sos grupos, possibilidade de istichire marcadores dae sa mapa
\n
\n • Modìficas OSM: Possibilidade de modificare sas etichetas pro sos ogetos chi non sunt puntos, acontzu de su problema de sos cummentos chi mancaiant in sas notas, còpia de seguresa de sas modìficas
\n
\n • Anàlisi de Wikipedia e de Wikivoyage megioradas, sos documentos agiornados sunt giai disponìbiles
\n
\n • Menù de cuntestu: colores de sos iscudos de trasportu in sa modalidade pro sa note acontzados, mannàrias pro sos menùs additzionales acontzadas
\n
\n • Àteros acontzos de errores
\n
\n</string>
<string name="increase_search_radius_to">Ismànnia su raju de chirca finas a %1$s</string>
</resources>

View file

@ -3531,4 +3531,19 @@
<string name="poi_cable_number">Počet lán</string>
<string name="poi_via_ferrata_scale">Náročnosť</string>
</resources>
<string name="poi_checkpoint_type">Typ kontrolného stanovišťa</string>
<string name="poi_appliance">Obchod so spotrebičmi</string>
<string name="poi_payment_contactless_yes">Bezkontaktne</string>
<string name="poi_payment_contactless_no">Bezkontaktne nie je možné platiť</string>
<string name="poi_hazard_nuclear">Nebezpečenstvo rádioaktivity</string>
<string name="poi_hazard_erosion">Nebezpečenstvo erózie</string>
<string name="poi_hazard_avalanche">Nebezpečenstvo lavín</string>
<string name="poi_hazard_slippery_road">Klzká cesta</string>
<string name="poi_hazard_flood">Nebezpečenstvo záplav</string>
<string name="poi_hazard_minefield">Mínové pole</string>
</resources>

View file

@ -1422,7 +1422,7 @@ Proporčná pamäť %4$s MB (Limit Androidu %5$s MB, Dalvik %6$s MB).</string>
<string name="map_widget_right">Pravý panel</string>
<string name="map_widget_left">Ľavý panel</string>
<string name="configure_map">Nastaviť mapu</string>
<string name="search_radius_proximity">Vovnútri</string>
<string name="search_radius_proximity">Do vzdialenosti</string>
<string name="rendering_category_routes">Trasy</string>
<string name="rendering_attr_trainLightrailRoutes_name">Vlakové linky</string>
<string name="rendering_attr_tramRoutes_name">Električkové linky</string>
@ -2853,7 +2853,7 @@ Zodpovedá oblasti: %1$s x %2$s</string>
<string name="north_abbreviation">S</string>
<string name="optional_point_name">Voliteľný názov bodu</string>
<string name="transport_nearby_routes_within">Blízke trasy do</string>
<string name="transport_nearby_routes">Vovnútri</string>
<string name="transport_nearby_routes">Do vzdialenosti</string>
<string name="rendering_attr_whiteWaterSports_name">Divoká voda</string>
<string name="group_deleted">Skupina odstránená</string>
<string name="waypoints_removed_from_map_markers">Body trasy odstránené z mapových značiek</string>
@ -2965,4 +2965,22 @@ Zodpovedá oblasti: %1$s x %2$s</string>
<string name="coord_input_save_as_track_descr">Pridali ste %1$s bodov. Zadajte názov súboru a stlačte \"Uložiť\".</string>
<string name="point_deleted">Bod %1$s vymazaný</string>
<string name="shared_string_world">Celý svet</string>
<string name="release_3_1">• Navigácia: Opravený indikátor postupu, rýchle prepínanie začiatočného a koncového bodu trasy
\n
\n • Mapové značky: opravené zapínanie a vypínanie skupín, možnosť skryť značky z mapy
\n
\n • Úpravy OSM: Možnosť meniť značky nebodových objektov, oprava chýbajúcich komentárov na poznámkach, záloha úprav
\n
\n • Vylepšené čítanie Wikipédie a Wikivoyage, aktualizované súbory sú už k dispozícii
\n
\n • Kontextové menu: opravené farby znakov ciest v nočnom režime, opravené doplnkové veľkosti menu
\n
\n • Opravy ďalších chýb
\n
\n</string>
<string name="increase_search_radius_to">Zväčšiť polomer hľadania na %1$s</string>
<string name="send_search_query_description">Odošleme váš vyhľadávaciu požiadavku: <b>\"%1$s\"</b>, ako aj vašu polohu.<br/><br/> Nezbierame osobné údaje, potrebujeme len údaje vyhľadávania na vylepšenie vyhľadávací algoritmus.<br/></string>
<string name="search_no_results_description">Žiadne výsledky?
\nPovedzte nám o tom.</string>
<string name="send_search_query">Odoslať vyhľadávaciu požiadavku?</string>
</resources>

View file

@ -2971,4 +2971,5 @@
<string name="search_no_results_description">Нема резултата?
\nРеците нам о овоме.</string>
<string name="send_search_query">Пошаљи упит претраге?</string>
<string name="increase_search_radius_to">Повећај полупречник претраге на %1$s</string>
</resources>

View file

@ -183,7 +183,7 @@
<string name="poi_service_tyres">Шини</string>
<string name="poi_vehicle_inspection">Огляд автомобіля</string>
<string name="poi_car_wash">Мийка автомобіля</string>
<string name="poi_fuel">АЗС</string>
<string name="poi_fuel">АЗС;Автомобільна заправка;Автозаправка;Бензоколонка;Бензозаправка</string>
<string name="poi_fuel_diesel">Дизель</string>
<string name="poi_fuel_gtl_diesel">Високоякісний дизель</string>
<string name="poi_fuel_hgv_diesel">TIR дизель</string>
@ -3825,4 +3825,41 @@
<string name="poi_aerialway_zip_line">Зіплайн</string>
</resources>
<string name="poi_climbing_adventure">Пригоди з скелелазенням</string>
<string name="poi_via_ferrata">Віа феррата</string>
<string name="poi_glacier_type_icecap">Льодовиковий покрив</string>
<string name="poi_glacier_type_icefield">Льодовикове поле</string>
<string name="poi_glacier_type_plateau">Плато</string>
<string name="poi_glacier_type_valley">Долинний льодовик</string>
<string name="poi_glacier_type_outlet">Відтік</string>
<string name="poi_glacier_type_tidewater">Стічна вода</string>
<string name="poi_glacier_type_icefall">Льодоспад</string>
<string name="poi_glacier_type_rock">Скала</string>
<string name="poi_glacier_type_shelf">Шельфовий</string>
<string name="poi_glacier_type_remnant">Залишок</string>
<string name="poi_glacier_type_ice_tongue">Льодовий язик</string>
<string name="poi_glacier_ele_top">Найвища точка</string>
<string name="poi_glacier_ele_bottom">Найнижча точка</string>
<string name="poi_glacier_slope">Середній схил</string>
<string name="poi_checkpoint_hiking">Пішохідний контрольний пункт</string>
<string name="poi_checkpoint_type_stamp">Пункт штампування</string>
<string name="poi_checkpoint_type_needler">Голкова машина</string>
<string name="poi_checkpoint_type_quize">Вікторина</string>
<string name="poi_rock">Скеля</string>
<string name="poi_appliance">Магазин побутової техніки</string>
<string name="poi_outcrop">Оголення порід</string>
<string name="poi_hazard_nuclear">Радіаційна небезпека</string>
<string name="poi_hazard_erosion">Ерозійна небезпека</string>
<string name="poi_hazard_avalanche">Небезпека лавини</string>
<string name="poi_hazard_slippery_road">Слизька дорога</string>
<string name="poi_hazard_flood">Небезпека затоплення</string>
<string name="poi_hazard_minefield">Мінне поле</string>
</resources>

View file

@ -653,7 +653,7 @@
<string name="loading_streets">Завантажуються вулиці…</string>
<string name="loading_cities">Завантажуються міста…</string>
<string name="poi">POI</string>
<string name="poi">Корисне місце</string>
<string name="error_occurred_saving_gpx">Помилка збереження шляху в GPX файл</string>
<string name="error_calculating_route">Помилка розрахунку маршруту</string>
<string name="error_calculating_route_occured">Помилка прокладання маршруту</string>
@ -1010,8 +1010,8 @@
<string name="intermediate_point">Проміжний пункт %1$s</string>
<string name="context_menu_item_last_intermediate_point">Додати як останню проміжну точку</string>
<string name="context_menu_item_first_intermediate_point">Додати як першу проміжну точку</string>
<string name="add_as_last_destination_point">Додати як останню проміжну точку</string>
<string name="add_as_first_destination_point">Додати як першу проміжну точку</string>
<string name="add_as_last_destination_point">Додати як останній проміжний пункт призначення</string>
<string name="add_as_first_destination_point">Додати як перший проміжний пункт призначення</string>
<string name="replace_destination_point">Замінити пункт призначення</string>
<string name="new_destination_point_dialog">Ви вже встановили пункт призначення:</string>
<string name="shared_string_target_points">Точки призначення</string>
@ -1508,7 +1508,7 @@
<string name="calculate_osmand_route_without_internet">Розрахувати ділянку маршруту OsmAnd без Інтернету</string>
<string name="gpx_option_calculate_first_last_segment">Обчислити маршрут OsmAnd для першого та останнього сегментів маршруту</string>
<string name="use_displayed_track_for_navigation">Чи Ви хочете використовувати відображення треку для навігації?</string>
<string name="keep_and_add_destination_point">Додати як наступний пункт призначення</string>
<string name="keep_and_add_destination_point">Додати наступним пунктом призначення</string>
<string name="select_gpx">Виберіть GPX…</string>
<string name="route_descr_select_destination">Виберіть пункт призначення</string>
<string name="shared_string_select_on_map">Виберіть на мапі</string>
@ -2169,7 +2169,7 @@
<string name="add_time_span">Додати часовий проміжок</string>
<string name="road_blocked">Дорога заблокована</string>
<string name="shared_string_select">Вибрати</string>
<string name="switch_start_finish">Поміняти місцями точки призначення та початку</string>
<string name="switch_start_finish">Поміняти місцями пункт відправлення і пункт призначення</string>
<string name="rendering_attr_hideIcons_name">Значки POI</string>
<string name="item_removed">Елемент видалено</string>
<string name="n_items_removed">Елементи видалено</string>
@ -2921,15 +2921,15 @@
<string name="date_added">Дата додавання</string>
<string name="order_by">Сортувати за:</string>
<string name="use_location">Використовувати розташування</string>
<string name="add_location_as_first_point_descr">Додати Ваше місце розташування як першу точку при плануванні маршруту.</string>
<string name="add_location_as_first_point_descr">Додати Ваше місце розташування як точку старту при плануванні маршруту.</string>
<string name="my_location">Моє місцезнаходження</string>
<string name="shared_string_finish">Фініш</string>
<string name="plan_route">Планувати маршрут</string>
<string name="shared_string_sort">Сортувати</string>
<string name="coordinate_input">Введення координат</string>
<string name="is_saved">збережено</string>
<string name="marker_save_as_track_descr">Експортувати Ваші маркери у файл, який Ви можете вказати тут:</string>
<string name="marker_save_as_track">Зберегти як трек</string>
<string name="marker_save_as_track_descr">Експортувати Ваші маркери у наступний GPX-файл:</string>
<string name="marker_save_as_track">Зберегти як GPX-файл</string>
<string name="move_to_history">Перемістити в історію</string>
<string name="group_will_be_removed_after_restart">Група буде вилучена після перезапуску застосунку.</string>
<string name="show_guide_line">Показувати напрямні лінії</string>
@ -2939,14 +2939,14 @@
<string name="shared_string_markers">Маркери</string>
<string name="coordinates_format">Формат координат</string>
<string name="use_system_keyboard">Використовувати системну клавіатуру</string>
<string name="fast_coordinates_input_descr">Вибрати формат вводу координат. Ви завжди можете змінити його, натиснувши „Параметри“.</string>
<string name="fast_coordinates_input_descr">Виберіть формат введення координат. Ви завжди можете змінити його, натиснувши „Параметри“.</string>
<string name="fast_coordinates_input">Швидке введення координат</string>
<string name="routing_attr_avoid_ice_roads_fords_name">Уникати льодових доріг і бродів</string>
<string name="routing_attr_avoid_ice_roads_fords_description">Уникає льодових доріг і бродів.</string>
<string name="make_round_trip_descr">Додати копію початкової точки як місце призначення.</string>
<string name="make_round_trip">Зробити кругову подорож</string>
<string name="osn_modify_dialog_error">Виняткова ситуація: примітку не було змінено</string>
<string name="osn_modify_dialog_error">Не вдалося змінити замітку</string>
<string name="osn_modify_dialog_title">Змінити примітку</string>
<string name="context_menu_item_modify_note">Змінити OSM-примітку</string>
<string name="wrong_input">Неправильний ввід</string>
@ -2962,7 +2962,7 @@
<string name="shared_string_back">Назад</string>
<string name="shared_string_view">Перегляд</string>
<string name="waypoints_added_to_map_markers">Шляхові точки додані в маркери мапи</string>
<string name="import_gpx_file_description">може бути імпортовано як точки Закладок або як файл треку.</string>
<string name="import_gpx_file_description">може бути імпортовано як заклади або як GPX-файл.</string>
<string name="import_as_gpx">Імпортувати як GPX-файл</string>
<string name="import_as_favorites">Імпортувати як закладки</string>
<string name="import_file">Імпортувати файл</string>
@ -2975,26 +2975,26 @@
<string name="shared_string_paste">Вставити</string>
<string name="coordinate_input_accuracy_description">Автоматично перемикається в наступне поле після введення %1$d цифр після десяткової точки.</string>
<string name="coordinate_input_accuracy">%1$d цифр</string>
<string name="go_to_next_field">Перейти до наступного поля</string>
<string name="go_to_next_field">Наступне поле</string>
<string name="rename_marker">Перейменувати маркер</string>
<string name="appearance_on_the_map">Поява на мапі</string>
<string name="add_track_to_markers_descr">Виберіть трек для додавання шляхових точок (показані лише треки з точками)</string>
<string name="add_track_to_markers_descr">Виберіть трек для додавання шляхових точок в маркери.</string>
<string name="add_favourites_group_to_markers_descr">Виберіть категорію закладок для додавання до маркерів.</string>
<string name="shared_string_gpx_waypoints">Шляхові точки треку</string>
<string name="favourites_group">Категорія закладок</string>
<string name="add_group">Додати групу</string>
<string name="add_group_descr">Ви можете імпортувати групу з закладок або шляхових точок.</string>
<string name="add_group_descr">Імпортувати групи з закладок або шляхових точок.</string>
<string name="empty_state_markers_active">Створіть маркери на мапі!</string>
<string name="empty_state_markers_active_desc">Натисніть на потрібне місце, а потім на прапорець маркера.</string>
<string name="empty_state_markers_active_desc">Довге або коротке натискання на потрібне місце, а потім на прапорець маркера.</string>
<string name="empty_state_markers_groups">Імпортувати групи</string>
<string name="empty_state_markers_groups_desc">Ви можете імпортувати групи закладок або шляхові точки треку як маркери.</string>
<string name="empty_state_markers_groups_desc">Імпортувати групи закладок або шляхових точок треку як маркери.</string>
<string name="empty_state_markers_history_desc">Маркери, позначені як пройдені, з\'являться на цьому екрані.</string>
<string name="shared_string_two">Два</string>
<string name="shared_string_one">Один</string>
<string name="show_guide_line_descr">Відображати напрямні лінії від Вашого місця розташування до активних маркерів.</string>
<string name="show_arrows_descr">Відображати одну або дві стрілки, що вказують напрямок на активні маркери.</string>
<string name="distance_indication_descr">Виберіть спосіб відображення відстані до активних маркерів.</string>
<string name="active_markers_descr">Виберіть скільки відображати індикаторів напрямку.</string>
<string name="active_markers_descr">Виберіть, скільки відображати покажчиків напрямку.</string>
<string name="shared_string_right">Направо</string>
<string name="shared_string_left">Наліво</string>
<string name="looking_for_tracks_with_waypoints">Пошук треків з шляховими точками</string>
@ -3022,7 +3022,7 @@
<string name="context_menu_points_of_group">Всі пункти групи</string>
<string name="open_from">Відкрито з</string>
<string name="open_till">Відкрито до</string>
<string name="will_close_at">Закриється в</string>
<string name="will_close_at">Закриється о</string>
<string name="will_open_at">Відкриється о</string>
<string name="will_open_on">Відкриється о</string>
<string name="additional_actions">Додаткові дії</string>
@ -3039,12 +3039,12 @@
<string name="nautical_renderer">Морський</string>
<string name="map_import_error">Помилка імпорту мапи</string>
<string name="map_imported_successfully">Мапа успішна імпортована</string>
<string name="make_as_start_point">Зробити початковою точкою</string>
<string name="map_imported_successfully">Мапа імпортована</string>
<string name="make_as_start_point">Зробити пунктом відправлення</string>
<string name="shared_string_current">Поточний</string>
<string name="last_intermediate_dest_description">Додає останню зупинку на маршруті</string>
<string name="first_intermediate_dest_description">Додає першу зупинку на маршруті</string>
<string name="subsequent_dest_description">Переміщує пункт призначення і створює проміжну зупинку</string>
<string name="last_intermediate_dest_description">Додає проміжну зупинку</string>
<string name="first_intermediate_dest_description">Додає першу зупинку</string>
<string name="subsequent_dest_description">Пересунути призначення далі і створити його</string>
<string name="show_closed_notes">Показати закриті нотатки</string>
<string name="switch_osm_notes_visibility_desc">Показати/приховати OSM-нотатки на мапі.</string>
<string name="gpx_file_desc">GPX — підходить для експорту в JOSM та інші OSM-редактори.</string>
@ -3064,7 +3064,7 @@
<string name="toast_empty_name_error">Місце не має назви</string>
<string name="tunnel_warning">Тунель попереду</string>
<string name="show_tunnels">Тунелі</string>
<string name="enter_the_file_name">Введіть ім\'я файлу.</string>
<string name="enter_the_file_name">Введіть назву файлу.</string>
<string name="enter_lon">Введіть довготу</string>
<string name="enter_lat">Введіть широту</string>
<string name="enter_lat_and_lon">Введіть широту та довготу</string>
@ -3078,8 +3078,8 @@
<string name="south_abbreviation">Пд</string>
<string name="north_abbreviation">Пн</string>
<string name="optional_point_name">Необов\'язкове ім\'я точки</string>
<string name="transport_nearby_routes_within">Маршрути поряд з</string>
<string name="transport_nearby_routes">ПОРУЧ</string>
<string name="transport_nearby_routes_within">Близькі маршрути в межах</string>
<string name="transport_nearby_routes">В межах</string>
<string name="distance_farthest">Відстань: спочатку найдальше</string>
<string name="distance_nearest">Відстань: спочатку найближче</string>
<string name="group_deleted">Групу було видалено</string>
@ -3107,4 +3107,103 @@
<string name="light_rs_render_descr">Простий і контрастний стиль для автомобільної навігації. Комфортний для очей в нічному режимі. Ключові особливості: контурні лінії, контрастні помаранчеві дороги, менше відволікаючих другорядних об\'єктів на мапі.</string>
<string name="topo_render_descr">Контрастний стиль, призначений в основному для піших прогулянок, походів і велосипедних прогулянок на природі. Хороша читабельність при складному зовнішньому освітленні. Ключові особливості: контрастні дороги і природні об\'єкти, різні типи маршрутів, контурні лінії з розширеними настройками, більш детальна інформація при відповідних рівнях масштабування, ніж в стилі за замовчуванням. Опція „Якість дорожнього покриття“ дозволяє розрізняти дороги з різною якістю поверхні. Немає нічного режиму.</string>
<string name="mapnik_render_descr">Старий стиль відображення за умовчанням „Mapnik“. Ключові особливості: кольору схожі на стиль „Mapnik“.</string>
</resources>
<string name="touring_view_render_descr">Високо деталізований стиль для туристичних цілей. Включає усі параметри конфігурації стилю за умованням, крім того: відображає якомога більше деталей, зокрема, усі дороги, стежки та інші способи переміщення. Чітка візуальна відмінність між усіма типами доріг, ремінісценція багатьох туристичних атласів. Висококонтрастна колірна схема для вуличного використання, денний і нічний режим.</string>
<string name="default_render_descr">Стиль загального призначення. Спрощений рендеринг в густонаселених містах. Ключові особливості: контурні лінії, маршрути, якість поверхні, обмеження доступу, дорожні щити, візуалізація маршрутів за шкалою SAC, характеристики спортивних сплавів.</string>
<string name="open_wikipedia_link_online">Відкрити посилання Вікіпедії в онлайні</string>
<string name="open_wikipedia_link_online_description">Посилання буде відкрите в веб-браузері.</string>
<string name="read_wikipedia_offline_description">Отримайте підписку на OsmAnd Live, щоб читати статті у Вікіпедії та вікімандри в автономному режимі.</string>
<string name="read_wikipedia_offline">Читати Вікіпедію в автономному режимі</string>
<string name="purchase_cancelled_dialog_title">Ви скасували підписку OsmAnd Live</string>
<string name="purchase_cancelled_dialog_descr">Відновіть підписку, щоб продовжити використовувати усі функції:</string>
<string name="maps_you_need_descr">На основі збережених Вами статей ми рекомендуємо Вам звантажити наступні мапи:</string>
<string name="maps_you_need">Потрібні Вам мапи</string>
<string name="osmand_team">Команда OsmAnd</string>
<string name="popular_destinations">Популярні напрямки</string>
<string name="paid_app">Платний додаток</string>
<string name="travel_card_update_descr">Доступні нові дані ВікіМандри, оновіть їх та насолоджуйтеся.</string>
<string name="travel_card_download_descr">Завантажте путівники ВікіМандри, щоб переглянути статті про місця в усьому світі без підключення до Інтернету.</string>
<string name="update_is_available">Оновлення доступне</string>
<string name="download_file">Звантажити файл</string>
<string name="start_editing_card_image_text">Вільний всесвітній путівник, який може редагувати кожен.</string>
<string name="welcome_to_open_beta_description">Туристичні путівники в даний час засновані на Вікімандрах. Перевірте усі функції безкоштовно під час відкритого бета-тестування. Потім путівники будуть доступні передплатникам OsmAnd Unlimited і власником OsmAnd+.</string>
<string name="start_editing_card_description">Вам можна і слід редагувати будь-яку статтю на Вікімандрах. Діліться знаннями, досвідом, талантом і вашої увагою</string>
<string name="start_editing">Розпочати редагування</string>
<string name="get_unlimited_access">Отримати необмежений доступ</string>
<string name="welcome_to_open_beta">Ласкаво просимо на відкрите бета-тестування</string>
<string name="wikivoyage_travel_guide">Туристичний путівник</string>
<string name="wikivoyage_travel_guide_descr">Переглядайте путівники Вікімандів про найцікавіші місця на планеті всередині OsmAnd без підключення до інтернету.</string>
<string name="clear_all_intermediates">Очистити усі проміжні точки</string>
<string name="release_3_1">• Навігація: закріплена панель поступу, швидка зміна початкової та кінцевої точок маршруту
\n• Маркери мапи: увімкнення/вимкнення фіксованих груп, можливість сховати маркери на мапі
\n• Редагування OSM: можливість редагування тегів для неточкових об\'єктів, виправлення відсутніх коментарів до нотаток, резервування редагувань
\n• Поліпшено аналіз Вікіпедії та Вікімандрів, доступні оновлені файли
\n• Контекстне меню: у нічному режимі було покращено кольори транспортних щитів, виправлено додаткові розміри меню
\n• Інші виправлення помилок</string>
<string name="increase_search_radius_to">Збільшити радіус пошуку до %1$s</string>
<string name="send_search_query_description">Ми відправимо Ваш пошуковий запит: <b>„%1$s“</b>, а також Ваше місце розташування. <br/> <br/> Ми не збираємо особисту інформацію, нам потрібні тільки дані пошуку, щоб поліпшити алгоритм пошуку. <br/></string>
<string name="search_no_results_description">Немає результатів?
\nРозкажіть нам про це.</string>
<string name="send_search_query">Надіслати пошуковий запит?</string>
<string name="shared_string_world">Світ</string>
<string name="monthly_map_updates">Оновлення мап: <b>щомісячне</b></string>
<string name="daily_map_updates">Оновлення мап: <b>щогодинне</b></string>
<string name="in_app_purchase">Купівля в додатку</string>
<string name="in_app_purchase_desc">Разовий платіж</string>
<string name="in_app_purchase_desc_ex">Після покупки цей план стане доступний для Вас назавжди.</string>
<string name="purchase_unlim_title">Купити — %1$s</string>
<string name="purchase_subscription_title">Підписатися — %1$s</string>
<string name="wikivoyage_offline">Вікімандри в автономному режимі</string>
<string name="unlimited_downloads">Необмежені звантаження</string>
<string name="wikipedia_offline">Вікіпедія в автономному режимі</string>
<string name="contour_lines_hillshade_maps">Контурні лінії і затінення рельєфу</string>
<string name="unlock_all_features">Розблокувати усі функції OsmAnd</string>
<string name="purchase_dialog_title">Виберіть план</string>
<string name="purchase_dialog_travel_description">Будь ласка, придбайте одне з наведених нижче, щоб отримати функціональність туристичного путівника без підключення до мережі:</string>
<string name="purchase_dialog_subtitle">Виберіть підходящий пункт:</string>
<string name="shared_string_dont">Ні</string>
<string name="shared_string_do">Виконати</string>
<string name="shared_string_only_with_wifi">Лише через WiFi</string>
<string name="wikivoyage_download_pics">Звантажити зображення</string>
<string name="wikivoyage_download_pics_descr">Зображення зі статей можуть бути звантажені для автономного користування.
\nЗавжди доступно в „Дослідити“ → „Параметри“.</string>
<string name="shared_string_wifi_only">Лише через WiFi</string>
<string name="select_travel_book">Вибрати щоденник подорожей</string>
<string name="shared_string_travel_book">Щоденник подорожей</string>
<string name="online_webpage_warning">Сторінка доступна тільки онлайн. Відкрити її в браузері?</string>
<string name="images_cache">Кеш зображень</string>
<string name="delete_search_history">Вилучити історію пошуку</string>
<string name="download_images">Звантаження зображень</string>
<string name="download_maps_travel">Туристичні путівники</string>
<string name="shared_string_wikivoyage">Вікімандри</string>
<string name="article_removed">Стаття вилучена</string>
<string name="wikivoyage_search_hint">Пошук: країна, місто, регіон</string>
<string name="shared_string_read">Читати</string>
<string name="saved_articles">Збережені статті</string>
<string name="shared_string_explore">Дослідити</string>
<string name="shared_string_contents">Зміст</string>
<string name="shared_string_result">Результат</string>
<string name="use_two_digits_longitude">Використовувати двозначну довготу</string>
<string name="shared_string_travel_guides">Туристичні путівники</string>
<string name="waypoints_removed_from_map_markers">Шляхові точки вилучені з маркерів мапи</string>
<string name="nothing_found_in_radius">Нічого не знайдено:</string>
<string name="select_waypoints_category_description">Додати усі проміжні точки маршруту або вибрати окремі категорії.</string>
<string name="shared_string_total">Усього</string>
<string name="release_3_0">• Нове: підтримка глобальних туристичних путівників. Наведені місця, пов\'язані з картою. Вихідні дані з Вікімандрів.
\n• Вікіпедія: новий вигляд, активні посилання, підтримка зображень
\n• Open Track UI: підтримка груп шляхових точок
\n• Маркери мапи: імпорт обраних груп з GPX-файлів, введення координат, новий вигляд
\n• Підписка OsmAnd Live тепер підтримує усі функції OsmAnd</string>
<string name="index_item_world_wikivoyage">Статті путівника Вікімандрів</string>
<string name="shared_string_gpx_files">Файли GPX</string>
<string name="access_intermediate_arrival_time">Проміжний час прибуття</string>
<string name="map_widget_intermediate_time">Проміжний час</string>
<string name="download_wikipedia_description">Звантажити статті Вікіпедії для %1$s, щоб читати їх в автономному режимі.</string>
<string name="download_wikipedia_label">Звантаження даних Вікіпедії</string>
<string name="open_in_browser_wiki">Відкрити статтю в Інтернеті</string>
<string name="open_in_browser_wiki_description">Переглянути статтю в браузері.</string>
<string name="download_wiki_region_placeholder">цей регіон</string>
<string name="wiki_article_search_text">Пошук відповідної статті Вікіпедії</string>
<string name="wiki_article_not_found">Статтю не знайдено</string>
<string name="how_to_open_wiki_title">Як відкрити статті Вікіпедії?</string>
</resources>

View file

@ -2715,4 +2715,7 @@
<string name="download_wikipedia_label">下载维基百科数据</string>
<string name="open_in_browser_wiki">在线打开文章</string>
<string name="wiki_article_not_found">文章未找到</string>
<string name="increase_search_radius_to">增大搜索半径至 %1$s</string>
<string name="send_search_query_description">我们将会发送您的搜索请求:<b>\"%1$s\"</b>,以及您的位置。<br/><br/>我们不会搜集您的个人信息,我们只需要搜索数据以改进搜索算法。<br/></string>
<string name="send_search_query">发送搜索请求?</string>
</resources>

View file

@ -19,6 +19,7 @@
• Context menu: fix transport shields color in the night mode, fix additional menu sizes\n\n
• Other bug fixes\n\n
</string>
<string name="commiting_way">Committing way…</string>
<string name="increase_search_radius_to">Increase search radius to %1$s</string>
<string name="send_search_query_description"><![CDATA[We will send your search query: <b>\"%1$s\"</b>, as well as your location.<br/><br/>
We do not collect personal information, we only need search data to improve the search algorithm.<br/>]]></string>
@ -30,7 +31,7 @@
<string name="coord_input_add_point">Add point</string>
<string name="coord_input_save_as_track">Save as track</string>
<string name="coord_input_save_as_track_descr">You added %1$s points. Type a filename and tap \"Save\".</string>
<string name="error_notification_desc">Please send screenshoot of this notification to support@osmand.net</string>
<string name="error_notification_desc">Please send a screenshot of this notification to support@osmand.net</string>
<string name="quick_action_edit_actions">Edit actions</string>
<string name="get_osmand_live">Get OsmAnd Live to unlock all features: Daily map updates with unlimited downloads, all paid and free plugins, Wikipedia, Wikivoyage and much more.</string>
<string name="unirs_render_descr">Modification of the default style to increase contrast of pedestrian and bicycle roads. Uses legacy Mapnik colors.</string>

View file

@ -53,7 +53,7 @@ import net.osmand.aidl.gpx.RemoveGpxParams;
import net.osmand.aidl.maplayer.point.ShowMapPointParams;
import net.osmand.aidl.navdrawer.AddOpenAppNavDrawerItemParams;
import net.osmand.aidl.navdrawer.SetNavDrawerItemsParams;
// NOTE: Add new methods at the end of file!!!
@ -108,5 +108,5 @@ interface IOsmAndAidlInterface {
boolean showMapPoint(in ShowMapPointParams params);
boolean addOpenAppNavDrawerItem(in AddOpenAppNavDrawerItemParams params);
boolean setNavDrawerItems(in SetNavDrawerItemsParams params);
}

View file

@ -6,10 +6,12 @@ import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.ParcelFileDescriptor;
import android.support.annotation.Nullable;
import android.support.v7.app.AlertDialog;
import android.text.TextUtils;
import android.view.View;
@ -42,7 +44,6 @@ import net.osmand.plus.MapMarkersHelper;
import net.osmand.plus.MapMarkersHelper.MapMarker;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandPlugin;
import net.osmand.plus.OsmandSettings;
import net.osmand.plus.TargetPointsHelper;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.audionotes.AudioVideoNotesPlugin;
@ -60,6 +61,9 @@ import net.osmand.plus.views.mapwidgets.TextInfoWidget;
import net.osmand.util.Algorithms;
import org.apache.commons.logging.Log;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.ByteArrayInputStream;
import java.io.File;
@ -69,6 +73,9 @@ import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
@ -121,6 +128,8 @@ public class OsmandAidlApi {
private static final int DEFAULT_ZOOM = 15;
private static final int MAX_NAV_DRAWER_ITEMS_PER_APP = 3;
private OsmandApplication app;
private Map<String, AMapWidget> widgets = new ConcurrentHashMap<>();
private Map<String, TextInfoWidget> widgetControls = new ConcurrentHashMap<>();
@ -1192,40 +1201,142 @@ public class OsmandAidlApi {
return true;
}
boolean addOpenAppNavDrawerItem(String itemName, String appPackage, int flags) {
if (!TextUtils.isEmpty(itemName) && !TextUtils.isEmpty(appPackage)) {
OsmandSettings settings = app.getSettings();
settings.API_NAV_DRAWER_ITEM_NAME.set(itemName);
settings.API_NAV_DRAWER_ITEM_APP_PACKAGE.set(appPackage);
settings.API_NAV_DRAWER_ITEM_FLAGS.set(flags);
return true;
boolean setNavDrawerItems(String appPackage, List<net.osmand.aidl.navdrawer.NavDrawerItem> items) {
if (!TextUtils.isEmpty(appPackage) && items != null) {
if (items.isEmpty()) {
clearNavDrawerItems(appPackage);
return true;
}
List<NavDrawerItem> newItems = new ArrayList<>(MAX_NAV_DRAWER_ITEMS_PER_APP);
boolean success = true;
for (int i = 0; i < items.size() && i <= MAX_NAV_DRAWER_ITEMS_PER_APP; i++) {
net.osmand.aidl.navdrawer.NavDrawerItem item = items.get(i);
String name = item.getName();
String uri = item.getUri();
if (!TextUtils.isEmpty(name) && !TextUtils.isEmpty(uri)) {
newItems.add(new NavDrawerItem(name, uri, item.getIconName(), item.getFlags()));
} else {
success = false;
break;
}
}
if (success) {
saveNavDrawerItems(appPackage, newItems);
}
return success;
}
return false;
}
public void registerNavDrawerItem(final Activity activity, ContextMenuAdapter adapter) {
final OsmandSettings settings = app.getSettings();
final String itemName = settings.API_NAV_DRAWER_ITEM_NAME.get();
final String appPackage = settings.API_NAV_DRAWER_ITEM_APP_PACKAGE.get();
if (!TextUtils.isEmpty(itemName) && !TextUtils.isEmpty(appPackage)) {
final Intent intent = activity.getPackageManager().getLaunchIntentForPackage(appPackage);
if (intent != null) {
int flags = settings.API_NAV_DRAWER_ITEM_FLAGS.get();
if (flags != -1) {
intent.addFlags(flags);
public void registerNavDrawerItems(final Activity activity, ContextMenuAdapter adapter) {
PackageManager pm = activity.getPackageManager();
for (Map.Entry<String, List<NavDrawerItem>> entry : getNavDrawerItems().entrySet()) {
String appPackage = entry.getKey();
for (NavDrawerItem item : entry.getValue()) {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(item.uri));
if (intent.resolveActivity(pm) == null) {
intent = pm.getLaunchIntentForPackage(appPackage);
}
if (intent != null) {
if (item.flags != -1) {
intent.addFlags(item.flags);
}
final Intent finalIntent = intent;
adapter.addItem(new ContextMenuItem.ItemBuilder()
.setTitle(item.name)
.setIcon(getIconId(item.iconName))
.setListener(new ContextMenuAdapter.ItemClickListener() {
@Override
public boolean onContextMenuClick(ArrayAdapter<ContextMenuItem> adapter, int itemId, int position, boolean isChecked, int[] viewCoordinates) {
activity.startActivity(finalIntent);
return true;
}
})
.createItem());
}
adapter.addItem(new ContextMenuItem.ItemBuilder()
.setTitle(itemName)
.setListener(new ContextMenuAdapter.ItemClickListener() {
@Override
public boolean onContextMenuClick(ArrayAdapter<ContextMenuItem> adapter, int itemId, int position, boolean isChecked, int[] viewCoordinates) {
activity.startActivity(intent);
return true;
}
})
.createItem());
}
}
}
private int getIconId(@Nullable String iconName) {
if (!TextUtils.isEmpty(iconName)) {
int id = app.getResources().getIdentifier(iconName, "drawable", app.getPackageName());
return id == 0 ? -1 : id;
}
return -1;
}
private void clearNavDrawerItems(String appPackage) {
try {
JSONObject allItems = new JSONObject(app.getSettings().API_NAV_DRAWER_ITEMS_JSON.get());
allItems.put(appPackage, null);
app.getSettings().API_NAV_DRAWER_ITEMS_JSON.set(allItems.toString());
} catch (JSONException e) {
e.printStackTrace();
}
}
private void saveNavDrawerItems(String appPackage, List<NavDrawerItem> items) {
try {
JSONArray jArray = new JSONArray();
for (NavDrawerItem item : items) {
JSONObject obj = new JSONObject();
obj.put(NavDrawerItem.NAME_KEY, item.name);
obj.put(NavDrawerItem.URI_KEY, item.uri);
obj.put(NavDrawerItem.ICON_NAME_KEY, item.iconName);
obj.put(NavDrawerItem.FLAGS_KEY, item.flags);
jArray.put(obj);
}
JSONObject allItems = new JSONObject(app.getSettings().API_NAV_DRAWER_ITEMS_JSON.get());
allItems.put(appPackage, jArray);
app.getSettings().API_NAV_DRAWER_ITEMS_JSON.set(allItems.toString());
} catch (JSONException e) {
e.printStackTrace();
}
}
private Map<String, List<NavDrawerItem>> getNavDrawerItems() {
Map<String, List<NavDrawerItem>> res = new LinkedHashMap<>();
try {
JSONObject allItems = new JSONObject(app.getSettings().API_NAV_DRAWER_ITEMS_JSON.get());
for (Iterator<?> it = allItems.keys(); it.hasNext(); ) {
String appPackage = (String) it.next();
JSONArray jArray = allItems.getJSONArray(appPackage);
List<NavDrawerItem> list = new ArrayList<>();
for (int i = 0; i < jArray.length(); i++) {
JSONObject obj = jArray.getJSONObject(i);
list.add(new NavDrawerItem(
obj.optString(NavDrawerItem.NAME_KEY),
obj.optString(NavDrawerItem.URI_KEY),
obj.optString(NavDrawerItem.ICON_NAME_KEY),
obj.optInt(NavDrawerItem.FLAGS_KEY, -1)
));
}
res.put(appPackage, list);
}
} catch (JSONException e) {
e.printStackTrace();
}
return res;
}
private static class NavDrawerItem {
static final String NAME_KEY = "name";
static final String URI_KEY = "uri";
static final String ICON_NAME_KEY = "icon_name";
static final String FLAGS_KEY = "flags";
private String name;
private String uri;
private String iconName;
private int flags;
NavDrawerItem(String name, String uri, String iconName, int flags) {
this.name = name;
this.uri = uri;
this.iconName = iconName;
this.flags = flags;
}
}
}

View file

@ -34,7 +34,7 @@ import net.osmand.aidl.mapmarker.UpdateMapMarkerParams;
import net.osmand.aidl.mapwidget.AddMapWidgetParams;
import net.osmand.aidl.mapwidget.RemoveMapWidgetParams;
import net.osmand.aidl.mapwidget.UpdateMapWidgetParams;
import net.osmand.aidl.navdrawer.AddOpenAppNavDrawerItemParams;
import net.osmand.aidl.navdrawer.SetNavDrawerItemsParams;
import net.osmand.aidl.navigation.NavigateGpxParams;
import net.osmand.aidl.navigation.NavigateParams;
import net.osmand.aidl.note.StartAudioRecordingParams;
@ -460,9 +460,9 @@ public class OsmandAidlService extends Service {
}
@Override
public boolean addOpenAppNavDrawerItem(AddOpenAppNavDrawerItemParams params) throws RemoteException {
public boolean setNavDrawerItems(SetNavDrawerItemsParams params) throws RemoteException {
try {
return params != null && getApi("addOpenAppNavDrawerItem").addOpenAppNavDrawerItem(params.getItemName(), params.getAppPackage(), params.getFlags());
return params != null && getApi("setNavDrawerItems").setNavDrawerItems(params.getAppPackage(), params.getItems());
} catch (Exception e) {
handleException(e);
return false;

View file

@ -1,3 +0,0 @@
package net.osmand.aidl.navdrawer;
parcelable AddOpenAppNavDrawerItemParams;

View file

@ -1,63 +0,0 @@
package net.osmand.aidl.navdrawer;
import android.os.Parcel;
import android.os.Parcelable;
public class AddOpenAppNavDrawerItemParams implements Parcelable {
private String itemName;
private String appPackage;
private int flags;
public AddOpenAppNavDrawerItemParams(String itemName, String appPackage) {
this(itemName, appPackage, -1);
}
public AddOpenAppNavDrawerItemParams(String itemName, String appPackage, int flags) {
this.itemName = itemName;
this.appPackage = appPackage;
this.flags = flags;
}
protected AddOpenAppNavDrawerItemParams(Parcel in) {
itemName = in.readString();
appPackage = in.readString();
flags = in.readInt();
}
public String getItemName() {
return itemName;
}
public String getAppPackage() {
return appPackage;
}
public int getFlags() {
return flags;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(itemName);
dest.writeString(appPackage);
dest.writeInt(flags);
}
@Override
public int describeContents() {
return 0;
}
public static final Creator<AddOpenAppNavDrawerItemParams> CREATOR = new Creator<AddOpenAppNavDrawerItemParams>() {
@Override
public AddOpenAppNavDrawerItemParams createFromParcel(Parcel in) {
return new AddOpenAppNavDrawerItemParams(in);
}
@Override
public AddOpenAppNavDrawerItemParams[] newArray(int size) {
return new AddOpenAppNavDrawerItemParams[size];
}
};
}

View file

@ -0,0 +1,3 @@
package net.osmand.aidl.navdrawer;
parcelable NavDrawerItem;

View file

@ -0,0 +1,73 @@
package net.osmand.aidl.navdrawer;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
public class NavDrawerItem implements Parcelable {
private String name;
private String uri;
private String iconName;
private int flags;
public NavDrawerItem(@NonNull String name, @NonNull String uri, @Nullable String iconName) {
this(name, uri, iconName, -1);
}
public NavDrawerItem(@NonNull String name, @NonNull String uri, @Nullable String iconName, int flags) {
this.name = name;
this.uri = uri;
this.iconName = iconName;
this.flags = flags;
}
protected NavDrawerItem(Parcel in) {
name = in.readString();
uri = in.readString();
iconName = in.readString();
flags = in.readInt();
}
public String getName() {
return name;
}
public String getUri() {
return uri;
}
public String getIconName() {
return iconName;
}
public int getFlags() {
return flags;
}
@Override
public void writeToParcel(Parcel dest, int f) {
dest.writeString(name);
dest.writeString(uri);
dest.writeString(iconName);
dest.writeInt(flags);
}
@Override
public int describeContents() {
return 0;
}
public static final Creator<NavDrawerItem> CREATOR = new Creator<NavDrawerItem>() {
@Override
public NavDrawerItem createFromParcel(Parcel in) {
return new NavDrawerItem(in);
}
@Override
public NavDrawerItem[] newArray(int size) {
return new NavDrawerItem[size];
}
};
}

View file

@ -0,0 +1,3 @@
package net.osmand.aidl.navdrawer;
parcelable SetNavDrawerItemsParams;

View file

@ -0,0 +1,56 @@
package net.osmand.aidl.navdrawer;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.NonNull;
import java.util.ArrayList;
import java.util.List;
public class SetNavDrawerItemsParams implements Parcelable {
private String appPackage;
private List<NavDrawerItem> items;
public SetNavDrawerItemsParams(@NonNull String appPackage, @NonNull List<NavDrawerItem> items) {
this.appPackage = appPackage;
this.items = items;
}
protected SetNavDrawerItemsParams(Parcel in) {
appPackage = in.readString();
items = new ArrayList<>();
in.readTypedList(items, NavDrawerItem.CREATOR);
}
public String getAppPackage() {
return appPackage;
}
public List<NavDrawerItem> getItems() {
return items;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(appPackage);
dest.writeTypedList(new ArrayList<>(items));
}
@Override
public int describeContents() {
return 0;
}
public static final Creator<SetNavDrawerItemsParams> CREATOR = new Creator<SetNavDrawerItemsParams>() {
@Override
public SetNavDrawerItemsParams createFromParcel(Parcel in) {
return new SetNavDrawerItemsParams(in);
}
@Override
public SetNavDrawerItemsParams[] newArray(int size) {
return new SetNavDrawerItemsParams[size];
}
};
}

View file

@ -742,9 +742,7 @@ public class OsmandSettings {
public final CommonPreference<Boolean> SHOW_DASHBOARD_ON_START = new BooleanPreference("should_show_dashboard_on_start", false).makeGlobal();
public final CommonPreference<Boolean> SHOW_DASHBOARD_ON_MAP_SCREEN = new BooleanPreference("show_dashboard_on_map_screen", false).makeGlobal();
public final CommonPreference<String> API_NAV_DRAWER_ITEM_NAME = new StringPreference("api_nav_drawer_item_name", "").makeGlobal();
public final CommonPreference<String> API_NAV_DRAWER_ITEM_APP_PACKAGE = new StringPreference("api_nav_drawer_item_app_package", "").makeGlobal();
public final CommonPreference<Integer> API_NAV_DRAWER_ITEM_FLAGS = new IntPreference("api_nav_drawer_item_flags", -1).makeGlobal();
public final CommonPreference<String> API_NAV_DRAWER_ITEMS_JSON = new StringPreference("api_nav_drawer_items_json", "{}").makeGlobal();
public final CommonPreference<Integer> NUMBER_OF_STARTS_FIRST_XMAS_SHOWN = new IntPreference("number_of_starts_first_xmas_shown", 0).makeGlobal();

View file

@ -795,7 +795,7 @@ public class MapActivityActions implements DialogProvider {
}
}).createItem());
app.getAidlApi().registerNavDrawerItem(mapActivity, optionsMenuHelper);
app.getAidlApi().registerNavDrawerItems(mapActivity, optionsMenuHelper);
optionsMenuHelper.addItem(new ItemBuilder().setTitleId(R.string.layer_map_appearance, mapActivity)
.setIcon(R.drawable.ic_configure_screen_dark)

View file

@ -28,7 +28,7 @@ public class WhatsNewDialogFragment extends DialogFragment {
final OsmandApplication osmandApplication = (OsmandApplication) getActivity().getApplication();
final String appVersion = Version.getAppVersion(osmandApplication);
builder.setTitle(getString(R.string.whats_new) + " " + appVersion)
.setMessage(getString(R.string.release_3_0))
.setMessage(getString(R.string.release_3_1))
.setNegativeButton(R.string.shared_string_close, null);
if (AppInitializer.LATEST_CHANGES_URL != null) {
builder.setPositiveButton(R.string.read_more, new DialogInterface.OnClickListener() {

View file

@ -5,7 +5,7 @@ import android.support.annotation.Nullable;
import net.osmand.PlatformUtil;
import net.osmand.osm.PoiCategory;
import net.osmand.osm.PoiType;
import net.osmand.osm.edit.Node;
import net.osmand.osm.edit.Entity;
import net.osmand.plus.OsmandApplication;
import net.osmand.util.Algorithms;
@ -23,7 +23,7 @@ public class EditPoiData {
private Set<TagsChangedListener> mListeners = new HashSet<>();
private LinkedHashMap<String, String > tagValues = new LinkedHashMap<String, String>();
private boolean isInEdit = false;
private Node entity;
private Entity entity;
public static final String POI_TYPE_TAG = "poi_type_tag";
public static final String REMOVE_TAG_PREFIX = "----";
@ -34,11 +34,11 @@ public class EditPoiData {
private Set<String> changedTags = new HashSet<>();
public EditPoiData(Node node, OsmandApplication app) {
public EditPoiData(Entity entity, OsmandApplication app) {
allTranslatedSubTypes = app.getPoiTypes().getAllTranslatedNames(true);
category = app.getPoiTypes().getOtherPoiCategory();
entity = node;
initTags(node);
this.entity = entity;
initTags(entity);
updateTypeTag(getPoiTypeString(), false);
}
@ -68,7 +68,7 @@ public class EditPoiData {
return s == null ? "" : s;
}
public Node getEntity() {
public Entity getEntity() {
return entity;
}
@ -90,10 +90,10 @@ public class EditPoiData {
}
}
private void initTags(Node node) {
private void initTags(Entity entity) {
checkNotInEdit();
for (String s : node.getTagKeySet()) {
tryAddTag(s, node.getTag(s));
for (String s : entity.getTagKeySet()) {
tryAddTag(s, entity.getTag(s));
}
retrieveType();
}

View file

@ -53,9 +53,11 @@ import net.osmand.data.Amenity;
import net.osmand.data.LatLon;
import net.osmand.osm.PoiCategory;
import net.osmand.osm.PoiType;
import net.osmand.osm.edit.Entity;
import net.osmand.osm.edit.EntityInfo;
import net.osmand.osm.edit.Node;
import net.osmand.osm.edit.OSMSettings;
import net.osmand.osm.edit.Way;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandPlugin;
import net.osmand.plus.OsmandSettings;
@ -82,7 +84,7 @@ public class EditPoiDialogFragment extends BaseOsmAndDialogFragment {
public static final String TAG = "EditPoiDialogFragment";
private static final Log LOG = PlatformUtil.getLog(EditPoiDialogFragment.class);
private static final String KEY_AMENITY_NODE = "key_amenity_node";
private static final String KEY_AMENITY_ENTITY = "key_amenity_entity";
private static final String TAGS_LIST = "tags_list";
private static final String IS_ADDING_POI = "is_adding_poi";
@ -115,8 +117,8 @@ public class EditPoiDialogFragment extends BaseOsmAndDialogFragment {
mOpenstreetmapUtil = plugin.getPoiModificationRemoteUtil();
}
Node node = (Node) getArguments().getSerializable(KEY_AMENITY_NODE);
editPoiData = new EditPoiData(node, getMyApplication());
Entity entity = (Entity) getArguments().getSerializable(KEY_AMENITY_ENTITY);
editPoiData = new EditPoiData(entity, getMyApplication());
}
@Override
@ -312,7 +314,7 @@ public class EditPoiDialogFragment extends BaseOsmAndDialogFragment {
}
});
if (!isAddingPoi) {
if (!isAddingPoi && Entity.EntityType.valueOf(editPoiData.getEntity()) == Entity.EntityType.NODE) {
Button deleteButton = (Button) view.findViewById(R.id.deleteButton);
deleteButton.setVisibility(View.VISIBLE);
deleteButton.setOnClickListener(new View.OnClickListener() {
@ -448,14 +450,23 @@ public class EditPoiDialogFragment extends BaseOsmAndDialogFragment {
}
private void save() {
Node original = editPoiData.getEntity();
Entity original = editPoiData.getEntity();
final boolean offlineEdit = mOpenstreetmapUtil instanceof OpenstreetmapLocalUtil;
Node node = new Node(original.getLatitude(), original.getLongitude(), original.getId());
Action action = node.getId() < 0 ? Action.CREATE : Action.MODIFY;
Entity entity;
if (original instanceof Node) {
entity = new Node(original.getLatitude(), original.getLongitude(), original.getId());
} else if (original instanceof Way) {
entity = new Way(original.getId(), ((Way) original).getNodeIds(), original.getLatitude(), original.getLongitude());
} else {
return;
}
Action action = entity.getId() < 0 ? Action.CREATE : Action.MODIFY;
for (Map.Entry<String, String> tag : editPoiData.getTagValues().entrySet()) {
if (!Algorithms.isEmpty(tag.getKey()) && !Algorithms.isEmpty(tag.getValue()) &&
!tag.getKey().equals(EditPoiData.POI_TYPE_TAG)) {
node.putTagNoLC(tag.getKey(), tag.getValue());
entity.putTagNoLC(tag.getKey(), tag.getValue());
}
}
String poiTypeTag = editPoiData.getTagValues().get(EditPoiData.POI_TYPE_TAG);
@ -463,29 +474,29 @@ public class EditPoiDialogFragment extends BaseOsmAndDialogFragment {
if (poiTypeTag != null) {
final PoiType poiType = editPoiData.getAllTranslatedSubTypes().get(poiTypeTag.trim().toLowerCase());
if (poiType != null) {
node.putTagNoLC(poiType.getEditOsmTag(), poiType.getEditOsmValue());
node.removeTag(EditPoiData.REMOVE_TAG_PREFIX + poiType.getEditOsmTag());
entity.putTagNoLC(poiType.getEditOsmTag(), poiType.getEditOsmValue());
entity.removeTag(EditPoiData.REMOVE_TAG_PREFIX + poiType.getEditOsmTag());
if (poiType.getOsmTag2() != null) {
node.putTagNoLC(poiType.getOsmTag2(), poiType.getOsmValue2());
node.removeTag(EditPoiData.REMOVE_TAG_PREFIX + poiType.getOsmTag2());
entity.putTagNoLC(poiType.getOsmTag2(), poiType.getOsmValue2());
entity.removeTag(EditPoiData.REMOVE_TAG_PREFIX + poiType.getOsmTag2());
}
} else if (!Algorithms.isEmpty(poiTypeTag)) {
PoiCategory category = editPoiData.getPoiCategory();
if (category != null) {
node.putTagNoLC(category.getDefaultTag(), poiTypeTag);
entity.putTagNoLC(category.getDefaultTag(), poiTypeTag);
}
}
if (offlineEdit && !Algorithms.isEmpty(poiTypeTag)) {
node.putTagNoLC(EditPoiData.POI_TYPE_TAG, poiTypeTag);
entity.putTagNoLC(EditPoiData.POI_TYPE_TAG, poiTypeTag);
}
String actionString = action == Action.CREATE ? getString(R.string.default_changeset_add) : getString(R.string.default_changeset_edit);
comment = actionString + " " + poiTypeTag;
}
commitNode(action, node, mOpenstreetmapUtil.getEntityInfo(node.getId()), comment, false,
new CallbackWithObject<Node>() {
commitEntity(action, entity, mOpenstreetmapUtil.getEntityInfo(entity.getId()), comment, false,
new CallbackWithObject<Entity>() {
@Override
public boolean processResult(Node result) {
public boolean processResult(Entity result) {
if (result != null) {
OsmEditingPlugin plugin = OsmandPlugin.getPlugin(OsmEditingPlugin.class);
if (plugin != null && offlineEdit) {
@ -533,12 +544,12 @@ public class EditPoiDialogFragment extends BaseOsmAndDialogFragment {
poiTypeEditText.setText(subCategory);
}
public static void commitNode(final Action action,
final Node node,
public static void commitEntity(final Action action,
final Entity entity,
final EntityInfo info,
final String comment,
final boolean closeChangeSet,
final CallbackWithObject<Node> postExecute,
final CallbackWithObject<Entity> postExecute,
final Activity activity,
final OpenstreetmapUtil openstreetmapUtil,
@Nullable final Set<String> changedTags) {
@ -546,7 +557,7 @@ public class EditPoiDialogFragment extends BaseOsmAndDialogFragment {
Toast.makeText(activity, activity.getResources().getString(R.string.poi_error_info_not_loaded), Toast.LENGTH_LONG).show();
return;
}
new AsyncTask<Void, Void, Node>() {
new AsyncTask<Void, Void, Entity>() {
ProgressDialog progress;
@Override
@ -556,12 +567,12 @@ public class EditPoiDialogFragment extends BaseOsmAndDialogFragment {
}
@Override
protected Node doInBackground(Void... params) {
return openstreetmapUtil.commitNodeImpl(action, node, info, comment, closeChangeSet, changedTags);
protected Entity doInBackground(Void... params) {
return openstreetmapUtil.commitEntityImpl(action, entity, info, comment, closeChangeSet, changedTags);
}
@Override
protected void onPostExecute(Node result) {
protected void onPostExecute(Entity result) {
progress.dismiss();
if (postExecute != null) {
postExecute.processResult(result);
@ -652,19 +663,19 @@ public class EditPoiDialogFragment extends BaseOsmAndDialogFragment {
return createInstance(node, true);
}
public static EditPoiDialogFragment createInstance(Node node, boolean isAddingPoi) {
public static EditPoiDialogFragment createInstance(Entity entity, boolean isAddingPoi) {
EditPoiDialogFragment editPoiDialogFragment = new EditPoiDialogFragment();
Bundle args = new Bundle();
args.putSerializable(KEY_AMENITY_NODE, node);
args.putSerializable(KEY_AMENITY_ENTITY, entity);
args.putBoolean(IS_ADDING_POI, isAddingPoi);
editPoiDialogFragment.setArguments(args);
return editPoiDialogFragment;
}
public static EditPoiDialogFragment createInstance(Node node, boolean isAddingPoi, Map<String, String> tagList) {
public static EditPoiDialogFragment createInstance(Entity entity, boolean isAddingPoi, Map<String, String> tagList) {
EditPoiDialogFragment editPoiDialogFragment = new EditPoiDialogFragment();
Bundle args = new Bundle();
args.putSerializable(KEY_AMENITY_NODE, node);
args.putSerializable(KEY_AMENITY_ENTITY, entity);
args.putBoolean(IS_ADDING_POI, isAddingPoi);
args.putSerializable(TAGS_LIST, (Serializable) Collections.unmodifiableMap(tagList));
editPoiDialogFragment.setArguments(args);
@ -683,16 +694,16 @@ public class EditPoiDialogFragment extends BaseOsmAndDialogFragment {
} else {
openstreetmapUtilToLoad = plugin.getPoiModificationRemoteUtil();
}
new AsyncTask<Void, Void, Node>() {
new AsyncTask<Void, Void, Entity>() {
@Override
protected Node doInBackground(Void... params) {
return openstreetmapUtilToLoad.loadNode(amenity);
protected Entity doInBackground(Void... params) {
return openstreetmapUtilToLoad.loadEntity(amenity);
}
protected void onPostExecute(Node n) {
if (n != null) {
protected void onPostExecute(Entity entity) {
if (entity != null) {
EditPoiDialogFragment fragment =
EditPoiDialogFragment.createInstance(n, false);
EditPoiDialogFragment.createInstance(entity, false);
fragment.show(activity.getSupportFragmentManager(), TAG);
} else {
Toast.makeText(activity,
@ -750,22 +761,22 @@ public class EditPoiDialogFragment extends BaseOsmAndDialogFragment {
}
public void deletePoiWithDialog(Amenity amenity) {
new AsyncTask<Amenity, Void, Node>() {
new AsyncTask<Amenity, Void, Entity>() {
@Override
protected Node doInBackground(Amenity... params) {
return openstreetmapUtil.loadNode(params[0]);
protected Entity doInBackground(Amenity... params) {
return openstreetmapUtil.loadEntity(params[0]);
}
@Override
protected void onPostExecute(Node node) {
deletePoiWithDialog(node);
protected void onPostExecute(Entity entity) {
deletePoiWithDialog(entity);
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, amenity);
}
public void deletePoiWithDialog(final Node n) {
if (n == null) {
public void deletePoiWithDialog(final Entity entity) {
if (entity == null) {
Toast.makeText(activity, activity.getResources().getString(R.string.poi_error_poi_not_found), Toast.LENGTH_LONG).show();
return;
}
@ -793,24 +804,24 @@ public class EditPoiDialogFragment extends BaseOsmAndDialogFragment {
builder.setPositiveButton(isLocalEdit ? R.string.shared_string_save : R.string.shared_string_delete, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
String c = comment == null ? null : comment.getText().toString();
boolean closeChangeSet = closeChangesetCheckBox != null
&& closeChangesetCheckBox.isChecked();
deleteNode(n, c, closeChangeSet);
if (entity instanceof Node) {
String c = comment == null ? null : comment.getText().toString();
boolean closeChangeSet = closeChangesetCheckBox != null
&& closeChangesetCheckBox.isChecked();
deleteNode(entity, c, closeChangeSet);
}
}
});
builder.create().show();
}
private void deleteNode(final Node n, final String c, final boolean closeChangeSet) {
private void deleteNode(final Entity entity, final String c, final boolean closeChangeSet) {
final boolean isLocalEdit = openstreetmapUtil instanceof OpenstreetmapLocalUtil;
commitNode(Action.DELETE, n, openstreetmapUtil.getEntityInfo(n.getId()), c, closeChangeSet,
new CallbackWithObject<Node>() {
commitEntity(Action.DELETE, entity, openstreetmapUtil.getEntityInfo(entity.getId()), c, closeChangeSet,
new CallbackWithObject<Entity>() {
@Override
public boolean processResult(Node result) {
public boolean processResult(Entity result) {
if (result != null) {
if (callback != null) {
callback.poiDeleted();

View file

@ -5,9 +5,11 @@ import net.osmand.data.Amenity;
import net.osmand.osm.AbstractPoiType;
import net.osmand.osm.MapPoiTypes;
import net.osmand.osm.PoiType;
import net.osmand.osm.edit.Entity;
import net.osmand.osm.edit.EntityInfo;
import net.osmand.osm.edit.Node;
import net.osmand.osm.edit.OSMSettings.OSMTagKey;
import net.osmand.osm.edit.Way;
import net.osmand.util.Algorithms;
import net.osmand.util.MapUtils;
@ -46,18 +48,24 @@ public class OpenstreetmapLocalUtil implements OpenstreetmapUtil {
}
@Override
public Node commitNodeImpl(OsmPoint.Action action, Node n, EntityInfo info, String comment,
boolean closeChangeSet, Set<String> changedTags){
Node newNode = n;
if (n.getId() == -1) {
newNode = new Node(n, Math.min(-2, plugin.getDBPOI().getMinID() - 1)); // generate local id for the created node
public Entity commitEntityImpl(OsmPoint.Action action, Entity entity, EntityInfo info, String comment,
boolean closeChangeSet, Set<String> changedTags) {
Entity newEntity = entity;
if (entity.getId() == -1) {
if (entity instanceof Node) {
newEntity = new Node((Node) entity, Math.min(-2, plugin.getDBPOI().getMinID() - 1));
} else if (entity instanceof Way) {
newEntity = new Way(Math.min(-2, plugin.getDBPOI().getMinID() - 1), ((Way) entity).getNodeIds(), entity.getLatitude(), entity.getLongitude());
} else {
return null;
}
}
OpenstreetmapPoint p = new OpenstreetmapPoint();
newNode.setChangedTags(changedTags);
p.setEntity(newNode);
newEntity.setChangedTags(changedTags);
p.setEntity(newEntity);
p.setAction(action);
p.setComment(comment);
if (p.getAction() == OsmPoint.Action.DELETE && newNode.getId() < 0) { //if it is our local poi
if (p.getAction() == OsmPoint.Action.DELETE && newEntity.getId() < 0) { //if it is our local poi
plugin.getDBPOI().deletePOI(p);
} else {
plugin.getDBPOI().addOpenstreetmap(p);
@ -65,22 +73,27 @@ public class OpenstreetmapLocalUtil implements OpenstreetmapUtil {
for (OnNodeCommittedListener listener : listeners) {
listener.onNoteCommitted();
}
return newNode;
return newEntity;
}
@Override
public Node loadNode(Amenity n) {
public Entity loadEntity(Amenity n) {
PoiType poiType = n.getType().getPoiTypeByKeyName(n.getSubType());
if(n.getId() % 2 == 1 || poiType == null){
// that's way id
boolean isWay = n.getId() % 2 == 1; // check if amenity is a way
if (poiType == null) {
return null;
}
long nodeId = n.getId() >> 1;
long entityId = n.getId() >> 1;
// EntityId id = new Entity.EntityId(EntityType.NODE, nodeId);
Node entity = new Node(n.getLocation().getLatitude(),
n.getLocation().getLongitude(),
nodeId);
// EntityId id = new Entity.EntityId(EntityType.NODE, entityId);
Entity entity;
if (isWay) {
entity = new Way(entityId, null, n.getLocation().getLatitude(), n.getLocation().getLongitude());
} else {
entity = new Node(n.getLocation().getLatitude(),
n.getLocation().getLongitude(),
entityId);
}
entity.putTagNoLC(EditPoiData.POI_TYPE_TAG, poiType.getTranslation());
if(poiType.getOsmTag2() != null) {
entity.putTagNoLC(poiType.getOsmTag2(), poiType.getOsmValue2());
@ -103,7 +116,9 @@ public class OpenstreetmapLocalUtil implements OpenstreetmapUtil {
}
// check whether this is node (because id of node could be the same as relation)
if(entity != null && MapUtils.getDistance(entity.getLatLon(), n.getLocation()) < 50){
if (entity instanceof Node && MapUtils.getDistance(entity.getLatLon(), n.getLocation()) < 50) {
return entity;
} else if (entity instanceof Way) {
return entity;
}
return null;

View file

@ -1,12 +1,12 @@
package net.osmand.plus.osmedit;
import net.osmand.osm.edit.Node;
import net.osmand.osm.edit.Entity;
import net.osmand.osm.edit.OSMSettings.OSMTagKey;
import net.osmand.util.Algorithms;
public class OpenstreetmapPoint extends OsmPoint {
private static final long serialVersionUID = 729654300829771467L;
private Node entity;
private Entity entity;
private String comment;
public OpenstreetmapPoint(){
@ -59,7 +59,7 @@ public class OpenstreetmapPoint extends OsmPoint {
}
public Node getEntity() {
public Entity getEntity() {
return entity;
}
@ -67,7 +67,7 @@ public class OpenstreetmapPoint extends OsmPoint {
return comment;
}
public void setEntity(Node entity) {
public void setEntity(Entity entity) {
this.entity = entity;
}

View file

@ -5,12 +5,15 @@ import android.widget.Toast;
import net.osmand.PlatformUtil;
import net.osmand.data.Amenity;
import net.osmand.data.LatLon;
import net.osmand.osm.PoiCategory;
import net.osmand.osm.PoiType;
import net.osmand.osm.edit.Entity;
import net.osmand.osm.edit.Entity.EntityId;
import net.osmand.osm.edit.Entity.EntityType;
import net.osmand.osm.edit.EntityInfo;
import net.osmand.osm.edit.Node;
import net.osmand.osm.edit.Way;
import net.osmand.osm.io.Base64;
import net.osmand.osm.io.NetworkUtils;
import net.osmand.osm.io.OsmBaseStorage;
@ -222,8 +225,28 @@ public class OpenstreetmapRemoteUtil implements OpenstreetmapUtil {
}
ser.attribute(null, "changeset", changeSetId + ""); //$NON-NLS-1$ //$NON-NLS-2$
for (String k : n.getTagKeySet()) {
String val = n.getTag(k);
writeTags(n, ser);
ser.endTag(null, "node"); //$NON-NLS-1$
}
private void writeWay(Way way, EntityInfo i, XmlSerializer ser, long changeSetId, String user)
throws IllegalArgumentException, IllegalStateException, IOException {
ser.startTag(null, "way"); //$NON-NLS-1$
ser.attribute(null, "id", way.getId() + ""); //$NON-NLS-1$ //$NON-NLS-2$
if (i != null) {
ser.attribute(null, "visible", i.getVisible()); //$NON-NLS-1$
ser.attribute(null, "version", i.getVersion()); //$NON-NLS-1$
}
ser.attribute(null, "changeset", changeSetId + ""); //$NON-NLS-1$ //$NON-NLS-2$
writeTags(way, ser);
ser.endTag(null, "way"); //$NON-NLS-1$
}
private void writeTags(Entity entity, XmlSerializer ser)
throws IllegalArgumentException, IllegalStateException, IOException {
for (String k : entity.getTagKeySet()) {
String val = entity.getTag(k);
if (val.length() == 0 || k.length() == 0 || EditPoiData.POI_TYPE_TAG.equals(k) ||
k.startsWith(EditPoiData.REMOVE_TAG_PREFIX) || k.contains(EditPoiData.REMOVE_TAG_PREFIX))
continue;
@ -232,7 +255,6 @@ public class OpenstreetmapRemoteUtil implements OpenstreetmapUtil {
ser.attribute(null, "v", val); //$NON-NLS-1$
ser.endTag(null, "tag"); //$NON-NLS-1$
}
ser.endTag(null, "node"); //$NON-NLS-1$
}
private boolean isNewChangesetRequired() {
@ -251,7 +273,7 @@ public class OpenstreetmapRemoteUtil implements OpenstreetmapUtil {
}
@Override
public Node commitNodeImpl(OsmPoint.Action action, final Node n, EntityInfo info, String comment,
public Entity commitEntityImpl(OsmPoint.Action action, final Entity n, EntityInfo info, String comment,
boolean closeChangeSet, Set<String> changedTags) {
if (isNewChangesetRequired()) {
changeSetId = openChangeSet(comment);
@ -262,7 +284,7 @@ public class OpenstreetmapRemoteUtil implements OpenstreetmapUtil {
}
try {
Node newN = n;
Entity newE = n;
StringWriter writer = new StringWriter(256);
XmlSerializer ser = Xml.newSerializer();
try {
@ -274,7 +296,11 @@ public class OpenstreetmapRemoteUtil implements OpenstreetmapUtil {
ser.startTag(null, OsmPoint.stringAction.get(action));
ser.attribute(null, "version", "0.6"); //$NON-NLS-1$ //$NON-NLS-2$
ser.attribute(null, "generator", Version.getAppName(ctx)); //$NON-NLS-1$
writeNode(n, info, ser, changeSetId, settings.USER_NAME.get());
if (n instanceof Node) {
writeNode((Node) n, info, ser, changeSetId, settings.USER_NAME.get());
} else if (n instanceof Way) {
writeWay((Way) n, info, ser, changeSetId, settings.USER_NAME.get());
}
ser.endTag(null, OsmPoint.stringAction.get(action));
ser.endTag(null, "osmChange"); //$NON-NLS-1$
ser.endDocument();
@ -293,12 +319,16 @@ public class OpenstreetmapRemoteUtil implements OpenstreetmapUtil {
int end = res.indexOf('\"', i); //$NON-NLS-1$
if (end > 0) {
newId = Long.parseLong(res.substring(i, end)); // << 1;
newN = new Node(n, newId);
if (n instanceof Node) {
newE = new Node((Node) n, newId);
} else if (n instanceof Way) {
newE = new Way(newId, ((Way) n).getNodeIds(), n.getLatitude(), n.getLongitude());
}
}
}
}
changeSetTimeStamp = System.currentTimeMillis();
return newN;
return newE;
}
return null;
} finally {
@ -319,17 +349,22 @@ public class OpenstreetmapRemoteUtil implements OpenstreetmapUtil {
}
public EntityInfo loadNode(Node n) {
long nodeId = n.getId(); // >> 1;
public EntityInfo loadEntity(Entity n) {
long entityId = n.getId(); // >> 1;
boolean isWay = false;
if (n instanceof Way) { // check if entity is a way
isWay = true;
}
try {
String res = sendRequest(
getSiteApi() + "api/0.6/node/" + nodeId, "GET", null, ctx.getString(R.string.loading_poi_obj) + nodeId, false); //$NON-NLS-1$ //$NON-NLS-2$
String api = isWay ? "api/0.6/way/" : "api/0.6/node/";
String res = sendRequest(getSiteApi() + api + entityId, "GET", null,
ctx.getString(R.string.loading_poi_obj) + entityId, false); //$NON-NLS-1$ //$NON-NLS-2$
if (res != null) {
OsmBaseStorage st = new OsmBaseStorage();
st.setConvertTagsToLC(false);
st.parseOSM(new ByteArrayInputStream(res.getBytes("UTF-8")), null, null, true); //$NON-NLS-1$
EntityId id = new Entity.EntityId(EntityType.NODE, nodeId);
Node entity = (Node) st.getRegisteredEntities().get(id);
EntityId id = new Entity.EntityId(isWay ? EntityType.WAY : EntityType.NODE, entityId);
Entity entity = st.getRegisteredEntities().get(id);
// merge non existing tags
Map<String, String> updatedTags = new HashMap<>();
for (String tagKey : entity.getTagKeySet()) {
@ -345,7 +380,7 @@ public class OpenstreetmapRemoteUtil implements OpenstreetmapUtil {
}
}
n.replaceTags(updatedTags);
if(MapUtils.getDistance(n.getLatLon(), entity.getLatLon()) < 10) {
if (!isWay && MapUtils.getDistance(n.getLatLon(), entity.getLatLon()) < 10) {
// avoid shifting due to round error
n.setLatitude(entity.getLatitude());
n.setLongitude(entity.getLongitude());
@ -356,7 +391,7 @@ public class OpenstreetmapRemoteUtil implements OpenstreetmapUtil {
}
} catch (IOException | XmlPullParserException e) {
log.error("Loading node failed " + nodeId, e); //$NON-NLS-1$
log.error("Loading entity failed " + entityId, e); //$NON-NLS-1$
Toast.makeText(ctx, ctx.getResources().getString(R.string.shared_string_io_error),
Toast.LENGTH_LONG).show();
}
@ -369,44 +404,44 @@ public class OpenstreetmapRemoteUtil implements OpenstreetmapUtil {
}
}
private boolean deletedTag(Node node, String tag) {
return node.getTagKeySet().contains(EditPoiData.REMOVE_TAG_PREFIX + tag);
private boolean deletedTag(Entity entity, String tag) {
return entity.getTagKeySet().contains(EditPoiData.REMOVE_TAG_PREFIX + tag);
}
@Override
public Node loadNode(Amenity n) {
if (n.getId() % 2 == 1) {
// that's way id
return null;
}
long nodeId = n.getId() >> 1;
public Entity loadEntity(Amenity n) {
boolean isWay = n.getId() % 2 == 1;// check if amenity is a way
long entityId = n.getId() >> 1;
try {
String res = sendRequest(
getSiteApi() + "api/0.6/node/" + nodeId, "GET", null, ctx.getString(R.string.loading_poi_obj) + nodeId, false); //$NON-NLS-1$ //$NON-NLS-2$
String api = isWay ? "api/0.6/way/" : "api/0.6/node/";
String res = sendRequest(getSiteApi() + api + entityId, "GET", null,
ctx.getString(R.string.loading_poi_obj) + entityId, false); //$NON-NLS-1$ //$NON-NLS-2$
if (res != null) {
OsmBaseStorage st = new OsmBaseStorage();
st.setConvertTagsToLC(false);
st.parseOSM(new ByteArrayInputStream(res.getBytes("UTF-8")), null, null, true); //$NON-NLS-1$
EntityId id = new Entity.EntityId(EntityType.NODE, nodeId);
Node entity = (Node) st.getRegisteredEntities().get(id);
EntityId id = new Entity.EntityId(isWay ? EntityType.WAY : EntityType.NODE, entityId);
Entity entity = (Entity) st.getRegisteredEntities().get(id);
entityInfo = st.getRegisteredEntityInfo().get(id);
entityInfoId = id;
// check whether this is node (because id of node could be the same as relation)
if (entity != null && MapUtils.getDistance(entity.getLatLon(), n.getLocation()) < 50) {
PoiType poiType = n.getType().getPoiTypeByKeyName(n.getSubType());
if(poiType.getEditOsmValue().equals(entity.getTag(poiType.getEditOsmTag()))) {
entity.removeTag(poiType.getEditOsmTag());
entity.putTagNoLC(EditPoiData.POI_TYPE_TAG, poiType.getTranslation());
} else {
// later we could try to determine tags
if (entity != null) {
if (!isWay && entity instanceof Node) {
// check whether this is node (because id of node could be the same as relation)
if (MapUtils.getDistance(entity.getLatLon(), n.getLocation()) < 50) {
return replaceEditOsmTags(n, entity);
}
} else if (isWay && entity instanceof Way) {
LatLon loc = n.getLocation();
entity.setLatitude(loc.getLatitude());
entity.setLongitude(loc.getLongitude());
return replaceEditOsmTags(n, entity);
}
return entity;
}
return null;
}
} catch (Exception e) {
log.error("Loading node failed " + nodeId, e); //$NON-NLS-1$
log.error("Loading entity failed " + entityId, e); //$NON-NLS-1$
ctx.runInUIThread(new Runnable() {
@Override
@ -419,6 +454,21 @@ public class OpenstreetmapRemoteUtil implements OpenstreetmapUtil {
return null;
}
private Entity replaceEditOsmTags(Amenity amenity, Entity entity) {
PoiCategory type = amenity.getType();
String subType = amenity.getSubType();
if (type != null && subType != null) {
PoiType poiType = type.getPoiTypeByKeyName(subType);
if (poiType != null && poiType.getEditOsmValue().equals(entity.getTag(poiType.getEditOsmTag()))) {
entity.removeTag(poiType.getEditOsmTag());
entity.putTagNoLC(EditPoiData.POI_TYPE_TAG, poiType.getTranslation());
} else {
// later we could try to determine tags
}
}
return entity;
}
private void showWarning(final String msg) {
ctx.runInUIThread(new Runnable() {
@Override
@ -427,5 +477,4 @@ public class OpenstreetmapRemoteUtil implements OpenstreetmapUtil {
}
});
}
}

View file

@ -3,18 +3,18 @@ package net.osmand.plus.osmedit;
import android.support.annotation.Nullable;
import net.osmand.data.Amenity;
import net.osmand.osm.edit.Entity;
import net.osmand.osm.edit.EntityInfo;
import net.osmand.osm.edit.Node;
import java.util.Set;
public interface OpenstreetmapUtil {
EntityInfo getEntityInfo(long id);
Node commitNodeImpl(OsmPoint.Action action, Node n, EntityInfo info, String comment, boolean closeChangeSet, @Nullable Set<String> changedTags);
Entity commitEntityImpl(OsmPoint.Action action, Entity n, EntityInfo info, String comment, boolean closeChangeSet, @Nullable Set<String> changedTags);
void closeChangeSet();
Node loadNode(Amenity n);
}
Entity loadEntity(Amenity n);
}

View file

@ -5,7 +5,9 @@ import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import net.osmand.osm.edit.Entity;
import net.osmand.osm.edit.Node;
import net.osmand.osm.edit.Way;
import net.osmand.util.Algorithms;
import java.util.ArrayList;
@ -16,9 +18,10 @@ import java.util.List;
import java.util.Map.Entry;
import java.util.Set;
public class OpenstreetmapsDbHelper extends SQLiteOpenHelper {
private static final int DATABASE_VERSION = 5;
private static final int DATABASE_VERSION = 6;
public static final String OPENSTREETMAP_DB_NAME = "openstreetmap"; //$NON-NLS-1$
private static final String OPENSTREETMAP_TABLE_NAME = "openstreetmaptable"; //$NON-NLS-1$
private static final String OPENSTREETMAP_COL_ID = "id"; //$NON-NLS-1$
@ -28,11 +31,14 @@ public class OpenstreetmapsDbHelper extends SQLiteOpenHelper {
private static final String OPENSTREETMAP_COL_ACTION = "action"; //$NON-NLS-1$
private static final String OPENSTREETMAP_COL_COMMENT = "comment"; //$NON-NLS-1$
private static final String OPENSTREETMAP_COL_CHANGED_TAGS = "changed_tags";
private static final String OPENSTREETMAP_COL_ENTITY_TYPE = "entity_type";
private static final String OPENSTREETMAP_TABLE_CREATE = "CREATE TABLE " + OPENSTREETMAP_TABLE_NAME + " (" + //$NON-NLS-1$ //$NON-NLS-2$
OPENSTREETMAP_COL_ID + " bigint,"+
OPENSTREETMAP_COL_LAT + " double," + OPENSTREETMAP_COL_LON + " double," +
OPENSTREETMAP_COL_TAGS + " VARCHAR(2048)," +
OPENSTREETMAP_COL_ACTION + " TEXT, " + OPENSTREETMAP_COL_COMMENT + " TEXT, " + OPENSTREETMAP_COL_CHANGED_TAGS + " TEXT);";
OPENSTREETMAP_COL_ACTION + " TEXT, " + OPENSTREETMAP_COL_COMMENT + " TEXT," +
" " + OPENSTREETMAP_COL_CHANGED_TAGS + " TEXT, " + OPENSTREETMAP_COL_ENTITY_TYPE + " TEXT);";
List<OpenstreetmapPoint> cache = null;
public OpenstreetmapsDbHelper(Context context) {
@ -53,6 +59,11 @@ public class OpenstreetmapsDbHelper extends SQLiteOpenHelper {
if (oldVersion < 5) {
db.execSQL("ALTER TABLE " + OPENSTREETMAP_TABLE_NAME + " ADD " + OPENSTREETMAP_COL_CHANGED_TAGS + " TEXT");
}
if (oldVersion < 6) {
db.execSQL("ALTER TABLE " + OPENSTREETMAP_TABLE_NAME + " ADD " + OPENSTREETMAP_COL_ENTITY_TYPE + " TEXT");
db.execSQL("UPDATE " + OPENSTREETMAP_TABLE_NAME + " SET " + OPENSTREETMAP_COL_ENTITY_TYPE + " = ? " +
"WHERE " + OPENSTREETMAP_COL_ENTITY_TYPE + " IS NULL", new String[]{Entity.EntityType.NODE.toString()});
}
}
public List<OpenstreetmapPoint> getOpenstreetmapPoints() {
@ -66,7 +77,8 @@ public class OpenstreetmapsDbHelper extends SQLiteOpenHelper {
SQLiteDatabase db = getWritableDatabase();
if (db != null) {
StringBuilder tags = new StringBuilder();
Iterator<Entry<String, String>> eit = p.getEntity().getTags().entrySet().iterator();
Entity entity = p.getEntity();
Iterator<Entry<String, String>> eit = entity.getTags().entrySet().iterator();
while(eit.hasNext()) {
Entry<String, String> e = eit.next();
if(Algorithms.isEmpty(e.getKey()) || Algorithms.isEmpty(e.getValue())) {
@ -97,10 +109,13 @@ public class OpenstreetmapsDbHelper extends SQLiteOpenHelper {
OPENSTREETMAP_COL_TAGS + ", " +
OPENSTREETMAP_COL_ACTION + ", " +
OPENSTREETMAP_COL_COMMENT + ", " +
OPENSTREETMAP_COL_CHANGED_TAGS + ")" +
" VALUES (?, ?, ?, ?, ?, ?, ?)",
OPENSTREETMAP_COL_CHANGED_TAGS + ", " +
OPENSTREETMAP_COL_ENTITY_TYPE + ")" +
" VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
new Object[]{p.getId(), p.getLatitude(), p.getLongitude(), tags.toString(),
OsmPoint.stringAction.get(p.getAction()), p.getComment(), chTags == null ? null : changedTags.toString()});
OsmPoint.stringAction.get(p.getAction()), p.getComment(),
chTags == null ? null : changedTags.toString(), Entity.EntityType.valueOf(entity)});
db.close();
checkOpenstreetmapPoints();
return true;
@ -108,8 +123,6 @@ public class OpenstreetmapsDbHelper extends SQLiteOpenHelper {
return false;
}
public boolean deletePOI(OpenstreetmapPoint p) {
SQLiteDatabase db = getWritableDatabase();
if (db != null) {
@ -122,7 +135,6 @@ public class OpenstreetmapsDbHelper extends SQLiteOpenHelper {
return false;
}
private List<OpenstreetmapPoint> checkOpenstreetmapPoints(){
SQLiteDatabase db = getReadableDatabase();
List<OpenstreetmapPoint> points = new ArrayList<OpenstreetmapPoint>();
@ -134,27 +146,39 @@ public class OpenstreetmapsDbHelper extends SQLiteOpenHelper {
OPENSTREETMAP_COL_ACTION + "," +
OPENSTREETMAP_COL_COMMENT + "," +
OPENSTREETMAP_COL_TAGS + "," +
OPENSTREETMAP_COL_CHANGED_TAGS +
OPENSTREETMAP_COL_CHANGED_TAGS + "," +
OPENSTREETMAP_COL_ENTITY_TYPE +
" FROM " + OPENSTREETMAP_TABLE_NAME, null);
if (query.moveToFirst()) {
do {
OpenstreetmapPoint p = new OpenstreetmapPoint();
Node entity = new Node(query.getDouble(1),
query.getDouble(2),
query.getLong(0));
String tags = query.getString(5);
String[] split = tags.split("\\$\\$\\$");
for(int i=0; i<split.length - 1; i+= 2){
entity.putTagNoLC(split[i].trim(), split[i+1].trim());
String entityType = query.getString(7);
Entity entity = null;
if (entityType != null && Entity.EntityType.valueOf(entityType) == Entity.EntityType.NODE) {
entity = new Node(query.getDouble(1),
query.getDouble(2),
query.getLong(0));
} else if (entityType != null && Entity.EntityType.valueOf(entityType) == Entity.EntityType.WAY) {
entity = new Way(query.getLong(0), null,
query.getDouble(1),
query.getDouble(2));
}
String changedTags = query.getString(6);
if (changedTags != null) {
entity.setChangedTags(new HashSet<>(Arrays.asList(changedTags.split("\\$\\$\\$"))));
if (entity != null) {
String tags = query.getString(5);
String[] split = tags.split("\\$\\$\\$");
for (int i = 0; i < split.length - 1; i += 2) {
entity.putTagNoLC(split[i].trim(), split[i + 1].trim());
}
String changedTags = query.getString(6);
if (changedTags != null) {
entity.setChangedTags(new HashSet<>(Arrays.asList(changedTags.split("\\$\\$\\$"))));
}
p.setEntity(entity);
p.setAction(query.getString(3));
p.setComment(query.getString(4));
points.add(p);
}
p.setEntity(entity);
p.setAction(query.getString(3));
p.setComment(query.getString(4));
points.add(p);
} while (query.moveToNext());
}
query.close();

View file

@ -21,7 +21,7 @@ import net.osmand.PlatformUtil;
import net.osmand.data.Amenity;
import net.osmand.data.TransportStop;
import net.osmand.osm.PoiType;
import net.osmand.osm.edit.Node;
import net.osmand.osm.edit.Entity;
import net.osmand.plus.ContextMenuAdapter;
import net.osmand.plus.ContextMenuAdapter.ItemClickListener;
import net.osmand.plus.ContextMenuItem;
@ -200,7 +200,7 @@ public class OsmEditingPlugin extends OsmandPlugin {
EditPoiDialogFragment.showEditInstance(selectedObj instanceof TransportStop ?
((TransportStop) selectedObj).getAmenity() : (Amenity) selectedObj, mapActivity);
} else if (resId == R.string.poi_context_menu_modify_osm_change) {
final Node entity = ((OpenstreetmapPoint) selectedObj).getEntity();
final Entity entity = ((OpenstreetmapPoint) selectedObj).getEntity();
EditPoiDialogFragment.createInstance(entity, false)
.show(mapActivity.getSupportFragmentManager(), EditPoiDialogFragment.TAG);
}

View file

@ -31,7 +31,9 @@ import android.widget.Toast;
import net.osmand.AndroidUtils;
import net.osmand.data.PointDescription;
import net.osmand.osm.edit.Entity;
import net.osmand.osm.edit.Node;
import net.osmand.osm.edit.Way;
import net.osmand.plus.GPXUtilities;
import net.osmand.plus.GPXUtilities.GPXFile;
import net.osmand.plus.GPXUtilities.WptPt;
@ -537,7 +539,7 @@ public class OsmEditsFragment extends OsmAndListFragment implements SendPoiDialo
@Override
public void onModifyOsmChangeClick(OsmPoint osmPoint) {
OpenstreetmapPoint i = (OpenstreetmapPoint) getPointAfterModify(osmPoint);
final Node entity = i.getEntity();
final Entity entity = i.getEntity();
refreshId = entity.getId();
EditPoiDialogFragment.createInstance(entity, false).show(getActivity().getSupportFragmentManager(), "edit_poi");
}
@ -817,22 +819,10 @@ public class OsmEditsFragment extends OsmAndListFragment implements SendPoiDialo
if (point.getGroup() == Group.POI) {
OpenstreetmapPoint p = (OpenstreetmapPoint) point;
if (p.getAction() == a) {
sz.startTag("", "node");
sz.attribute("", "lat", p.getLatitude() + "");
sz.attribute("", "lon", p.getLongitude() + "");
sz.attribute("", "id", p.getId() + "");
sz.attribute("", "version", "1");
for (String tag : p.getEntity().getTagKeySet()) {
String val = p.getEntity().getTag(tag);
if (isNotValid(tag, val)) {
continue;
}
sz.startTag("", "tag");
sz.attribute("", "k", tag);
sz.attribute("", "v", val);
sz.endTag("", "tag");
Entity entity = p.getEntity();
if (entity != null && entity instanceof Node) {
writeNode(sz, (Node) entity);
}
sz.endTag("", "node");
}
} else if (point.getGroup() == Group.BUG) {
OsmNotesPoint p = (OsmNotesPoint) point;
@ -850,6 +840,36 @@ public class OsmEditsFragment extends OsmAndListFragment implements SendPoiDialo
}
}
private void writeNode(XmlSerializer sz, Node p) {
try {
sz.startTag("", "node");
sz.attribute("", "lat", p.getLatitude() + "");
sz.attribute("", "lon", p.getLongitude() + "");
sz.attribute("", "id", p.getId() + "");
sz.attribute("", "version", "1");
writeTags(sz, p);
sz.endTag("", "node");
} catch (IOException e) {
e.printStackTrace();
}
}
private void writeTags(XmlSerializer sz, Entity p) {
for (String tag : p.getTagKeySet()) {
String val = p.getTag(tag);
if (isNotValid(tag, val)) {
continue;
}
try {
sz.startTag("", "tag");
sz.attribute("", "k", tag);
sz.attribute("", "v", val);
sz.endTag("", "tag");
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Override
protected void onPreExecute() {

View file

@ -13,7 +13,7 @@ import android.widget.Toast;
import net.osmand.data.LatLon;
import net.osmand.data.PointDescription;
import net.osmand.data.RotatedTileBox;
import net.osmand.osm.edit.Node;
import net.osmand.osm.edit.Entity;
import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.views.ContextMenuLayer;
@ -209,9 +209,9 @@ public class OsmEditsLayer extends OsmandMapLayer implements ContextMenuLayer.IC
if (o instanceof OsmPoint) {
if (o instanceof OpenstreetmapPoint) {
OpenstreetmapPoint objectInMotion = (OpenstreetmapPoint) o;
Node node = objectInMotion.getEntity();
node.setLatitude(position.getLatitude());
node.setLongitude(position.getLongitude());
Entity entity = objectInMotion.getEntity();
entity.setLatitude(position.getLatitude());
entity.setLongitude(position.getLongitude());
new SaveOsmChangeAsyncTask(mOsmChangeUtil, callback, objectInMotion).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
} else if (o instanceof OsmNotesPoint) {
OsmNotesPoint objectInMotion = (OsmNotesPoint) o;
@ -223,7 +223,7 @@ public class OsmEditsLayer extends OsmandMapLayer implements ContextMenuLayer.IC
}
}
static class SaveOsmChangeAsyncTask extends AsyncTask<Void, Void, Node> {
static class SaveOsmChangeAsyncTask extends AsyncTask<Void, Void, Entity> {
private final OpenstreetmapLocalUtil mOpenstreetmapUtil;
@Nullable
private final ContextMenuLayer.ApplyMovedObjectCallback mCallback;
@ -237,16 +237,16 @@ public class OsmEditsLayer extends OsmandMapLayer implements ContextMenuLayer.IC
}
@Override
protected Node doInBackground(Void... params) {
Node node = objectInMotion.getEntity();
return mOpenstreetmapUtil.commitNodeImpl(objectInMotion.getAction(), node,
mOpenstreetmapUtil.getEntityInfo(node.getId()), "", false, null);
protected Entity doInBackground(Void... params) {
Entity entity = objectInMotion.getEntity();
return mOpenstreetmapUtil.commitEntityImpl(objectInMotion.getAction(), entity,
mOpenstreetmapUtil.getEntityInfo(entity.getId()), "", false, null);
}
@Override
protected void onPostExecute(Node newNode) {
protected void onPostExecute(Entity newEntity) {
if (mCallback != null) {
mCallback.onApplyMovedObject(newNode != null, objectInMotion);
mCallback.onApplyMovedObject(newEntity != null, objectInMotion);
}
}
}

View file

@ -3,6 +3,7 @@ package net.osmand.plus.osmedit;
import android.content.DialogInterface;
import android.os.AsyncTask;
import net.osmand.osm.edit.Entity;
import net.osmand.osm.edit.EntityInfo;
import net.osmand.osm.edit.Node;
import net.osmand.plus.dialogs.ProgressDialogFragment;
@ -53,9 +54,9 @@ public class UploadOpenstreetmapPointAsyncTask
OpenstreetmapPoint p = (OpenstreetmapPoint) point;
EntityInfo entityInfo = null;
if (OsmPoint.Action.CREATE != p.getAction()) {
entityInfo = remotepoi.loadNode(p.getEntity());
entityInfo = remotepoi.loadEntity(p.getEntity());
}
Node n = remotepoi.commitNodeImpl(p.getAction(), p.getEntity(), entityInfo,
Entity n = remotepoi.commitEntityImpl(p.getAction(), p.getEntity(), entityInfo,
p.getComment(), false, null);
if (n != null) {
uploaded = true;

View file

@ -32,6 +32,7 @@ import net.osmand.osm.AbstractPoiType;
import net.osmand.osm.MapPoiTypes;
import net.osmand.osm.PoiCategory;
import net.osmand.osm.PoiType;
import net.osmand.osm.edit.Entity;
import net.osmand.osm.edit.Node;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandPlugin;
@ -91,9 +92,9 @@ public class AddPOIAction extends QuickAction {
node.replaceTags(getTagsFromParams());
EditPoiData editPoiData = new EditPoiData(node, activity.getMyApplication());
if (Boolean.valueOf(getParams().get(KEY_DIALOG))) {
Node newNode = editPoiData.getEntity();
Entity newEntity = editPoiData.getEntity();
EditPoiDialogFragment editPoiDialogFragment =
EditPoiDialogFragment.createInstance(newNode, true, getTagsFromParams());
EditPoiDialogFragment.createInstance(newEntity, true, getTagsFromParams());
editPoiDialogFragment.show(activity.getSupportFragmentManager(),
EditPoiDialogFragment.TAG);
} else {
@ -129,11 +130,11 @@ public class AddPOIAction extends QuickAction {
newNode.putTagNoLC(tag.getKey(), tag.getValue());
}
}
EditPoiDialogFragment.commitNode(action, newNode, mOpenstreetmapUtil.getEntityInfo(newNode.getId()), "", false,
new CallbackWithObject<Node>() {
EditPoiDialogFragment.commitEntity(action, newNode, mOpenstreetmapUtil.getEntityInfo(newNode.getId()), "", false,
new CallbackWithObject<Entity>() {
@Override
public boolean processResult(Node result) {
public boolean processResult(Entity result) {
if (result != null) {
OsmEditingPlugin plugin = OsmandPlugin.getPlugin(OsmEditingPlugin.class);
if (plugin != null && offlineEdit) {

View file

@ -1871,6 +1871,11 @@ public class QuickSearchDialogFragment extends DialogFragment implements OsmAndC
@Override
public void onlineSearchOnClick() {
final OsmandSettings settings = app.getSettings();
if (!settings.isInternetConnectionAvailable()) {
Toast.makeText(app, R.string.internet_not_available, Toast.LENGTH_LONG).show();
return;
}
startOnlineSearch();
mainSearchFragment.getAdapter().clear();
updateTabbarVisibility(false);

View file

@ -42,6 +42,8 @@ public class AidlMapLayer extends OsmandMapLayer implements IContextMenuProvider
private static final int POINT_OUTER_COLOR = 0x88555555;
private static final float START_ZOOM = 7;
private static final int SMALL_ICON_SIZE_DP = 20;
private static final int BIG_ICON_SIZE_DP = 40;
private final MapActivity map;
private OsmandMapTileView view;
@ -60,7 +62,7 @@ public class AidlMapLayer extends OsmandMapLayer implements IContextMenuProvider
private int smallIconSize;
private int bigIconSize;
private PointType pointsType;
private PointsType pointsType;
private MapTextLayer mapTextLayer;
@ -103,8 +105,8 @@ public class AidlMapLayer extends OsmandMapLayer implements IContextMenuProvider
? R.drawable.map_pin_user_location_night : R.drawable.map_pin_user_location_day);
placeholder = BitmapFactory.decodeResource(res, R.drawable.img_user_picture);
smallIconSize = AndroidUtils.dpToPx(map, 20);
bigIconSize = AndroidUtils.dpToPx(map, 40);
smallIconSize = AndroidUtils.dpToPx(map, SMALL_ICON_SIZE_DP);
bigIconSize = AndroidUtils.dpToPx(map, BIG_ICON_SIZE_DP);
mapTextLayer = view.getLayerByClass(MapTextLayer.class);
}
@ -116,7 +118,7 @@ public class AidlMapLayer extends OsmandMapLayer implements IContextMenuProvider
@Override
public void onPrepareBufferImage(Canvas canvas, RotatedTileBox tileBox, DrawSettings settings) {
pointsType = getPointsType(tileBox.getZoom());
if (pointsType == PointType.NONE) {
if (pointsType == PointsType.INVISIBLE) {
mapTextLayer.putData(this, Collections.emptyList());
return;
}
@ -132,7 +134,7 @@ public class AidlMapLayer extends OsmandMapLayer implements IContextMenuProvider
int y = (int) tileBox.getPixYFromLatLon(l.getLatitude(), l.getLongitude());
if (tileBox.containsPoint(x, y, bigIconSize)) {
Bitmap image = null;
if (pointsType != PointType.STANDARD) {
if (pointsType != PointsType.STANDARD) {
String imageUri = point.getParams().get(AMapPoint.POINT_IMAGE_URI_PARAM);
if (!TextUtils.isEmpty(imageUri)) {
image = pointImages.get(imageUri);
@ -157,19 +159,19 @@ public class AidlMapLayer extends OsmandMapLayer implements IContextMenuProvider
if (image == null) {
image = placeholder;
}
if (pointsType == PointType.STANDARD) {
if (pointsType == PointsType.STANDARD) {
int radius = getRadiusPoi(tb);
float density = tb.getDensity();
pointInnerCircle.setColor(point.getColor());
canvas.drawCircle(x, y, radius + density, pointOuterCircle);
canvas.drawCircle(x, y, radius - density, pointInnerCircle);
} else if (pointsType == PointType.CIRCLE) {
} else if (pointsType == PointsType.CIRCLE) {
drawColoredBitmap(canvas, x, y, circle, point.getColor());
} else if (pointsType == PointType.SMALL_ICON) {
} else if (pointsType == PointsType.SMALL_ICON) {
drawColoredBitmap(canvas, x, y, smallIconBg, point.getColor());
bitmapPaint.setColorFilter(null);
canvas.drawBitmap(image, null, getDstRect(x, y, smallIconSize / 2), bitmapPaint);
} else if (pointsType == PointType.BIG_ICON) {
} else if (pointsType == PointsType.BIG_ICON) {
bitmapPaint.setColorFilter(null);
// FIXME: vertical offset
float vOffset = bigIconBg.getHeight() * 0.9f;
@ -263,13 +265,13 @@ public class AidlMapLayer extends OsmandMapLayer implements IContextMenuProvider
@Override
public int getTextShift(AMapPoint o, RotatedTileBox rb) {
if (pointsType == PointType.STANDARD) {
if (pointsType == PointsType.STANDARD) {
return (int) (getRadiusPoi(rb) * 1.5);
} else if (pointsType == PointType.CIRCLE) {
} else if (pointsType == PointsType.CIRCLE) {
return (int) (circle.getHeight() * 0.6);
} else if (pointsType == PointType.SMALL_ICON) {
} else if (pointsType == PointsType.SMALL_ICON) {
return smallIconBg.getHeight() / 2;
} else if (pointsType == PointType.BIG_ICON) {
} else if (pointsType == PointsType.BIG_ICON) {
return bigIconBg.getHeight() / 6;
}
return 0;
@ -296,18 +298,18 @@ public class AidlMapLayer extends OsmandMapLayer implements IContextMenuProvider
}
}
private PointType getPointsType(int zoom) {
private PointsType getPointsType(int zoom) {
if (!aidlLayer.isImagePoints()) {
return zoom >= START_ZOOM ? PointType.STANDARD : PointType.NONE;
return zoom >= START_ZOOM ? PointsType.STANDARD : PointsType.INVISIBLE;
}
if (zoom >= aidlLayer.getCirclePointMinZoom() && zoom <= aidlLayer.getCirclePointMaxZoom()) {
return PointType.CIRCLE;
return PointsType.CIRCLE;
} else if (zoom >= aidlLayer.getSmallPointMinZoom() && zoom <= aidlLayer.getSmallPointMaxZoom()) {
return PointType.SMALL_ICON;
return PointsType.SMALL_ICON;
} else if (zoom >= aidlLayer.getBigPointMinZoom() && zoom <= aidlLayer.getBigPointMaxZoom()) {
return PointType.BIG_ICON;
return PointsType.BIG_ICON;
}
return PointType.NONE;
return PointsType.INVISIBLE;
}
private int getRadiusPoi(RotatedTileBox tb) {
@ -327,13 +329,13 @@ public class AidlMapLayer extends OsmandMapLayer implements IContextMenuProvider
private int getPointRadius(RotatedTileBox tb) {
int r = 0;
if (pointsType == PointType.STANDARD) {
if (pointsType == PointsType.STANDARD) {
r = getRadiusPoi(tb);
} else if (pointsType == PointType.CIRCLE) {
} else if (pointsType == PointsType.CIRCLE) {
r = circle.getHeight() / 2;
} else if (pointsType == PointType.SMALL_ICON) {
} else if (pointsType == PointsType.SMALL_ICON) {
r = smallIconSize / 2;
} else if (pointsType == PointType.BIG_ICON) {
} else if (pointsType == PointsType.BIG_ICON) {
r = bigIconSize / 2;
}
return r * 3 / 2;
@ -357,12 +359,12 @@ public class AidlMapLayer extends OsmandMapLayer implements IContextMenuProvider
}
}
private enum PointType {
private enum PointsType {
STANDARD,
CIRCLE,
SMALL_ICON,
BIG_ICON,
NONE
INVISIBLE
}
private static class PointImageReaderTask extends AsyncTask<String, Void, Boolean> {