Merge branch 'master' into travel_obf_gpx_profile

This commit is contained in:
Dima-1 2021-02-02 17:05:05 +02:00
commit 7f678334c2
94 changed files with 2588 additions and 1719 deletions

3
.gitignore vendored
View file

@ -16,7 +16,8 @@ OsmAndCore_*.aar
*.iml
.settings
.idea
.project
**/.project
**/.classpath
out/
# Huawei

View file

@ -8,6 +8,7 @@ import net.osmand.aidlapi.AidlParams;
import net.osmand.aidlapi.profile.AExportSettingsType;
import java.util.ArrayList;
import java.util.List;
import static net.osmand.aidlapi.profile.ExportProfileParams.SETTINGS_TYPE_KEY;
@ -15,16 +16,18 @@ public class ProfileSettingsParams extends AidlParams {
public static final String VERSION_KEY = "version";
public static final String REPLACE_KEY = "replace";
public static final String SILENT_IMPORT_KEY = "silentImport";
public static final String LATEST_CHANGES_KEY = "latestChanges";
public static final String PROFILE_SETTINGS_URI_KEY = "profileSettingsUri";
private Uri profileSettingsUri;
private String latestChanges;
private int version;
private ArrayList<String> settingsTypeKeyList = new ArrayList<>();
boolean replace;
private List<String> settingsTypeKeyList = new ArrayList<>();
private boolean silent;
private boolean replace;
public ProfileSettingsParams(Uri profileSettingsUri, ArrayList<AExportSettingsType> settingsTypeList, boolean replace,
String latestChanges, int version) {
public ProfileSettingsParams(Uri profileSettingsUri, List<AExportSettingsType> settingsTypeList, boolean replace,
boolean silent, String latestChanges, int version) {
this.profileSettingsUri = profileSettingsUri;
for (AExportSettingsType settingsType : settingsTypeList) {
settingsTypeKeyList.add(settingsType.name());
@ -32,6 +35,7 @@ public class ProfileSettingsParams extends AidlParams {
this.replace = replace;
this.latestChanges = latestChanges;
this.version = version;
this.silent = silent;
}
public ProfileSettingsParams(Parcel in) {
@ -62,7 +66,7 @@ public class ProfileSettingsParams extends AidlParams {
return profileSettingsUri;
}
public ArrayList<String> getSettingsTypeKeys() {
public List<String> getSettingsTypeKeys() {
return settingsTypeKeyList;
}
@ -70,13 +74,18 @@ public class ProfileSettingsParams extends AidlParams {
return replace;
}
public boolean isSilent() {
return silent;
}
@Override
public void writeToBundle(Bundle bundle) {
bundle.putInt(VERSION_KEY, version);
bundle.putString(LATEST_CHANGES_KEY, latestChanges);
bundle.putParcelable(PROFILE_SETTINGS_URI_KEY, profileSettingsUri);
bundle.putStringArrayList(SETTINGS_TYPE_KEY, settingsTypeKeyList);
bundle.putStringArrayList(SETTINGS_TYPE_KEY, new ArrayList<>(settingsTypeKeyList));
bundle.putBoolean(REPLACE_KEY, replace);
bundle.putBoolean(SILENT_IMPORT_KEY, silent);
}
@Override
@ -86,5 +95,6 @@ public class ProfileSettingsParams extends AidlParams {
profileSettingsUri = bundle.getParcelable(PROFILE_SETTINGS_URI_KEY);
settingsTypeKeyList = bundle.getStringArrayList(SETTINGS_TYPE_KEY);
replace = bundle.getBoolean(REPLACE_KEY);
silent = bundle.getBoolean(SILENT_IMPORT_KEY);
}
}

View file

@ -0,0 +1,218 @@
package net.osmand.osm;
public enum RouteActivityType {
WATER("Water", "yellow"), WINTER("Winter", "yellow"), SNOWMOBILE("Snowmobile", "yellow"), RIDING("Riding", "yellow"), RACING("Racing", "yellow"),
MOUNTAINBIKE("Mountainbike", "blue"), CYCLING("Cycling", "blue"),
HIKING("Hiking", "orange"), RUNNING("Running", "orange"), WALKING("Walking", "orange"),
OFFROAD("Off-road", "yellow"),
MOTORBIKE("Motorbike", "green"), CAR("Car", "green");
// less specific bottom order
String name;
String color;
private RouteActivityType(String nm, String clr) {
this.name = nm;
this.color = clr;
}
public String getName() {
return name;
}
public String getColor() {
return color;
}
public static RouteActivityType getTypeFromTags(String[] tags) {
RouteActivityType activityType = null;
for (String tg : tags) {
RouteActivityType rat = RouteActivityType.convertFromOsmGPXTag(tg);
if (rat != null) {
if (activityType == null || activityType.ordinal() > rat.ordinal()) {
activityType = rat;
}
}
}
return activityType;
}
public static RouteActivityType convertFromOsmGPXTag(String tg) {
String t = tg.toLowerCase();
if ("mountain hiking".equalsIgnoreCase(t)) {
return HIKING;
}
if ("motorcar".equalsIgnoreCase(t)) {
return CAR;
}
if ("laufen".equalsIgnoreCase(t)) {
return RUNNING;
}
if ("pedestrian".equalsIgnoreCase(t)) {
return WALKING;
}
switch (t) {
case "mountainbiking":
case "mtb":
case "mountainbike":
case "mountain bike":
case "mountain biking":
case "mountbarker":
case "mtb-tour":
case "ciclismo-mtb-gravel":
case "vtt":
case "btt":
case "vth":
case "mtb ride":
return MOUNTAINBIKE;
case "hiking":
case "route=hiking":
case "mountain hiking":
case "hiking trail":
case "wandern":
case "hike":
case "randonnée":
case "trekking":
case "climbing":
return HIKING;
case "bike":
case "biking":
case "bicycling":
case "bicycle":
case "cycling":
case "cycle":
case "cycleway":
case "cykel":
case "handcycle":
case "cyclotourisme":
case "route=bicycle":
case "cyclotourism":
case "fietsen":
case "вело":
case "велосипед":
case "rower":
case "trasa rowerem":
case "vélo":
case "velo":
case "radtour":
case "bici":
case "fiets":
case "fahrrad":
case "ncn":
case "icn":
case "lcn":
case "network=ncn":
case "network=icn":
case "network=lcn":
return CYCLING;
case "car":
case "motorcar":
case "by car":
case "auto":
case "автомобиль":
case "automobile":
case "autós":
case "driving":
case "drive":
case "van":
case "авто":
case "на автомобиле":
case "bus":
case "truck":
case "taxi":
return CAR;
case "running":
case "run":
case "rungis":
case "trail running":
case "trailrunning":
case "бег":
case "laufen":
case "langlauf":
case "lauf":
case "course":
case "jogging":
case "fitotrack":
return RUNNING;
case "wanderung":
case "walking":
case "walk":
case "nightwalk":
case "walkway":
case "пешком":
case "пеший":
case "pěšky":
case "marche":
case "pedestrian":
case "foot":
case "footing":
case "on_foot":
case "byfoot":
case "onfoot":
case "sightseeing":
case "geocaching":
case "etnanatura":
case "etna":
case "iwn":
case "lwn":
case "rwn":
case "network=iwn":
case "network=lwn":
case "network=rwn":
return WALKING;
case "ling-moto":
case "motorbiking":
case "motorcycle":
case "motorrad":
case "motorbike":
case "motor bike":
case "FVbike":
case "Motorrad":
return MOTORBIKE;
case "offroad":
case "off-road":
case "off road":
case "4x4":
case "terrain":
case "quad":
case "enduro":
case "feldwege":
case "feldweg":
return OFFROAD;
case "boat":
case "water":
case "boating":
case "kayak":
case "river":
case "lake":
case "lakes":
case "canal":
return WATER;
case "ski":
case "skiing":
case "skating":
case "skitour":
case "winter":
case "wintersports":
case "snowboard":
case "лыжи":
case "лыжня":
case "nordic":
case "piste":
return WINTER;
case "snowmobile=designated":
case "snowmobile=permissive":
case "snowmobile=yes":
case "snowmobile":
return SNOWMOBILE;
case "ride":
case "horse":
case "horse trail":
return RIDING;
case "racing":
return RACING;
}
return null;
}
}

View file

@ -156,6 +156,10 @@ public class TurnType {
return value == RNLB || value == TRU;
}
public void setExitOut(int exitOut) {
this.exitOut = exitOut;
}
public void setTurnAngle(float turnAngle) {
this.turnAngle = turnAngle;
}

View file

@ -668,8 +668,13 @@ public class MapUtils {
public static boolean areLatLonEqual(Location l1, Location l2) {
return l1 == null && l2 == null
|| (l1 != null && l2 != null && Math.abs(l1.getLatitude() - l2.getLatitude()) < 0.00001
&& Math.abs(l1.getLongitude() - l2.getLongitude()) < 0.00001);
|| (l2 != null && areLatLonEqual(l1, l2.getLatitude(), l2.getLongitude()));
}
public static boolean areLatLonEqual(Location l, double lat, double lon) {
return l != null
&& Math.abs(l.getLatitude() - lat) < 0.00001
&& Math.abs(l.getLongitude() - lon) < 0.00001;
}
public static LatLon rhumbDestinationPoint(LatLon latLon, double distance, double bearing){

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

View file

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:osmand="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/center_button_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1">
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/center_button"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/selectableItemBackground"
android:gravity="center"
android:textSize="@dimen/default_desc_text_size"
osmand:typeface="@string/font_roboto_medium"
tools:text="@string/altitude" />
</FrameLayout>

View file

@ -1,71 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:osmand="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/custom_radio_buttons"
android:layout_width="match_parent"
android:minHeight="@dimen/dialog_button_height"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/content_padding"
android:layout_marginEnd="@dimen/content_padding"
android:background="?attr/btn_bg_border_inactive"
android:baselineAligned="false"
android:minHeight="@dimen/dialog_button_height"
android:orientation="horizontal"
tools:showIn="@layout/fragment_route_between_points_bottom_sheet_dialog">
<FrameLayout
android:id="@+id/left_button_container"
<include
layout="@layout/left_button_container"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1">
android:layout_weight="1" />
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/left_button"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/selectableItemBackground"
android:gravity="center"
android:textSize="@dimen/default_desc_text_size"
osmand:typeface="@string/font_roboto_medium"
tools:text="@string/shared_string_left"/>
</FrameLayout>
<FrameLayout
android:id="@+id/center_button_container"
<include
layout="@layout/center_button_container"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:visibility="gone">
android:visibility="gone" />
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/center_button"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/selectableItemBackground"
android:gravity="center"
android:textSize="@dimen/default_desc_text_size"
osmand:typeface="@string/font_roboto_medium"
tools:text="@string/position_on_map_center"/>
</FrameLayout>
<FrameLayout
android:id="@+id/right_button_container"
<include
layout="@layout/right_button_container"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1">
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/right_button"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/selectableItemBackground"
android:gravity="center"
android:textSize="@dimen/default_desc_text_size"
osmand:typeface="@string/font_roboto_medium"
tools:text="@string/shared_string_right"/>
</FrameLayout>
android:layout_weight="1" />
</LinearLayout>

View file

@ -9,7 +9,8 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="@dimen/card_row_min_height">
android:layout_height="wrap_content"
android:minHeight="@dimen/card_row_min_height">
<androidx.appcompat.widget.AppCompatImageView
android:id="@android:id/icon"
@ -31,11 +32,15 @@
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:paddingLeft="@dimen/content_padding"
android:paddingStart="@dimen/content_padding"
android:paddingRight="0dp"
android:paddingEnd="0dp"
android:paddingTop="@dimen/content_padding_half"
android:paddingBottom="@dimen/content_padding_half"
android:textColor="?android:textColorPrimary"
android:textSize="@dimen/default_desc_text_size"
osmand:typeface="@string/font_roboto_regular"
tools:text="Internal application memory"
android:paddingStart="@dimen/content_padding" />
tools:text="Internal application memory" />
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/memory"

View file

@ -1,24 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
android:layout_height="wrap_content"
android:orientation="vertical">
<include layout="@layout/list_item_divider" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/bg_color"
android:orientation="vertical">
<net.osmand.plus.views.controls.PagerSlidingTabStrip
android:id="@+id/sliding_tabs"
android:layout_width="match_parent"
android:layout_height="48dp"
android:background="?attr/bg_color"/>
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/content_padding"
android:layout_marginRight="@dimen/content_padding"
android:minHeight="@dimen/dialog_button_height"
android:paddingTop="@dimen/content_padding" />
<net.osmand.plus.views.controls.WrapContentHeightViewPager
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/bg_color"
android:paddingTop="4dp" />
</LinearLayout>
</LinearLayout>

View file

@ -10,43 +10,59 @@
android:orientation="horizontal">
<LinearLayout
android:layout_width="match_parent"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginEnd="@dimen/content_padding"
android:layout_marginRight="@dimen/content_padding"
android:gravity="center_vertical"
android:maxWidth="@dimen/grid_menu_item_width"
android:orientation="vertical">
<LinearLayout
android:layout_width="wrap_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
android:gravity="center_vertical"
android:orientation="horizontal"
android:weightSum="2">
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/value"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="@null"
android:lines="1"
android:textColor="?android:attr/textColorPrimary"
android:textSize="@dimen/default_desc_text_size"
osmand:typeface="@string/font_roboto_medium"
tools:text="700 km" />
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginStart="@dimen/content_padding_half"
android:layout_marginLeft="@dimen/content_padding_half"
android:layout_weight="1">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/image"
android:layout_width="@dimen/context_menu_transport_icon_size"
android:layout_height="@dimen/context_menu_transport_icon_size"
android:layout_gravity="center_vertical"
android:layout_marginStart="@dimen/context_menu_first_line_top_margin"
android:layout_marginLeft="@dimen/context_menu_first_line_top_margin"
android:layout_gravity="center_vertical|end"
tools:src="@drawable/ic_action_track_16" />
</FrameLayout>
</LinearLayout>
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@null"
android:ellipsize="end"
android:lines="1"
android:maxWidth="@dimen/grid_menu_item_width"
android:textColor="?android:attr/textColorSecondary"
android:textSize="@dimen/default_desc_text_size"
tools:text="@string/distance" />

View file

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:osmand="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/left_button_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1">
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/left_button"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/selectableItemBackground"
android:gravity="center"
android:textSize="@dimen/default_desc_text_size"
osmand:typeface="@string/font_roboto_medium"
tools:text="@string/shared_string_overview" />
</FrameLayout>

View file

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:osmand="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/right_button_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1">
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/right_button"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/selectableItemBackground"
android:gravity="center"
android:textSize="@dimen/default_desc_text_size"
osmand:typeface="@string/font_roboto_medium"
tools:text="@string/map_widget_speed" />
</FrameLayout>

View file

@ -3678,4 +3678,5 @@
<string name="poi_wildlife_crossing_bat_tunnel">نفق خفافيش</string>
<string name="poi_wildlife_crossing_bat_bridge">جسر خفافيش</string>
<string name="poi_wildlife_crossing">معبر الحيوانات البرية</string>
<string name="poi_attraction_slide">شريط التمرير</string>
</resources>

View file

@ -3513,7 +3513,7 @@
<string name="shared_string_poi_types">أنواع نقاط الاهتمام</string>
<string name="shared_string_nothing_selected">لا شيء محدد</string>
<string name="shared_string_quick_actions">زر الإجراء السريع</string>
<string name="shared_string_profiles">ملفات التعريف</string>
<string name="shared_string_profiles">الأوضاع</string>
<string name="replace_all_desc">سيتم استبدال العناصر الحالية بالعناصر التي في الملف</string>
<string name="replace_all">استبدل الكل</string>
<string name="get_discount_title">احصل على %1$d %2$s عند %3$s مقابل.</string>
@ -3965,7 +3965,7 @@
<string name="export_not_enough_space_descr">مساحة جهازك %1$s الخالية فقط. يرجى تحرير بعض المساحة أو إلغاء تحديد بعض العناصر للتصدير.</string>
<string name="shared_string_resources">المصادر</string>
<string name="approximate_file_size">حجم الملف التقريبي</string>
<string name="select_data_to_export">حدد البيانات التي سيتم تصديرها إلى الملف.</string>
<string name="select_data_to_export">حدد البيانات التي سيتم تصديرها إلى ملف.</string>
<string name="file_size_needed_for_import">مطلوب للاستيراد</string>
<string name="export_not_enough_space">لا يوجد مساحة كافية</string>
<string name="add_to_mapillary">أضف إلى مابيلاي</string>
@ -3997,10 +3997,10 @@
\n • دعم ألوان مخصصة للمفضلة ونقاط لمسار الطريق
\n
\n</string>
<string name="profile_type_osmand_string">ملف تعريف أوسماند</string>
<string name="profile_type_osmand_string">وضع الاستعراض</string>
<string name="profile_type_user_string">ملف تعريف المستخدم</string>
<string name="reverse_all_points">عكس جميع النقاط</string>
<string name="profile_by_default_description">حدد ملف التعريف، الذي سيتم استخدامه في بدء التطبيق.</string>
<string name="profile_by_default_description">حدد الوضع الذي سيتم استخدامه في بدء التطبيق.</string>
<string name="shared_string_last_used">آخر استخدام</string>
<string name="routing_attr_prefer_hiking_routes_description">تفضيل طرق التنزه</string>
<string name="routing_attr_prefer_hiking_routes_name">تفضيل طرق التنزه</string>
@ -4063,4 +4063,15 @@
<string name="routing_engine_vehicle_type_mtb">MTB</string>
<string name="message_server_error">خطأ في الخادم: %1$s</string>
<string name="message_name_is_already_exists">الاسم موجود بالفعل</string>
<string name="delete_online_routing_engine">هل تريد حذف محرك التوجيه عبر الإنترنت؟</string>
<string name="context_menu_read_full">قراءة كاملة</string>
<string name="context_menu_edit_descr">تحرير الوصف</string>
<string name="delete_waypoints">حذف نقاط الطريق</string>
<string name="copy_to_map_markers">نسخ لعلامات الخريطة</string>
<string name="copy_to_map_favorites">نسخ للمفضلة</string>
<string name="upload_photo">يتم الرفع</string>
<string name="upload_photo_completed">اكتمال الرفع</string>
<string name="uploading_count">رفع %1$d من %2$d</string>
<string name="uploaded_count">تم رفع %1$d من %2$d</string>
<string name="toast_select_edits_for_upload">تحديد التعديلات للتحميل</string>
</resources>

View file

@ -24,4 +24,8 @@
<string name="osmand_purchases_item">ওএসএমও কেনাকাটা</string>
<string name="legend_item_description">একটি মানচিত্রের প্রতীকের জন্য গাইড</string>
<string name="navigation_profiles_item">ন্যাভিগেশন প্রোফাইল</string>
<string name="av_locations">অবস্থানগুলো</string>
<string name="shared_string_navigation">দিক নির্ণয়</string>
<string name="m_s">মি/সে</string>
<string name="nm">নটিকাল মাইল</string>
</resources>

View file

@ -2314,7 +2314,7 @@
<string name="average">Průměr</string>
<string name="of">%1$d z %2$d</string>
<string name="ascent_descent">Stoupání/Klesání</string>
<string name="moving_time">Čas pohybu</string>
<string name="moving_time">Doba pohybu</string>
<string name="max_min">Max/Min</string>
<string name="min_max">Min/Max</string>
<string name="quick_action_resume_pause_navigation">Pozastavit/pokračovat v navigaci</string>
@ -4000,4 +4000,15 @@
<string name="routing_engine_vehicle_type_mtb">Horské kolo</string>
<string name="message_server_error">Chyba serveru: %1$s</string>
<string name="message_name_is_already_exists">Název již existuje</string>
<string name="delete_online_routing_engine">Odstranit tuto online navigační službu\?</string>
<string name="context_menu_read_full">Přečíst celé</string>
<string name="context_menu_edit_descr">Upravit popis</string>
<string name="delete_waypoints">Odstranit body trasy</string>
<string name="copy_to_map_markers">Kopírovat do mapových značek</string>
<string name="copy_to_map_favorites">Kopírovat do oblíbených</string>
<string name="upload_photo">Nahrávání</string>
<string name="upload_photo_completed">Nahrávání dokončeno</string>
<string name="uploading_count">Nahrávám %1$d z %2$d</string>
<string name="uploaded_count">Nahráno %1$d z %2$d</string>
<string name="toast_select_edits_for_upload">Vyberte úpravy pro nahrání</string>
</resources>

View file

@ -3972,7 +3972,7 @@
<string name="select_folder">Ordner auswählen</string>
<string name="select_folder_descr">Ordner auswählen oder neuen hinzufügen</string>
<string name="shared_string_empty">Leer</string>
<string name="analyze_by_intervals">Nach Intervallen auswerten (geteiltes Intervall)</string>
<string name="analyze_by_intervals">Nach Intervallen auswerten</string>
<string name="upload_to_openstreetmap">Hochladen zu OpenStreetMap</string>
<string name="edit_track">Track editieren</string>
<string name="rename_track">Track umbenennen</string>
@ -4008,4 +4008,9 @@
<string name="delete_waypoints">Wegpunkte löschen</string>
<string name="copy_to_map_favorites">In Favoriten kopieren</string>
<string name="copy_to_map_markers">In Kartenmarkierungen kopieren</string>
<string name="upload_photo">Lade hoch</string>
<string name="upload_photo_completed">Hochladen abgeschlossen</string>
<string name="uploading_count">Lade %1$d von %2$d hoch</string>
<string name="uploaded_count">%1$d von %2$d hochgeladen</string>
<string name="toast_select_edits_for_upload">Bearbeitungen zum Hochladen auswählen</string>
</resources>

View file

@ -2433,7 +2433,7 @@
<string name="average">Mezumo</string>
<string name="of">%1$d el %2$d</string>
<string name="ascent_descent">Supreniroj/malsupreniroj</string>
<string name="moving_time">Movada tempo</string>
<string name="moving_time">Tempo dum movo</string>
<string name="max_min">Maks./min.</string>
<string name="min_max">Min./maks.</string>
<string name="rendering_value_translucent_pink_name">Rozkolora diafana</string>
@ -4006,4 +4006,9 @@
<string name="context_menu_edit_descr">Redakti priskribon</string>
<string name="delete_waypoints">Forigi navigadpunktojn</string>
<string name="copy_to_map_markers">Kopii al mapmarkoj</string>
<string name="upload_photo">Sendado</string>
<string name="upload_photo_completed">Sendado finita</string>
<string name="uploading_count">Sendado de %1$d el %2$d</string>
<string name="uploaded_count">Sendis %1$d el %2$d</string>
<string name="toast_select_edits_for_upload">Elektu redaktojn por sendi</string>
</resources>

View file

@ -2438,7 +2438,7 @@
<string name="average">Promedio</string>
<string name="of">%1$d de %2$d</string>
<string name="ascent_descent">Ascenso/Descenso</string>
<string name="moving_time">Tiempo moviéndose</string>
<string name="moving_time">Tiempo en movimiento</string>
<string name="max_min">Máx/Min</string>
<string name="min_max">Min/Máx</string>
<string name="rendering_value_translucent_pink_name">Rosa translúcido</string>
@ -3982,7 +3982,7 @@
<string name="announcement_time_prepare">Preparar</string>
<string name="announcement_time_off_route">Fuera de la ruta</string>
<string name="announcement_time_arrive">Has llegado al destino</string>
<string name="shared_string_turn">Giro</string>
<string name="shared_string_turn">Girar</string>
<string name="announcement_time_intervals">Intervalos de tiempo y distancia</string>
<string name="announcement_time_descr">El tiempo de anuncio de las diferentes indicaciones por voz depende del tipo de mensaje, la velocidad de navegación actual y la velocidad de navegación predefinida.</string>
<string name="announcement_time_title">Tiempo de anuncio</string>
@ -4003,4 +4003,15 @@
<string name="routing_engine_vehicle_type_mtb">Bicicleta de montaña</string>
<string name="message_server_error">Error de servidor: %1$s</string>
<string name="message_name_is_already_exists">El nombre ya existe</string>
<string name="delete_online_routing_engine">¿Borrar este motor de navegación en línea\?</string>
<string name="context_menu_read_full">Leer completo</string>
<string name="context_menu_edit_descr">Editar descripción</string>
<string name="delete_waypoints">Borrar puntos de referencia</string>
<string name="copy_to_map_markers">Copiar a «Marcadores del mapa»</string>
<string name="copy_to_map_favorites">Copiar a favoritos</string>
<string name="upload_photo">Subiendo</string>
<string name="upload_photo_completed">Subida completa</string>
<string name="uploading_count">Subiendo %1$d de %2$d</string>
<string name="uploaded_count">Se subieron %1$d de %2$d</string>
<string name="toast_select_edits_for_upload">Marcar ediciones a subir</string>
</resources>

View file

@ -3948,4 +3948,9 @@
<string name="shared_string_last_used">Viimati kasutatud</string>
<string name="message_server_error">Serveri viga: %1$s</string>
<string name="message_name_is_already_exists">Selline nimi on juba olemas</string>
<string name="toast_select_edits_for_upload">Vali tehtud muudatused üleslaadimiseks</string>
<string name="uploaded_count">Üleslaaditud %1$d/%2$d</string>
<string name="uploading_count">Laadin üles muudatusi %1$d/%2$d</string>
<string name="upload_photo_completed">Sai üleslaaditud</string>
<string name="upload_photo">Laadin üles</string>
</resources>

View file

@ -2739,4 +2739,15 @@ Jos pidät OsmAndista ja OSMsta ja haluat tukea niitä, on tämä täydellinen t
<string name="routing_engine_vehicle_type_foot">Kävely</string>
<string name="routing_engine_vehicle_type_bike">Polkupyörä</string>
<string name="routing_engine_vehicle_type_car">Auto</string>
<string name="message_server_error">Palvelimen virhe: %1$s</string>
<string name="message_name_is_already_exists">Nimi on jo käytössä</string>
<string name="context_menu_read_full">Lue kaikki</string>
<string name="context_menu_edit_descr">Muokkaa kuvausta</string>
<string name="copy_to_map_markers">Kopioi karttamerkkeihin</string>
<string name="copy_to_map_favorites">Kopioi suosikkeihin</string>
<string name="upload_photo">Lähetetään</string>
<string name="upload_photo_completed">Lähetys valmis</string>
<string name="uploading_count">Lähetetty %1$d muutosta %2$d muutoksesta</string>
<string name="uploaded_count">Lähetettiin %1$d muutosta %2$d muutoksesta</string>
<string name="toast_select_edits_for_upload">Valitse lähetettävät muutokset</string>
</resources>

View file

@ -3996,4 +3996,9 @@
<string name="context_menu_read_full">Lire la suite</string>
<string name="context_menu_edit_descr">Modifier la description</string>
<string name="delete_waypoints">Supprimer les points de passage</string>
<string name="uploading_count">Envoi de %1$d sur %2$d</string>
<string name="toast_select_edits_for_upload">Sélectionnez les modifications à envoyer</string>
<string name="uploaded_count">%1$d sur %2$d envoyé</string>
<string name="upload_photo">Envoi en cours</string>
<string name="upload_photo_completed">Envoi terminé</string>
</resources>

View file

@ -708,7 +708,7 @@
<string name="poi_recycling_cars">Autó</string>
<string name="poi_recycling_bicycles">Kerékpár</string>
<string name="poi_landfill_waste_nuclear">Radioaktívhulladék-lerakó</string>
<string name="poi_basin">Vízgyűjtő</string>
<string name="poi_basin">Vízgyűjtő medence</string>
<string name="poi_monitoring_station">Megfigyelőállomás</string>
<string name="poi_crane">Daru</string>
<string name="poi_construction">Építkezés</string>
@ -2633,7 +2633,7 @@
<string name="poi_lottery">Lottózó</string>
<string name="poi_gambling">Szerencsejáték-helyszín</string>
<string name="poi_gambling_type">Típus</string>
<string name="poi_gambling_lottery">Lottó</string>
<string name="poi_gambling_lottery">Lottó</string>
<string name="poi_gambling_slot_machines">Játékgépek</string>
<string name="poi_gambling_betting">Fogadás</string>
<string name="poi_e_cigarette">E-cigaretta-bolt</string>
@ -3446,7 +3446,7 @@
<string name="poi_service_vehicle_motor_yes">Motorszerelés</string>
<string name="poi_service_vehicle_insurance_yes">Biztosítás</string>
<string name="poi_service_vehicle_tyres_yes">Gumiszerelés</string>
<string name="poi_aerialway_zip_line">Kötélpálya</string>
<string name="poi_aerialway_zip_line">Csúszópálya</string>
<string name="poi_climbing_adventure">Kalandpark</string>
<string name="poi_via_ferrata">Via ferrata (vasalt út)</string>
<string name="poi_cable_number">Sodronyok száma</string>
@ -3524,7 +3524,7 @@
<string name="poi_books_academic">akadémiai</string>
<string name="poi_books_children">gyermekkönyv</string>
<string name="poi_atoll">Atoll</string>
<string name="poi_toll_gantry">Útdíjellenőrző kapu</string>
<string name="poi_toll_gantry">Automatikus útdíjbeszedő kapu</string>
<string name="poi_childcare">Gyermekgondozás (bölcsőde)</string>
<string name="poi_denotation_natural_monument">Természeti emlék</string>
<string name="poi_denotation_landmark">Tájékozódási pont</string>

View file

@ -4000,4 +4000,9 @@
<string name="delete_waypoints">Útpontok törlése</string>
<string name="copy_to_map_markers">Másolás a térképjelölők közé</string>
<string name="copy_to_map_favorites">Másolás a kedvencek közé</string>
<string name="upload_photo">Felöltés folyamatban</string>
<string name="upload_photo_completed">Feltöltés befejezve</string>
<string name="uploading_count">%1$d / %2$d feltöltés alatt</string>
<string name="uploaded_count">%1$d / %2$d feltöltve</string>
<string name="toast_select_edits_for_upload">Szerkesztések kijelölése feltöltéshez</string>
</resources>

View file

@ -1528,7 +1528,7 @@
<string name="distance">מרחק</string>
<string name="average">ממוצע</string>
<string name="of">%1$d מתוך %2$d</string>
<string name="moving_time">זמן תנועה</string>
<string name="moving_time">זמן בתנועה</string>
<string name="max_min">מרבי/מזערי</string>
<string name="min_max">מזערי/מרבי</string>
<string name="index_tours">סיורים</string>
@ -4001,4 +4001,16 @@
<string name="delete_waypoints">מחיקת נקודות דרך</string>
<string name="copy_to_map_markers">העתקה לסמני המפה</string>
<string name="copy_to_map_favorites">העתקה למועדפים</string>
<string name="shared_string_sec">שנ׳</string>
<string name="announcement_time_passing">מעבר</string>
<string name="announcement_time_approach">הגעה</string>
<string name="announcement_time_prepare_long">הכנה ממושכת</string>
<string name="announcement_time_prepare">הכנה</string>
<string name="shared_string_turn">פנייה</string>
<string name="announcement_time_intervals">הפרשי זמן ומרחק</string>
<string name="upload_photo">מתבצעת שליחה</string>
<string name="upload_photo_completed">השליחה הושלמה</string>
<string name="uploading_count">נשלחות %1$d מתוך %2$d</string>
<string name="uploaded_count">נשלחו %1$d מתוך %2$d</string>
<string name="toast_select_edits_for_upload">נא לבחור עריכות לשליחה</string>
</resources>

View file

@ -18,9 +18,8 @@
<string name="osmand_parking_pm">po piet</string>
<string name="osmand_parking_am">ryto</string>
<string name="osmand_parking_position_name">Statymo vieta</string>
<string name="osmand_parking_plugin_description">Šis įskiepis leidžia įsiminti vietą, kurioje palikote savo automobilį ir kiek laiko liko iki parkavimo pabaigos (jei ribojamas laikas).
Tiek vieta, tiek laikas yra matomi OsmAnd valdymo skydelyje bei skydelyje žemėlapyje rodinyje. Šis įskiepis taip pat gali įrašyti priminimą į kalendorių.</string>
<string name="osmand_parking_plugin_description">Šis įskiepis leidžia įsiminti vietą, kurioje palikote savo automobilį ir kiek laiko liko iki parkavimo pabaigos .
\nTiek vieta, tiek laikas yra matomi OsmAnd valdymo skydelyje bei skydelyje žemėlapyje rodinyje. Šis įskiepis taip pat gali įrašyti priminimą į Android kalendorių.</string>
<string name="osmand_parking_plugin_name">Statymo vieta</string>
<string name="context_menu_item_add_parking_point">Žymėti statymo vietą</string>
<string name="context_menu_item_delete_parking_point">Naikinti statymo žymę</string>
@ -200,9 +199,8 @@ Tiek vieta, tiek laikas yra matomi OsmAnd valdymo skydelyje bei skydelyje žemė
<string name="osmand_service">Foninis režimas</string>
<string name="osmand_service_descr">Reikalinga, jei norite naudoti OsmAnd kai ekranas yra išjungtas.</string>
<string name="download_files_not_enough_space">Neužtenka vietos parsiųsti %1$s MB (laisva: %2$s).</string>
<string name="download_files_question_space">Atsiųsti {0} failą(-us)?
Tam prireiks {1} MB pastoviam saugojimui.
(Dabar laisvos vietos yra {2} MB.)</string>
<string name="download_files_question_space">Atsiųsti {0} failą(-us)\?
\nTam prireiks {1} MB pastoviam saugojimui. (Dabar laisvos vietos yra {2} MB.)</string>
<string name="use_transparent_map_theme">Permatoma tema</string>
<string name="native_library_not_supported">Aparatinė biblioteka šiame įrenginyje nepalaikoma.</string>
<string name="init_native_library">Inicializuojama aparatinė biblioteka…</string>
@ -779,7 +777,27 @@ Tam prireiks {1} MB pastoviam saugojimui.
<string name="snap_to_road_descr">Poziciją rodyti ant kelių kai naviguojama.</string>
<string name="snap_to_road">Rodyti ant kelio</string>
<string name="osmand_long_description_1000_chars">OsmAnd (OSM Automated Navigation Directions)
\nOsmAnd yra atviro kodo programa naudojanti įvairius OpenStreetMap (OSM) duomenis. Visi žemėlapių duomenys (vektoriniai ar lakštiniai) gali būti išsaugoti telefone ir naudojami be interneto prieigos. OsmAnd taip pat gali pasiūlyti maršruto skaičiavimo paslaugas internete ar įrenginyje, bei balso nurodymus kelionei apskaičiuotu maršrutu. Dalis pagrindinių savybių: - Veikia be interneto (išsaugokite parsiųstus žemėlapius ar jų lakštus įrenginyje) - Kompaktiški vektoriniai viso pasaulio žemėlapiai - Parsisųskite šalies ar regiono žemėlapius tiesiai iš pačios propgramos - Galima sulieti kelis žemėlapop sluoksnius, tokius kaip GPX ar judėjimo istoriją, Lankytinas Vietas, mėgiamas vietas, kontūrų linijas, viešojo transporto stoteles, papildomus žemėlapius su pasirinktinai nustatomu permatomumo lygiu - Adresų ir LV paieška nenaudojant interneto - Vidutinio ilgio maršruto apskaičiavimas be interneto paslaugų - Automobilio, dviračio ir pėsčiojo režimai su: - pasirinktiniu dineos/nakties rodinio perjungimu - pasirinktiniu pagal judėjimo greitį automatiškai nustatomu mąsteliu - pasirinktine žemėlapio orientacija pagal kompaso arba judėjimo kryptį - pasirinktinis eismo juostų nurodymas, greičio ribojimų rodymas, įrašyti ar generuojami balsai Šios nemokamos OsmAnd versijos apribojimai: - Ribojamas žemėlapių parsiuntimų skaičius - Nėra prieigos prie iš Wikipedia parsiunčiamų LV OsmAnd yra aktyviai tobulinama ir mūsų projektas bei jo tolesnis progresas priklauso nuo finansinės paramos, kuri įgalina tolesnį vystymą ir naujų funkcijų kūrimą. Norime paskatinti jus nusipirkti OsmAnd+ programą arba finansiškai prisidėti prie specifinių funkcijų kūrimo arba šiaip paremti programą osmand.net svetainėje.</string>
\n
\nOsmAnd yra atviro kodo programa naudojanti įvairius OpenStreetMap (OSM) duomenis. Visi žemėlapių duomenys (vektoriniai ar lakštiniai) gali būti išsaugoti telefone ir naudojami be interneto prieigos. OsmAnd taip pat gali pasiūlyti maršruto skaičiavimo paslaugas internete ar įrenginyje, bei balso nurodymus kelionei apskaičiuotu maršrutu.
\n
\nDalis pagrindinių savybių:
\n- Veikia be interneto (išsaugokite parsiųstus žemėlapius ar jų lakštus įrenginyje)
\n- Kompaktiški vektoriniai viso pasaulio žemėlapiai
\n- Parsisųskite šalies ar regiono žemėlapius tiesiai iš pačios propgramos
\n- Galima sulieti kelis žemėlapop sluoksnius, tokius kaip GPX ar judėjimo istoriją, Lankytinas Vietas, mėgiamas vietas, kontūrų linijas, viešojo transporto stoteles, papildomus žemėlapius su pasirinktinai nustatomu permatomumo lygiu
\n - Adresų ir LV paieška nenaudojant interneto
\n- Vidutinio ilgio maršruto apskaičiavimas be interneto prieigos
\n- Automobilio, dviračio ir pėsčiojo režimai su:
\n- pasirinktiniu dineos/nakties rodinio perjungimu
\n- pasirinktiniu pagal judėjimo greitį automatiškai nustatomu mąsteliu
\n- pasirinktine žemėlapio orientacija pagal kompaso arba judėjimo kryptį
\n- pasirinktinis eismo juostų nurodymas, greičio ribojimų rodymas, įrašyti ar generuojami balsai
\n
\nNemokamos OsmAnd versijos apribojimai:
\n- Ribojamas žemėlapių parsiuntimų skaičius
\n- Nėra prieigos prie iš Wikipedia parsiunčiamų LV
\n
\n OsmAnd yra aktyviai tobulinama ir mūsų projektas bei jo tolesnis progresas priklauso nuo finansinės paramos, kuri įgalina tolesnį vystymą ir naujų funkcijų kūrimą. Norime paskatinti jus nusipirkti OsmAnd+ programą arba finansiškai prisidėti prie specifinių funkcijų kūrimo arba šiaip paremti programą https://osmand.net svetainėje.</string>
<string name="osmand_plus_short_description_80_chars">OsmAnd - atviro kodo navigacijos programa su žemėlapiais</string>
<string name="osmand_plus_long_description_1000_chars">OsmAnd+ (OSM Automated Navigation Directions)
\n
@ -1872,9 +1890,9 @@ Failams reikalinga {3} MB laikinam ir {1} MB pastoviam saugojimui.
<string name="osm_live_header">Prenumerata leidžia kas valandą gauti visų pasaulio žemėlapių atnaujinimus.
Dalis pajamų grįžta OSM bendruomenei ir apmokamas kiekvienas indėlis į OSM kūrimą.
Tai yra puikus būdas paremti OsmAnd ir OSM, jei jie jums patinka.</string>
<string name="download_files_question_space_with_temp">Ar siųsti {0} failų?
Failams reikalinga {3} MB laikinam ir {1} MB pastoviam saugojimui.
(Šiuo metu prieinama tik {2} MB vietos.)</string>
<string name="download_files_question_space_with_temp">Ar siųsti {0} failų\?
\nFailams reikalinga {3} MB laikinam ir {1} MB pastoviam saugojimui.
\n(Šiuo metu prieinama tik {2} MB vietos.)</string>
<string name="lang_es_us">Ispanų (Amerikos)</string>
<string name="lang_en_gb">Anglų (Junginė Karalystė)</string>
<string name="lang_be_by">Belarusų (Lotynų)</string>
@ -2419,7 +2437,9 @@ Tai yra puikus būdas paremti OsmAnd ir OSM, jei jie jums patinka.</string>
<string name="passed">Paskutinį kartą naudota: %1$s</string>
<string name="osm_recipient_stat">Taisymų %1$s, suma %2$s mBTC</string>
<string name="lang_lo">Laosiečių</string>
<string name="osmand_extended_description_part1">OsmAnd (OSM Automated Navigation Directions) yra žemėlapio ir navigacijos programa su prieiga prie nemokamų, pasaulinių ir aukštos kokybės OpenStreetMap (OSM) duomenų. Naudokitės balso ir vaizdo navigatoriumi, peržiūrėkite LV (lankytinas vietas), kurkite ir valdytkite GPX kelius, naudojkite kontūro linijos vizualizaciją ir aukščio info (įskiepių pagalba), pasirinkite vairavimo, dviračių, pėsčiųjų režimus, redaguokite OSM duomenis ir daug daugiau.</string>
<string name="osmand_extended_description_part1">OsmAnd (OSM Automated Navigation Directions) yra žemėlapio ir navigacijos programa su prieiga prie nemokamų, pasaulinių ir aukštos kokybės OpenStreetMap (OSM) duomenų.
\n
\nNaudokitės balso ir vaizdo navigatoriumi, peržiūrėkite LV (lankytinas vietas), kurkite ir valdytkite GPX kelius, naudojkite kontūro linijos vizualizaciją ir aukščio info (įskiepių pagalba), pasirinkite vairavimo, dviračių, pėsčiųjų režimus, redaguokite OSM duomenis ir daug daugiau.</string>
<string name="quick_favorites_name_preset">Nuostatos pavadinimas</string>
<string name="quick_action_add_marker_descr">Bakstelėję veiksmo mygtuką pridėsite žemėlapio žymeklį ekrano centre.</string>
<string name="quick_action_take_audio_note_descr">Bakstelėję veiksmo mygtuką pridėsite garso įrašą ekrano centre.</string>

View file

@ -1526,7 +1526,7 @@
<string name="voice_data_not_supported">Taledataversjon som ikke støttes</string>
<string name="background_router_service_descr">Sporer posisjonen din mens skjermen er slått av.</string>
<string name="share_fav_subject">Favoritter delt via OsmAnd</string>
<string name="import_file_favourites">Lagre data som GPX-fil eller importere rutepunkter til Favoritter\?</string>
<string name="import_file_favourites">Lagre data som GPX-fil eller importere rutepunkter til favoritter\?</string>
<string name="coords_format_descr">Format for geografiske koordinater.</string>
<string name="coords_format">Koordinatformat</string>
<string name="map_widget_search">Søk</string>
@ -3919,4 +3919,18 @@
<string name="routing_engine_vehicle_type_cycling_regular">Vanlig sykling</string>
<string name="message_server_error">Tjenerfeil: %1$s</string>
<string name="message_name_is_already_exists">Navnet finnes allerede</string>
<string name="analyze_by_intervals">Analyser ved intervaller (delt intervall)</string>
<string name="announcement_time_off_route">Ruteavvik</string>
<string name="routing_engine_vehicle_type_hgv">Stor lastebil</string>
<string name="delete_online_routing_engine">Slett denne nettbaserte rutingsmotoren\?</string>
<string name="context_menu_read_full">Les hele</string>
<string name="delete_waypoints">Slett rutepunkt</string>
<string name="app_mode_gap">Luke</string>
<string name="login_open_street_map">Logg inn på OpenStreetMap</string>
<string name="user_login">Logg inn</string>
<string name="announcement_time_passing">Tidsforbruk</string>
<string name="announcement_time_approach">Ankomst</string>
<string name="context_menu_edit_descr">Rediger beskrivelse</string>
<string name="copy_to_map_markers">Kopier til kartmarkører</string>
<string name="copy_to_map_favorites">Kopier til favoritter</string>
</resources>

View file

@ -931,7 +931,7 @@
<string name="files_limit">%1$d resterende bestanden</string>
<string name="available_downloads_left">%1$d resterende bestanden nog te downloaden</string>
<string name="install_paid">Volledige versie</string>
<string name="cancel_route">Annuleer route</string>
<string name="cancel_route">Annuleer route \?</string>
<string name="cancel_navigation">Stop navigatie</string>
<string name="clear_destination">Bestemming wissen</string>
<string name="use_magnetic_sensor_descr">Gebruik magnetische sensor in plaats van oriëntatiesensor voor het kompas.</string>
@ -2178,8 +2178,8 @@
<string name="shared_string_time_span">Tijdsduur</string>
<string name="shared_string_time_moving">Tijd in beweging</string>
<string name="routing_attr_driving_style_name">Rijstijl</string>
<string name="routing_attr_height_obstacles_name">Gebruik hoogtegegevens</string>
<string name="routing_attr_height_obstacles_description">Factor in hoogtegegevens (van SRTM, ASTER en EU-DEM data).</string>
<string name="routing_attr_height_obstacles_name">Hoogtegegevens gebruiken</string>
<string name="routing_attr_height_obstacles_description">Gebruik hoogtegegevens (van SRTM, ASTER en EU-DEM data) bij bepalen route.</string>
<string name="shared_string_gpx_track">Track</string>
<string name="right_side_navigation">Rechts rijdend</string>
<string name="driving_region_automatic">Automatisch</string>
@ -3320,9 +3320,9 @@
<string name="route_recalculation">Route herberekening</string>
<string name="accessibility_announce">Meld</string>
<string name="login_and_pass">Gebruikersnaam en wachtwoord</string>
<string name="plugin_global_prefs_info">Deze instellingen hebben betrekking op alle profielen</string>
<string name="plugin_global_prefs_info">Deze plugin-instellingen hebben betrekking op alle profielen</string>
<string name="osm_editing">OSM Bewerking</string>
<string name="osm_edits_view_descr">U kan al uw niet geüploade bewerkingen of OSM fouten zien in %1$s. Geüploade punten ziet u niet meer.</string>
<string name="osm_edits_view_descr">U kunt alle niet-geüploade bewerkingen of OSM-opmerkingen zien in %1$s. Geüploade wijzigingen ziet u niet meer.</string>
<string name="app_mode_osm">OSM</string>
<string name="select_nav_icon_descr">Tijdens navigatie of beweging getoond icoon.</string>
<string name="select_map_icon_descr">Bij rust getoond icoon.</string>
@ -3667,8 +3667,8 @@
<string name="next_segment">Volgende segment</string>
<string name="all_next_segments">Alle volgende segmenten</string>
<string name="all_next_segments_will_be_recalc">Alle volgende segmenten worden opnieuw berekend met het geselecteerde profiel.</string>
<string name="whole_track">De ganse track</string>
<string name="route_between_points_whole_track_button_desc">De ganse track wordt herberekend volgens het geselecteerde profiel.</string>
<string name="whole_track">De gehele route</string>
<string name="route_between_points_whole_track_button_desc">De gehele route wordt herberekend volgens het geselecteerde profiel.</string>
<string name="pass_whole_track_descr">Punt van de track om te navigeren</string>
<string name="shared_string_save_as_gpx">Bewaar als nieuw trackbestand</string>
<string name="save_as_new_track">Bewaar als nieuwe track</string>
@ -3726,14 +3726,14 @@
<string name="plan_a_route">Plan een route</string>
<string name="use_two_phase_routing">Gebruik de twee-fase A* route berekening methode</string>
<string name="shared_string_graph">Grafiek</string>
<string name="message_graph_will_be_available_after_recalculation">Wacht op de herberekening van de route.
\nDe grafiek is beschikbaar na herberekening.</string>
<string name="message_graph_will_be_available_after_recalculation">Wacht totdat route herberekend is.
\nNa herberekening is de grafiek zichtbaar.</string>
<string name="ltr_or_rtl_combine_via_dash">%1$s — %2$s</string>
<string name="import_track_descr">Kies een trackbestand om te volgen of importeer het, vanaf uw apparaat.</string>
<string name="app_mode_gap">Kloof</string>
<string name="shared_string_custom">Op maat</string>
<string name="app_mode_gap">Onderbreking</string>
<string name="shared_string_custom">Aangepast</string>
<string name="perform_oauth_authorization_description">Voer een OAuth-login uit om osm edit functies te gebruiken</string>
<string name="release_3_5">"• Bijgewerkte app- en profielinstellingen: instellingen zijn nu gerangschikt op type. Elk profiel kan afzonderlijk worden aangepast.
<string name="release_3_5">• Bijgewerkte app- en profielinstellingen: instellingen zijn nu gerangschikt op type. Elk profiel kan afzonderlijk worden aangepast.
\n
\n • Nieuw dialoogvenster voor het downloaden van kaarten waarin wordt voorgesteld een kaart te downloaden tijdens het browsen
\n
@ -3749,8 +3749,8 @@
\n
\n • Andere bugs opgelost
\n
\n"</string>
<string name="release_3_6">"• Profielen: nu kunt u de volgorde wijzigen, het pictogram voor de kaart instellen, alle instellingen voor basisprofielen wijzigen en ze terugzetten naar de standaardinstellingen
\n</string>
<string name="release_3_6">• Profielen: nu kunt u de volgorde wijzigen, het pictogram voor de kaart instellen, alle instellingen voor basisprofielen wijzigen en ze terugzetten naar de standaardinstellingen
\n
\n • Exitnummer toegevoegd in de navigatie
\n
@ -3774,7 +3774,7 @@
\n
\n • Antarctica-kaart toegevoegd
\n
\n"</string>
\n</string>
<string name="what_is_new">Wat is er nieuw</string>
<string name="snowmobile_render_descr">Voor sneeuwscooter, rijden met speciale wegen en tracks.</string>
<string name="set_working_days_to_continue">Stel aantal werkdagen in om door te gaan</string>
@ -3837,47 +3837,47 @@
<string name="osm_edit_logout_success">Uitloggen gelukt</string>
<string name="file_already_imported">Bestand is reeds geïmporteerd in OsmAnd</string>
<string name="shared_string_local_maps">Lokale kaarten</string>
<string name="icon_group_amenity">Aangenaam</string>
<string name="icon_group_amenity">Voorziening</string>
<string name="icon_group_special">Speciaal</string>
<string name="icon_group_transport">Transport</string>
<string name="icon_group_service">Onderhoud</string>
<string name="icon_group_symbols">Symbolen</string>
<string name="icon_group_sport">Sport</string>
<string name="icon_group_emergency">Noodtoestand</string>
<string name="icon_group_emergency">Noodgevallen</string>
<string name="icon_group_travel">Reizen</string>
<string name="empty_state_my_tracks_desc">Trackbestanden importeren of opnemen</string>
<string name="quick_action_add_gpx">Track waypoint toevoegen</string>
<string name="marker_save_as_track">Opslaan als trackbestand</string>
<string name="monitoring_control_start">Rec</string>
<string name="message_you_need_add_two_points_to_show_graphs">U moet minimaal twee punten toevoegen</string>
<string name="login_open_street_map">Login op OpenStreetMap</string>
<string name="login_open_street_map_org">Login op OpenStreetMap.org</string>
<string name="sign_in_with_open_street_map">Login met OpenStreetMap</string>
<string name="open_street_map_login_mode">U moet inloggen om nieuwe of gewijzigde wijzigingen te uploaden.
<string name="login_open_street_map">Inloggen bij OpenStreetMap</string>
<string name="login_open_street_map_org">Inloggen bij OpenStreetMap.org</string>
<string name="sign_in_with_open_street_map">Aanmelden via OpenStreetMap (OAuth)</string>
<string name="open_street_map_login_mode">U moet inloggen om wijzigingen te uploaden.
\n
\nU kunt inloggen met de veilige OAuth-methode of uw login en wachtwoord gebruiken.</string>
<string name="use_login_password">Gebruik uw login gegevens</string>
\nU kunt inloggen met de veilige OAuth-methode of uw loginnaam en wachtwoord gebruiken.</string>
<string name="use_login_password">Inloggen met gebruikersnaam en wachtwoord</string>
<string name="login_account">Account</string>
<string name="user_login">Inloggen</string>
<string name="user_login">Gebruikersnaam</string>
<string name="manage_subscription">Abonnement beheren</string>
<string name="subscription_payment_issue_title">Er is een probleem met uw abonnement. Klik op de knop om naar de Google Play-abonnementsinstellingen te gaan om uw betalingsmethode te corrigeren.</string>
<string name="subscription_expired_title">OsmAnd Live-abonnement is verlopen</string>
<string name="subscription_paused_title">OsmAnd Live-abonnement is gepauzeerd</string>
<string name="subscription_on_hold_title">Het OsmAnd Live-abonnement is op wacht gezet</string>
<string name="markers_history">Markeervlaggen geschiedenis</string>
<string name="subscription_on_hold_title">Het OsmAnd Live-abonnement is opgeschort</string>
<string name="markers_history">Markeervlaggetjes-geschiedenis</string>
<string name="send_files_to_openstreetmap">Stuur het GPX-bestand naar OpenStreetMap</string>
<string name="enter_text_separated">Voer tags in, gescheiden door komma\'s.</string>
<string name="gpx_upload_public_visibility_descr">Openbaar betekent dat de trace openbaar zal worden getoond in Uw GPS-sporen en in openbare GPS-traceerlijsten. Gegevens die via de API worden geleverd, verwijzen niet naar uw traceerpagina. Tijdaanduidingen van de traceerpunten zijn niet beschikbaar via de openbare GPS-API en de punten zijn niet chronologisch gerangschikt. Andere gebruikers kunnen de onbewerkte tracering echter nog steeds downloaden van de openbare traceringslijst en eventuele tijdaanduiding erin.</string>
<string name="gpx_upload_private_visibility_descr">Privé betekent dat de trace niet in openbare vermeldingen zal verschijnen, maar trackpoints ervan zullen nog steeds beschikbaar zijn via de openbare GPS API zonder tijdaanduiding, maar zullen niet chronologisch worden gerangschikt.</string>
<string name="gpx_upload_identifiable_visibility_descr">Identificeerbaar betekent dat de trace openbaar wordt getoond in uw GPS-sporen en in openbare GPS-trace-lijsten, dat wil zeggen dat andere gebruikers de onbewerkte trace kunnen downloaden en deze aan uw gebruikersnaam kunnen koppelen. Gegevens die via de trackpoints-API worden aangeboden, verwijzen naar uw oorspronkelijke tracepagina. Tijdaanduidingen van de traceerpunten zijn beschikbaar via de openbare GPS-API.</string>
<string name="gpx_upload_trackable_visibility_descr">Trackbaar betekent dat de trace niet in openbare vermeldingen zal verschijnen, maar trackpoints ervan zullen nog steeds beschikbaar zijn via de openbare GPS API met tijdaanduiding. Andere gebruikers kunnen alleen verwerkte trackpoints downloaden van uw trace die niet rechtstreeks aan u kunnen worden gekoppeld.</string>
<string name="gpx_upload_public_visibility_descr">\"Publiek\" betekent dat de track openbaar wordt getoond in \"Jouw GPS-tracks\" en in openbare GPS-track-lijsten. Trackpoints die d.m.v. de API worden gedownload zullen niet aan je oorspronkelijke trackpagina refereren. Tijden in de tracks zijn niet beschikbaar in de publieke GPS API, maar de punten zullen wel chronologisch geordend zijn. Echter, andere gebruikers kunnen de track van de openbare GPS-track-lijsten downloaden met alle tijdinformatie.</string>
<string name="gpx_upload_private_visibility_descr">\"Persoonlijk\" betekent dat de track niet wordt getoond in openbare GPS-track-lijsten, maar de trackpunten zijn wel beschikbaar in volgorde van tijd door de publieke GPS API, maar zonder tijdinformatie.</string>
<string name="gpx_upload_identifiable_visibility_descr">\"Identificeerbaar\" betekent dat de trace openbaar wordt getoond in uw GPS-sporen en in openbare GPS-trace-lijsten. Dat wil zeggen dat andere gebruikers de onbewerkte trace kunnen downloaden en deze aan uw gebruikersnaam kunnen koppelen. Gegevens die via de trackpoints-API worden aangeboden, verwijzen naar uw oorspronkelijke tracepagina. Tijdaanduidingen van de traceerpunten zijn beschikbaar via de openbare GPS-API.</string>
<string name="gpx_upload_trackable_visibility_descr">\"Traceerbaar\" betekent dat de track niet wordt getoond in openbare GPS-track-lijsten maar de trackpunten zijn wel beschikbaar door de publieke GPS API met tijdinformatie. Andere gebruikers kunnen alleen bewerkte trackpunten downloaden die niet aan jou herleid kunnen worden.</string>
<string name="osm_edit_close_note">Sluit OSM Note</string>
<string name="osm_edit_comment_note">Opmerking maken bij OSM-nota</string>
<string name="osm_login_descr">U kunt inloggen met de veilige OAuth-methode of uw login en wachtwoord gebruiken.</string>
<string name="osm_login_descr">U kunt inloggen met de veilige OAuth-methode, of uw loginnaam en wachtwoord gebruiken.</string>
<string name="shared_string_add_photo">Een foto toevoegen</string>
<string name="register_on_openplacereviews">Registreer u op
\nOpenPlaceReviews.org</string>
<string name="register_on_openplacereviews_desc">Foto\'s zijn afkomstig van het open data-project OpenPlaceReviews.org. Om uw foto\'s te uploaden, moet u zich aanmelden op deze website.</string>
<string name="register_on_openplacereviews_desc">Foto\'s zijn afkomstig van het open data-project OpenPlaceReviews.org. Om uw foto\'s te uploaden, moet u zich aanmelden op hun website.</string>
<string name="register_opr_create_new_account">Maak een nieuw account aan</string>
<string name="register_opr_have_account">Ik heb al een account</string>
<string name="ltr_or_rtl_combine_via_star">%1$s * %2$s</string>
@ -3954,4 +3954,48 @@
<string name="routing_attr_allow_intermittent_name">Laat regelmatig droogvallende waterwegen toe</string>
<string name="shared_string_enter_param">Geef een parameter</string>
<string name="keep_it_empty_if_not">Laat leeg indien niet</string>
<string name="analyze_by_intervals">Analyseren met intervallen</string>
<string name="upload_to_openstreetmap">Uploaden naar OpenStreetMap</string>
<string name="edit_track">GPX-track bewerken</string>
<string name="rename_track">GPX-track hernoemen</string>
<string name="change_folder">Map wijzigen</string>
<string name="shared_string_sec">sec</string>
<string name="announcement_time_approach">Bij nadering</string>
<string name="announcement_time_passing">Bij passeren</string>
<string name="announcement_time_prepare_long">Ruime vooraankondiging</string>
<string name="announcement_time_prepare">Vooraankondiging</string>
<string name="announcement_time_off_route">Afwijking van de route</string>
<string name="announcement_time_arrive">Aankomst op bestemming</string>
<string name="shared_string_turn">Bocht</string>
<string name="announcement_time_intervals">Tijd- en afstandsintervallen</string>
<string name="announcement_time_descr">De aankondigingstijd van verschillende aankondigen hangt af van type en huidige snelheid.</string>
<string name="announcement_time_title">Aankondigingstijd</string>
<string name="start_recording">Start opname</string>
<string name="show_track_on_map">Toon GPX-track op de kaart</string>
<string name="routing_engine_vehicle_type_wheelchair">Rolstoel</string>
<string name="routing_engine_vehicle_type_hiking">Hiken</string>
<string name="routing_engine_vehicle_type_walking">Wandelen</string>
<string name="routing_engine_vehicle_type_cycling_electric">Elektische Fiets</string>
<string name="routing_engine_vehicle_type_cycling_mountain">Mountainbiken</string>
<string name="routing_engine_vehicle_type_cycling_road">Fietsen</string>
<string name="routing_engine_vehicle_type_cycling_regular">Normaal Fietsen</string>
<string name="routing_engine_vehicle_type_hgv">Vrachtwagen</string>
<string name="routing_engine_vehicle_type_small_truck">Kleine Vrachtwagen</string>
<string name="routing_engine_vehicle_type_truck">Vrachtwagen</string>
<string name="routing_engine_vehicle_type_scooter">Scooter</string>
<string name="routing_engine_vehicle_type_racingbike">Racefiets</string>
<string name="routing_engine_vehicle_type_mtb">Mountainbike</string>
<string name="message_server_error">Server fout: %1$s</string>
<string name="message_name_is_already_exists">Deze naam bestaat al</string>
<string name="delete_online_routing_engine">Deze Online-routeservice verwijderen\?</string>
<string name="context_menu_read_full">Helemaal inlezen</string>
<string name="context_menu_edit_descr">Beschrijving bewerken</string>
<string name="delete_waypoints">Waypoints verwijderen</string>
<string name="copy_to_map_markers">Kopiëren naar Markeervlaggetjes</string>
<string name="copy_to_map_favorites">Kopiëren naar Favorieten</string>
<string name="upload_photo">Opladen</string>
<string name="upload_photo_completed">Opladen voltooid</string>
<string name="uploading_count">Aan het opladen %1$d van %2$d</string>
<string name="uploaded_count">Opgeladen %1$d van %2$d</string>
<string name="toast_select_edits_for_upload">Selecteer de op te laden wijzigingen</string>
</resources>

View file

@ -2345,7 +2345,7 @@
<string name="average">Średnia</string>
<string name="of">%1$d z %2$d</string>
<string name="ascent_descent">Podjazd/zjazd</string>
<string name="moving_time">Czas w ruchu</string>
<string name="moving_time">Czas poruszania</string>
<string name="max_min">Maks./min.</string>
<string name="quick_action_resume_pause_navigation">Zatrzymaj/wznów nawigację</string>
<string name="quick_action_resume_pause_navigation_descr">Przycisk do wstrzymania lub wznowienia nawigacji.</string>
@ -3998,4 +3998,14 @@
<string name="message_name_is_already_exists">Taka nazwa już istnieje</string>
<string name="online_routing_engine">Silnik wyznaczania tras online</string>
<string name="online_routing_engines">Silniki wyznaczania tras online</string>
<string name="context_menu_read_full">Przeczytaj całość</string>
<string name="context_menu_edit_descr">Edytuj opis</string>
<string name="delete_waypoints">Usuń punkty trasy</string>
<string name="copy_to_map_markers">Skopiuj do znaczników mapy</string>
<string name="copy_to_map_favorites">Skopiuj do ulubionych</string>
<string name="upload_photo">Wysyłanie</string>
<string name="upload_photo_completed">Przesyłanie zakończone</string>
<string name="uploading_count">Przesyłanie %1$d z %2$d</string>
<string name="uploaded_count">Przesłano %1$d z %2$d</string>
<string name="toast_select_edits_for_upload">Wybierz zmiany do przesłania</string>
</resources>

View file

@ -4001,4 +4001,9 @@
<string name="copy_to_map_favorites">Copiar para favoritos</string>
<string name="delete_online_routing_engine">Excluir este mecanismo de roteamento online\?</string>
<string name="context_menu_read_full">Ler na íntegra</string>
<string name="upload_photo">Carregando</string>
<string name="upload_photo_completed">Carreamento concluído</string>
<string name="uploading_count">Carregando %1$d de %2$d</string>
<string name="uploaded_count">Carregado %1$d de %2$d</string>
<string name="toast_select_edits_for_upload">Selecione as edições para carregamento</string>
</resources>

View file

@ -1185,7 +1185,7 @@
<string name="no_route">Нет маршрута</string>
<string name="gps_not_available">Включите GPS в настройках</string>
<string name="map_widget_show_destination_arrow">Показывать направление к пункту назначения</string>
<string name="enable_plugin_monitoring_services">Включите плагин «Запись поездки» для использования сервисов мониторинга (запись GPX, сопровождение в реальном времени)</string>
<string name="enable_plugin_monitoring_services">Включите плагин «Запись поездки» для использования служб мониторинга (запись GPX, сопровождение в реальном времени)</string>
<string name="rendering_attr_roadColors_description">Выберите цветовую схему дорог:</string>
<string name="rendering_attr_roadColors_name">Цветовая схема дорог</string>
<string name="route_descr_lat_lon">Ш %1$.3f Д %2$.3f</string>
@ -1731,7 +1731,7 @@
<string name="shared_string_selected_lowercase">выбранные</string>
<string name="shared_string_none">Нет</string>
<string name="shared_string_deselect">Отменить выбор</string>
<string name="shared_string_deselect_all">Отменить выбор всех</string>
<string name="shared_string_deselect_all">Отменить выбор</string>
<string name="shared_string_share">Поделиться</string>
<string name="shared_string_my_places">Мои места</string>
<string name="shared_string_my_favorites">Избранные</string>
@ -3225,7 +3225,7 @@
\n</string>
<string name="contour_lines_and_hillshade">Контурные линии и затенение рельефа</string>
<string name="routing_attr_prefer_unpaved_name">Предпочитать грунтовые дороги</string>
<string name="routing_attr_prefer_unpaved_description">Предпочитать грунтовые дороги.</string>
<string name="routing_attr_prefer_unpaved_description">Предпочитать грунтовые дороги</string>
<string name="update_all_maps_q">Вы уверены, что хотите обновить все карты (%1$d)\?</string>
<string name="apply_preference_to_all_profiles">Вы можете применить это ко всем или только к выбранному профилю.</string>
<string name="shared_preference">Общий</string>
@ -3713,7 +3713,7 @@
<string name="quick_action_remove_next_destination">Удалить ближайший пункт</string>
<string name="please_provide_point_name_error">Задайте название точки</string>
<string name="quick_action_remove_next_destination_descr">Следующая точка маршрута будет удалена. Если это конечный пункт, навигация завершится.</string>
<string name="plugin_wikipedia_description">Информация о достопримечательностях из Википедии. Ваш карманный офлайн-путеводитель — просто включите плагин Википедии и читайте об объектах вокруг вас.</string>
<string name="plugin_wikipedia_description">Информация о достопримечательностях из Википедии, карманного автономного путеводителя со статьями о местах и направлениях.</string>
<string name="search_download_wikipedia_maps">Скачать карты Википедии</string>
<string name="app_mode_enduro_motorcycle">Эндуро мотоцикл</string>
<string name="app_mode_motor_scooter">Мотороллер</string>
@ -3937,4 +3937,59 @@
<string name="shared_string_folders">Папки</string>
<string name="select_folder">Выбор папки</string>
<string name="select_folder_descr">Выберите папку или добавьте новую</string>
<string name="voice_prompts_timetable">Время голосовых подсказок</string>
<string name="elevation_data">Можно использовать данные о высотах для учёта подъёма/спуска поездки</string>
<string name="routing_attr_prefer_hiking_routes_description">Предпочитать пешеходные маршруты</string>
<string name="shared_string_subtype">Подтип</string>
<string name="shared_string_enter_param">Введите параметр</string>
<string name="routing_engine_vehicle_type_walking">Пешеход</string>
<string name="routing_engine_vehicle_type_scooter">Самокат</string>
<string name="analyze_by_intervals">Анализ по интервалам (по отдельности)</string>
<string name="announcement_time_prepare_long">Заблаговременно</string>
<string name="announcement_time_prepare">Заранее</string>
<string name="announcement_time_passing">При прохождении</string>
<string name="announcement_time_approach">При приближении</string>
<string name="routing_engine_vehicle_type_wheelchair">Инвалидная коляска</string>
<string name="routing_engine_vehicle_type_hiking">Пеший туризм</string>
<string name="routing_engine_vehicle_type_small_truck">Малый грузовик</string>
<string name="routing_engine_vehicle_type_truck">Грузовик</string>
<string name="copy_to_map_markers">Копировать в маркеры</string>
<string name="copy_to_map_favorites">Копировать в избранное</string>
<string name="delete_online_routing_engine">Удалить онлайн-маршрутизатор\?</string>
<string name="routing_attr_prefer_hiking_routes_name">Предпочитать пешеходные маршруты</string>
<string name="add_online_routing_engine">Добавить онлайн-маршрутизатор</string>
<string name="edit_online_routing_engine">Редактировать онлайн-маршрутизатор</string>
<string name="shared_string_api_key">Ключ API</string>
<string name="shared_string_server_url">URL-адрес сервера</string>
<string name="keep_it_empty_if_not">Оставить пустым, если не</string>
<string name="online_routing_example_hint">URL со всеми параметрами будет выглядеть так:</string>
<string name="test_route_calculation">Тест расчёта маршрута</string>
<string name="routing_engine_vehicle_type_car">Автомобиль</string>
<string name="online_routing_engine">Онлайн-маршрутизатор</string>
<string name="online_routing_engines">Онлайн-маршрутизаторы</string>
<string name="shared_string_empty">Пусто</string>
<string name="upload_to_openstreetmap">Отправить в OpenStreetMap</string>
<string name="edit_track">Редактировать трек</string>
<string name="rename_track">Переименовать трек</string>
<string name="change_folder">Изменить папку</string>
<string name="shared_string_sec">сек.</string>
<string name="announcement_time_off_route">Вне маршрута</string>
<string name="announcement_time_arrive">Прибытие в пункт назначения</string>
<string name="shared_string_turn">Поворот</string>
<string name="announcement_time_intervals">Интервалы времени и расстояния</string>
<string name="announcement_time_title">Время объявления</string>
<string name="announcement_time_descr">Время объявления различных голосовых подсказок зависит от типа подсказки, текущей скорости навигации и скорости навигации по умолчанию.</string>
<string name="start_recording">Начать запись</string>
<string name="show_track_on_map">Показать трек на карте</string>
<string name="message_server_error">Ошибка сервера: %1$s</string>
<string name="message_name_is_already_exists">Имя уже существует</string>
<string name="context_menu_read_full">Читать полностью</string>
<string name="context_menu_edit_descr">Редактировать описание</string>
<string name="delete_waypoints">Удалить путевые точки</string>
<string name="routing_engine_vehicle_type_hgv">HGV</string>
<string name="upload_photo">Отправка</string>
<string name="upload_photo_completed">Отправка завершена</string>
<string name="uploading_count">Отправка %1$d из %2$d</string>
<string name="uploaded_count">Отправлено %1$d из %2$d</string>
<string name="toast_select_edits_for_upload">Выберите правки для отправки</string>
</resources>

View file

@ -3982,4 +3982,21 @@
<string name="routing_engine_vehicle_type_mtb">MTB (motosilurante)</string>
<string name="message_server_error">Errore de su serbidore: %1$s</string>
<string name="message_name_is_already_exists">Su nùmene esistit giai</string>
<string name="analyze_by_intervals">Analiza pro intervallos (intervallu fratzionadu)</string>
<string name="upload_to_openstreetmap">Càrriga in OpenStreetMap</string>
<string name="edit_track">Modìfica sa rasta</string>
<string name="rename_track">Modìfica su nùmene de sa rasta</string>
<string name="change_folder">Càmbia sa cartella</string>
<string name="shared_string_sec">seg</string>
<string name="delete_online_routing_engine">Iscantzellare custu motore de càrculu in lìnia\?</string>
<string name="context_menu_read_full">Leghe totu</string>
<string name="context_menu_edit_descr">Modìfica sa descritzione</string>
<string name="delete_waypoints">Iscantzella sos puntos de coladòrgiu</string>
<string name="copy_to_map_markers">Còpia in sos marcadores de sa mapa</string>
<string name="copy_to_map_favorites">Còpia in sos preferidos</string>
<string name="upload_photo">Carrighende</string>
<string name="upload_photo_completed">Carrigamentu acabadu</string>
<string name="uploading_count">Carrighende %1$d de %2$d</string>
<string name="uploaded_count">%1$d de %2$d carrigados</string>
<string name="toast_select_edits_for_upload">Ischerta modìficas de carrigare</string>
</resources>

View file

@ -2434,7 +2434,7 @@
<string name="average">Priemer</string>
<string name="of">%1$d z %2$d</string>
<string name="ascent_descent">Stúpanie/Klesanie</string>
<string name="moving_time">Trvanie presunu</string>
<string name="moving_time">Čas v pohybe</string>
<string name="max_min">Max/Min</string>
<string name="quick_action_resume_pause_navigation">Pozastaviť/pokračovať navigáciu</string>
<string name="quick_action_resume_pause_navigation_descr">Tlačidlo pre pozastavenie alebo pokračovanie navigácie.</string>
@ -3995,4 +3995,15 @@
<string name="message_server_error">Chyba servera: %1$s</string>
<string name="message_name_is_already_exists">Názov už existuje</string>
<string name="shared_string_turn">Odbočiť</string>
<string name="delete_online_routing_engine">Odstrániť túto online navigačnú službu\?</string>
<string name="context_menu_read_full">Prečítať celé</string>
<string name="context_menu_edit_descr">Upraviť popis</string>
<string name="delete_waypoints">Odstrániť body trasy</string>
<string name="copy_to_map_markers">Skopírovať do mapových značiek</string>
<string name="copy_to_map_favorites">Skopírovať do obľúbených</string>
<string name="upload_photo">Odosielanie</string>
<string name="upload_photo_completed">Odoslanie dokončené</string>
<string name="uploading_count">Odosiela sa %1$d z %2$d</string>
<string name="uploaded_count">Odoslané %1$d z %2$d</string>
<string name="toast_select_edits_for_upload">Zvoľte úpravy na odoslanie</string>
</resources>

View file

@ -3275,14 +3275,14 @@
<string name="select_folder">Izberi mapo</string>
<string name="select_folder_descr">Izberi mapo ali dodaj novo</string>
<string name="shared_string_empty">Prazno</string>
<string name="analyze_by_intervals">Analiziraj po intervalih (razdelitveni interval)</string>
<string name="analyze_by_intervals">Preuči po intervalih (razdelitveni interval)</string>
<string name="upload_to_openstreetmap">Naloži v OpenStreetMap</string>
<string name="edit_track">Uredi sled</string>
<string name="rename_track">Preimenuj sled</string>
<string name="change_folder">Spremeni mapo</string>
<string name="shared_string_sec">sek</string>
<string name="announcement_time_approach">Pristop</string>
<string name="announcement_time_prepare">Pripravi se</string>
<string name="announcement_time_prepare">Pripravljanje</string>
<string name="announcement_time_off_route">Izven poti</string>
<string name="announcement_time_arrive">Prihod na cilj</string>
<string name="shared_string_turn">Zavoj</string>
@ -3296,7 +3296,7 @@
<string name="routing_engine_vehicle_type_cycling_electric">Električno kolesarjenje</string>
<string name="routing_engine_vehicle_type_cycling_mountain">Gorsko kolesarjenje</string>
<string name="routing_engine_vehicle_type_cycling_road">Cestno kolesarjenje</string>
<string name="routing_engine_vehicle_type_cycling_regular">Redno kolesarjenje</string>
<string name="routing_engine_vehicle_type_cycling_regular">Mestno kolesarjenje</string>
<string name="routing_engine_vehicle_type_hgv">Težko tovorno vozilo</string>
<string name="routing_engine_vehicle_type_small_truck">Majhno tovorno vozilo</string>
<string name="routing_engine_vehicle_type_truck">Tovorno vozilo</string>
@ -3305,4 +3305,55 @@
<string name="routing_engine_vehicle_type_mtb">MTB</string>
<string name="message_server_error">Napaka strežnika: %1$s</string>
<string name="message_name_is_already_exists">To ime že obstaja</string>
<string name="context_menu_read_full">Preberi v celoti</string>
<string name="context_menu_edit_descr">Uredi opis</string>
<string name="delete_waypoints">Brisanje točk</string>
<string name="copy_to_map_markers">Kopiraj na oznake na zemljevidu</string>
<string name="export_not_enough_space">Na napravi ni dovolj prostora.</string>
<string name="select_groups_for_import">Izbor skupin za uvoz.</string>
<string name="select_items_for_import">Izbor predmetov za uvoz.</string>
<string name="add_to_mapillary">Dodaj na Mapillary</string>
<string name="add_to_opr">Dodaj na OpenPlaceReviews</string>
<string name="use_dev_url_descr">Za preizkušanje pošiljanja sporočil, točk in sledi GPX preklopi iz openstreetmap.org na preizkusni dev.openstreetmap.org.</string>
<string name="use_dev_url">Uporabi dev.openstreetmap.org</string>
<string name="add_photos_descr">Program podpira prikaz fotografij različnih virov:
\nOpenPlaceReviews fotografije točk POI;
\nMapillary ulična fotografija;
\nSplet / Wikimedia fotografije točk POI in OpenStreetMap.</string>
<string name="ltr_or_rtl_combine_via_star">%1$s * %2$s</string>
<string name="plan_route_add_new_segment">Dodaj nov del poti</string>
<string name="app_mode_light_aircraft">Lahko letalo</string>
<string name="plan_route_join_segments">Združi dele poti</string>
<string name="plan_route_split_before">Razdeli pred</string>
<string name="plan_route_split_after">Razdeli po</string>
<string name="profile_type_osmand_string">Profil OsmAnd</string>
<string name="profile_type_user_string">Uporabniški profil</string>
<string name="reverse_all_points">Obrni vse točke</string>
<string name="profile_by_default_description">Izbor profila, ki bo prikazan ob zagonu programa.</string>
<string name="shared_string_last_used">Nazadnje uporabljeno</string>
<string name="shared_string_subtype">Podvrsta</string>
<string name="shared_string_vehicle">Vozilo</string>
<string name="shared_string_api_key">Ključ API</string>
<string name="shared_string_server_url">Naslov URL strežnika</string>
<string name="shared_string_enter_param">Vpis parametrov</string>
<string name="online_routing_example_hint">Naslov URL z vsemi parametri bo zapisan kot:</string>
<string name="test_route_calculation">Preizkusi izračun poti</string>
<string name="routing_engine_vehicle_type_driving">Vožnja</string>
<string name="routing_engine_vehicle_type_foot">Hoja</string>
<string name="routing_engine_vehicle_type_bike">Kolo</string>
<string name="routing_engine_vehicle_type_car">Avto</string>
<string name="copy_address">Kopiraj naslov</string>
<string name="announcement_time_prepare_long">Dolgo pripravljanje</string>
<string name="show_track_on_map">Pokaži sled na zemljevidu</string>
<string name="shared_string_zoom_levels">Raven približanja</string>
<string name="shared_string_transparency">Prosojnost</string>
<string name="shared_string_legend">Legenda</string>
<string name="terrain_empty_state_text">Prikaz višinskega senčenja na zemljevidu. Več o tem je mogoče prebrati na spletni strani programa.</string>
<string name="shared_string_hillshade">Senčenje</string>
<string name="copy_to_map_favorites">Kopiraj med priljubljene</string>
<string name="upload_photo">Poteka pošiljanje</string>
<string name="upload_photo_completed">Pošiljanje je končano</string>
<string name="uploading_count">Poteka pošiljanje %1$d od %2$d</string>
<string name="uploaded_count">Poslano %1$d od %2$d</string>
<string name="toast_select_edits_for_upload">Izbor sprememb za pošiljanje</string>
</resources>

View file

@ -299,14 +299,14 @@
<string name="poi_recycling_paper">Kağıt</string>
<string name="poi_recycling_clothes">Giyim</string>
<string name="poi_recycling_cans">Kutular</string>
<string name="poi_recycling_glass_bottles">Cam şişeler</string>
<string name="poi_recycling_glass_bottles">Cam şişeleri</string>
<string name="poi_recycling_plastic">Plastik</string>
<string name="poi_recycling_scrap_metal">Hurda metal</string>
<string name="poi_recycling_batteries">Piller</string>
<string name="poi_recycling_plastic_bottles">Plastik şişeler</string>
<string name="poi_recycling_green_waste">Yeşil atık</string>
<string name="poi_recycling_waste">Atık (siyah çanta)</string>
<string name="poi_recycling_plastic_packaging">Plastik Ambalaj</string>
<string name="poi_recycling_plastic_packaging">Plastik ambalaj</string>
<string name="poi_recycling_newspaper">Gazete</string>
<string name="poi_recycling_cartons">Kartonlar</string>
<string name="poi_recycling_cardboard">Mukavva</string>
@ -316,11 +316,11 @@
<string name="poi_recycling_wood">Ahşap</string>
<string name="poi_recycling_books">Kitaplar</string>
<string name="poi_recycling_shoes">Ayakkabı</string>
<string name="poi_recycling_aluminium">alüminyum</string>
<string name="poi_recycling_aluminium">Alüminyum</string>
<string name="poi_recycling_organic">Organik</string>
<string name="poi_recycling_beverage_cartons">İçecek kartonları</string>
<string name="poi_recycling_garden_waste">Bahçe atıkları</string>
<string name="poi_recycling_low_energy_bulbs">Düşük enerji Ampüller</string>
<string name="poi_recycling_low_energy_bulbs">Düşük enerjili ampüller</string>
<string name="poi_recycling_fluorescent_tubes">Floresan tüpler</string>
<string name="poi_recycling_metal">Metal</string>
<string name="poi_recycling_electrical_items">Elektrik ögeleri</string>
@ -329,16 +329,16 @@
<string name="poi_recycling_engine_oil">Motor yağı</string>
<string name="poi_recycling_plastic_bags">Plastik torbalar</string>
<string name="poi_recycling_hazardous_waste">Tehlikeli atık</string>
<string name="poi_recycling_mobile_phones">Cep telefonları</string>
<string name="poi_recycling_mobile_phones">Cep telefonu</string>
<string name="poi_recycling_hydrargyrum">Cıva</string>
<string name="poi_recycling_computers">Bilgisayarlar</string>
<string name="poi_recycling_tyres">Lastikler</string>
<string name="poi_recycling_tyres">Araba lastiği</string>
<string name="poi_recycling_tv_monitor">TV, monitör</string>
<string name="poi_recycling_tetrapak">Karton kutu</string>
<string name="poi_recycling_rubble">Moloz</string>
<string name="poi_recycling_cds">CD</string>
<string name="poi_recycling_waste_oil">Atık yağ</string>
<string name="poi_recycling_bottles">Şişe</string>
<string name="poi_recycling_bottles">Şişeler</string>
<string name="poi_recycling_cork">Tıpa</string>
<string name="poi_recycling_printer_cartridges">Yazıcı kartuşları</string>
<string name="poi_recycling_sheet_metal">Sac metal</string>
@ -349,7 +349,7 @@
<string name="poi_recycling_compost">Gübre</string>
<string name="poi_recycling_hardcore">Zor</string>
<string name="poi_recycling_christmas_trees">Noel ağaçları</string>
<string name="poi_recycling_light_bulbs">ık Ampülleri</string>
<string name="poi_recycling_light_bulbs">Ampüller</string>
<string name="poi_recycling_chipboard">Sunta</string>
<string name="poi_recycling_polyester">Polyester</string>
<string name="poi_recycling_plasterboard">Alçıpan</string>
@ -584,7 +584,7 @@
<string name="poi_place_of_worship">İbadethane</string>
<string name="poi_religion_christian">Hristiyanlık</string>
<string name="poi_religion_jewish">Yahudilik</string>
<string name="poi_religion_muslim">İslami</string>
<string name="poi_religion_muslim">İslam</string>
<string name="poi_religion_sikh">Sih dini</string>
<string name="poi_religion_buddhist">Budizm</string>
<string name="poi_religion_hindu">Hinduizm</string>
@ -823,9 +823,9 @@
<string name="poi_accountant">Muhasebeci</string>
<string name="poi_bitcoin_yes">Bitcoin ödeme</string>
<string name="poi_cave_entrance">Mağara girişi</string>
<string name="poi_peak">Dağın tepesi</string>
<string name="poi_peak">Zirve</string>
<string name="poi_saddle">Eyer</string>
<string name="poi_volcano">Volkan</string>
<string name="poi_volcano">Yanardağ</string>
<string name="poi_crater">Krater</string>
<string name="poi_ridge">Sırt</string>
<string name="poi_glacier">Buzul</string>
@ -896,13 +896,13 @@
<string name="poi_wiki_lang_he">İbranice wiki</string>
<string name="poi_wiki_lang_hi">Hintçe wiki</string>
<string name="poi_wiki_lang_hr">Hırvatça wiki</string>
<string name="poi_wiki_lang_ht">Haiti dilinde wiki</string>
<string name="poi_wiki_lang_ht">Haitice wiki</string>
<string name="poi_wiki_lang_hu">Macarca wiki</string>
<string name="poi_wiki_lang_id">Endonezyaca wiki</string>
<string name="poi_wiki_lang_it">İtalyanca wiki</string>
<string name="poi_wiki_lang_lv">Letonca wiki</string>
<string name="poi_wiki_lang_ms">Malayca wiki</string>
<string name="poi_wiki_lang_new">Newar dilinde wiki</string>
<string name="poi_wiki_lang_new">Nevarca wiki</string>
<string name="poi_wiki_lang_nl">Flemenkçe wiki</string>
<string name="poi_wiki_lang_nn">Norveççe Nynorsk wiki</string>
<string name="poi_wiki_lang_no">Norveççe wiki</string>
@ -1385,7 +1385,7 @@
<string name="poi_generator_source_diesel">Enerji kaynağı: dizel</string>
<string name="poi_int_name">Uluslararası isim</string>
<string name="poi_nat_name">Ulusal isim</string>
<string name="poi_reg_name">Bölgesel isim</string>
<string name="poi_reg_name">Yerel ad</string>
<string name="poi_loc_name">Yerel isim</string>
<string name="poi_old_name">Eski isim</string>
<string name="poi_alt_name">Alternatif isim</string>
@ -1679,12 +1679,12 @@
<string name="poi_diet_gluten_free_only">Sadece glutensiz</string>
<string name="poi_diet_gluten_free_yes">Glutensiz</string>
<string name="poi_diet_gluten_free_no">Glutensiz diyet: hayır</string>
<string name="poi_diet_kosher_only">Sadece kosher</string>
<string name="poi_diet_kosher_only">Sadece koşer</string>
<string name="poi_diet_kosher_yes">Kosher</string>
<string name="poi_diet_kosher_no">Kosher diyet: hayır</string>
<string name="poi_diet_kosher_no">Koşer gıda: hayır</string>
<string name="poi_diet_halal_only">Sadece helal</string>
<string name="poi_diet_halal_yes">Helal</string>
<string name="poi_diet_halal_no">Helal diyet: hayır</string>
<string name="poi_diet_halal_no">Helal gıda: hayır</string>
<string name="poi_diet_lactose_free_only">Sadece laktozsuz</string>
<string name="poi_diet_lactose_free_yes">Laktozsuz</string>
<string name="poi_diet_lactose_free_no">Laktozsuz diyet: hayır</string>
@ -1718,7 +1718,7 @@
<string name="poi_diet_vegetarian_filter_yes">Vejetaryen</string>
<string name="poi_diet_vegan_filter_yes">Vegan</string>
<string name="poi_diet_gluten_free_filter_yes">Glutensiz</string>
<string name="poi_diet_kosher_filter_yes">Kosher</string>
<string name="poi_diet_kosher_filter_yes">Koşer</string>
<string name="poi_diet_halal_filter_yes">Helal</string>
<string name="poi_diet_lactose_free_filter_yes">Laktozsuz</string>
<string name="poi_takeaway_filter_yes">Evet</string>
@ -1902,7 +1902,7 @@
<string name="poi_faa">FAA kodu</string>
<string name="poi_artwork_type_sculpture">Sanat eseri türü: heykel</string>
<string name="poi_internet_access_type_yes">İnternet erişimi var</string>
<string name="poi_cash_withdrawal_bank_card">Nakit para çekme</string>
<string name="poi_cash_withdrawal_bank_card">Nakit çekme</string>
<string name="poi_swing_gate">Salıncak kapı</string>
<string name="poi_kent_carriage_gap">Kent at arabası boşluğu</string>
<string name="poi_windfall">Rüzgar tarafından düşürülen</string>
@ -2283,7 +2283,7 @@
<string name="poi_historic_civilization_nuragic">Uygarlık: nuragic (MÖ 18. yy MS 2. yy)</string>
<string name="poi_historic_civilization_etruscan">Uygarlık: etrüsk (MÖ 12. 6. yy)</string>
<string name="poi_historic_civilization_prehistoric">Uygarlık: tarih öncesi</string>
<string name="poi_historic_civilization_ancient_greek">Uygarlık: antik yunan</string>
<string name="poi_historic_civilization_ancient_greek">Uygarlık: eski yunan</string>
<string name="poi_historic_civilization_roman">Uygarlık: roma</string>
<string name="poi_historic_civilization_byzantine">Uygarlık: bizans (MS 285 MS 1453)</string>
<string name="poi_historic_civilization_imperial_chinese">Uygarlık: çin imparatorluğu (MÖ 221 MS 1911)</string>
@ -2291,7 +2291,7 @@
<string name="poi_historic_civilization_celtic">Uygarlık: kelt</string>
<string name="poi_historic_civilization_western_roman">Uygarlık: batı roma (MS 285 MS 476)</string>
<string name="poi_historic_civilization_mycenaean">Uygarlık: miken</string>
<string name="poi_historic_civilization_dacian">Uygarlık: dacian</string>
<string name="poi_historic_civilization_dacian">Uygarlık: daçya</string>
<string name="poi_historic_civilization_hernici">Uygarlık: hernici</string>
<string name="poi_historic_civilization_greek_egyptian">Uygarlık: yunan mısırı (MÖ 332 MÖ 30)</string>
<string name="poi_historic_civilization_roman_and_byzantine_egyptian">Uygarlık: roma ve bizans mısırı</string>
@ -2309,10 +2309,10 @@
<string name="poi_sms">SMS</string>
<string name="poi_volcano_status">Durum</string>
<string name="poi_volcano_type">Tür</string>
<string name="poi_historic_era_chalcolithic">Tarihi çağ: kalkolitik (MÖ 4.3. milenyum)</string>
<string name="poi_historic_era_neolithic">Tarihi çağ: neolitik</string>
<string name="poi_historic_era_mesolithic">Tarihi çağ: mezolitik</string>
<string name="poi_historic_era_paleolithic">Tarihi çağ: paleolitik (günümüzden 2,6 milyon yıl önce 10000 yıl önce)</string>
<string name="poi_historic_era_chalcolithic">Tarihi çağ: bakır taş (MÖ 4.3. milenyum)</string>
<string name="poi_historic_era_neolithic">Tarihi çağ: cilalı taş</string>
<string name="poi_historic_era_mesolithic">Tarihi çağ: orta taş</string>
<string name="poi_historic_era_paleolithic">Tarihi çağ: yontma taş (günümüzden 2,6 milyon yıl önce 10000 yıl önce)</string>
<string name="poi_historic_period_imperial">Tarihi dönem: imparatorluk (dönem V, MS 900 MS 1200</string>
<string name="poi_historic_period_classical">Tarihi dönem: klasik (dönem IV, MS 374 MS 900)</string>
<string name="poi_historic_period_urban">Tarihi dönem: kentsel (dönem III, MS 133 MS 374)</string>
@ -2892,18 +2892,18 @@
<string name="poi_cuisine_waffle">Waffle</string>
<string name="poi_cuisine_crepes">Krep</string>
<string name="poi_cuisine_falafel">Falafel</string>
<string name="poi_cuisine_tacos">Taco</string>
<string name="poi_cuisine_tacos">Tako</string>
<string name="poi_cuisine_canteen">Kantin</string>
<string name="poi_cuisine_savory_pancakes">Tuzlu krep</string>
<string name="poi_cuisine_fried_chicken">Kızarmış tavuk</string>
<string name="poi_cuisine_couscous">Kuskus</string>
<string name="poi_cuisine_bakery">Fırın</string>
<string name="poi_cuisine_bistro">Bistro</string>
<string name="poi_cuisine_fried_food">Kızarmış yiyecekler</string>
<string name="poi_cuisine_fried_food">Kızartma</string>
<string name="poi_cuisine_frozen_yogurt">Dondurulmuş yoğurt</string>
<string name="poi_cuisine_deli">Şarküteri</string>
<string name="poi_cuisine_pie">Turta</string>
<string name="poi_cuisine_tea_shop">Çay dükkanı</string>
<string name="poi_cuisine_tea_shop">Çaycı</string>
<string name="poi_health_person_type_witchdoctor">Sağlık çalışanının rolü: büyücü</string>
<string name="poi_health_person_type_technician">Sağlık çalışanının rolü: teknisyen</string>
<string name="poi_health_person_type_physician_assitant">Sağlık çalışanının rolü: doktor asistanı</string>
@ -3138,4 +3138,100 @@
<string name="poi_hgv_agricultural">ır yük aracı erişimi: tarım</string>
<string name="poi_hgv_no">ır yük aracı erişimi: hayır</string>
<string name="poi_hgv_private">ır yük aracı erişimi: özel</string>
<string name="poi_water_source_lake">Göl</string>
<string name="poi_water_source_river">Irmak</string>
<string name="poi_water_source_well">Kuyu</string>
<string name="poi_vaccination_covid19">ılama: Kovid-19</string>
<string name="poi_nurse">Hemşire</string>
<string name="poi_diplomatic_services_citizen_services_no">Hayır</string>
<string name="poi_diplomatic_services_citizen_services_yes">Evet</string>
<string name="poi_diplomatic_services_immigrant_visas_no">Hayır</string>
<string name="poi_diplomatic_services_immigrant_visas_yes">Evet</string>
<string name="poi_diplomatic_services_non_immigrant_visas_no">Hayır</string>
<string name="poi_diplomatic_services_non_immigrant_visas_yes">Evet</string>
<string name="poi_nuts">Çerezci</string>
<string name="poi_beehive">Arı kovanı</string>
<string name="poi_traffic_signals_sound_locate">Sadece yürümeye izin verildiğinde</string>
<string name="poi_internet_access_fee_customers">İnternet erişimi: müşteriler</string>
<string name="poi_volcano_number_of_eruptions">Püskürme sayısı</string>
<string name="poi_volcano_last_eruption">Son püskürme</string>
<string name="poi_grave">Mezar</string>
<string name="poi_cash_withdrawal_girocard">Girocard</string>
<string name="poi_cash_withdrawal_fee_no">Nakit çekme ücreti: hayır</string>
<string name="poi_cash_withdrawal_fee_yes">Nakit çekme ücreti: evet</string>
<string name="poi_cash_withdrawal_currency">Nakit çekme para birimi</string>
<string name="poi_cash_withdrawal">Nakit çekme</string>
<string name="poi_cash_withdrawal_yes">Nakit çekme: evet</string>
<string name="poi_disabled_yes">Evet</string>
<string name="poi_goods_yes">Evet</string>
<string name="poi_hgv_yes">Evet</string>
<string name="poi_mofa_yes">Evet</string>
<string name="poi_moped_yes">Evet</string>
<string name="poi_motorcycle_permissive">Serbest</string>
<string name="poi_motorcycle_yes">Evet</string>
<string name="poi_trailer_yes">Evet</string>
<string name="poi_motorhome_yes">Evet</string>
<string name="poi_caravan_yes">Evet</string>
<string name="poi_bus_yes">Evet</string>
<string name="poi_snowmobile_permissive">Serbest</string>
<string name="poi_snowmobile_yes">Evet</string>
<string name="poi_taxi_no">Taksi erişimi: hayır</string>
<string name="poi_taxi_yes">Taksi erişimi: evet</string>
<string name="poi_agricultural_no">Tarım aracı erişimi: hayır</string>
<string name="poi_agricultural_yes">Tarım aracı erişimi: evet</string>
<string name="poi_snowmobile_no">Kar arabası erişimi: hayır</string>
<string name="poi_snowmobile_private">Kar arabası erişimi: özel</string>
<string name="poi_bus_no">Otobüs erişimi: hayır</string>
<string name="poi_caravan_no">Karavan erişimi: hayır</string>
<string name="poi_foot_customers">Yaya erişimi: müşteriler</string>
<string name="poi_foot_permissive">Yaya erişimi: serbest</string>
<string name="poi_foot_no">Yaya erişimi: hayır</string>
<string name="poi_foot_private">Yaya erişimi: özel</string>
<string name="poi_foot_yes">Yaya erişimi: evet</string>
<string name="poi_horse_permissive">At erişimi: serbest</string>
<string name="poi_horse_private">At erişimi: özel</string>
<string name="poi_bicycle_customers">Bisiklet erişimi: müşteriler</string>
<string name="poi_bicycle_permissive">Bisiklet erişimi: serbest</string>
<string name="poi_bicycle_private">Bisiklet erişimi: özel</string>
<string name="poi_moped_no">Moped erişimi: hayır</string>
<string name="poi_motorcycle_private">Motorsiklet erişimi: özel</string>
<string name="poi_vehicle_military">Araç erişimi: askerî</string>
<string name="poi_vehicle_customers">Araç erişimi: müşteriler</string>
<string name="poi_vehicle_permissive">Araç erişimi: serbset</string>
<string name="poi_vehicle_no">Araç erişimi: hayır</string>
<string name="poi_vehicle_private">Araç erişimi: özel</string>
<string name="poi_vehicle_yes">Araç erişimi: evet</string>
<string name="poi_park_ride_metro">Metro</string>
<string name="poi_laboratory">Tıp laboratuvarı</string>
<string name="poi_ruins">Kalıntılar</string>
<string name="poi_payment_contactless_no">Temassız kabul edilmiyor</string>
<string name="poi_payment_contactless_yes">Temassız</string>
<string name="poi_service_vehicle_tyres_yes">Lastikler</string>
<string name="poi_service_vehicle_car_parts_yes">Araba parçaları</string>
<string name="poi_agrarian">Tarım mağazası</string>
<string name="poi_meadow_pasture">Tür: otlak</string>
<string name="poi_climbing_routes">Tırmanma güzergahları</string>
<string name="poi_climbing_ice_no">Buz: hayır</string>
<string name="poi_climbing_ice_yes">Buz: evet</string>
<string name="poi_climbing_sport_no">Spor: hayır</string>
<string name="poi_climbing_sport_yes">Spor: evet</string>
<string name="poi_money_transfer">Para gönderme</string>
<string name="poi_location_bridge">Konum: köprü</string>
<string name="poi_boat_canoe_rental_rental_no">Kano: hayır</string>
<string name="poi_boat_canoe_rental_rental_yes">Kano: evet</string>
<string name="poi_boat_kayak_rental_rental_no">Kayaklar: hayır</string>
<string name="poi_boat_kayak_rental_rental_yes">Kayaklar: evet</string>
<string name="poi_zoo_falconry">Kuşçuluk</string>
<string name="poi_zoo_safari_park">Safari parkı</string>
<string name="poi_locomotive">Lokomotif</string>
<string name="poi_cuisine_beef_bowl">Gıdon</string>
<string name="poi_traffic_mirror">Trafik aynası</string>
<string name="poi_inscription_ne">Yazıt: KD</string>
<string name="poi_inscription_e">Yazıt: D</string>
<string name="poi_inscription_se">Yazıt: GD</string>
<string name="poi_inscription_s">Yazıt: G</string>
<string name="poi_inscription_sw">Yazıt: GB</string>
<string name="poi_inscription_w">Yazıt: B</string>
<string name="poi_inscription_nw">Yazıt: KB</string>
<string name="poi_inscription_n">Yazıt: K</string>
</resources>

View file

@ -2332,7 +2332,7 @@
<string name="access_autoannounce_period">Otomatik-sesli-bildirim periyodu</string>
<string name="no_waypoints_found">Uğranacak-ara-noktalar bulunamadı</string>
<string name="lang_es_us">İspanyolca (Amerikan)</string>
<string name="moving_time">Hareket Zamanı</string>
<string name="moving_time">Hareket halindeki zaman</string>
<string name="purchase_dialog_title">Plan seçin</string>
<string name="purchase_dialog_travel_description">Çevrim dışı seyahat rehberi işlevselliğini almak için aşağıdakilerden birini satın alın:</string>
<string name="purchase_dialog_subtitle">Uygun ögeyi seçin</string>
@ -4007,4 +4007,9 @@
<string name="delete_online_routing_engine">Bu çevrim içi yönlendirme motoru silinsin mi\?</string>
<string name="context_menu_read_full">Tamamını oku</string>
<string name="context_menu_edit_descr">ıklamayı düzenle</string>
<string name="upload_photo">Karşıya yükleniyor</string>
<string name="upload_photo_completed">Karşıya yükleme tamamlandı</string>
<string name="uploading_count">%1$d / %2$d karşıya yükleniyor</string>
<string name="uploaded_count">%1$d / %2$d karşıya yüklendi</string>
<string name="toast_select_edits_for_upload">Karşıya yüklenecek düzenlemeleri seçin</string>
</resources>

View file

@ -2436,7 +2436,7 @@
<string name="average">Середнє</string>
<string name="of">%1$d зі %2$d</string>
<string name="ascent_descent">Підйом/спуск</string>
<string name="moving_time">Час руху</string>
<string name="moving_time">Час у русі</string>
<string name="max_min">Макс/мін</string>
<string name="min_max">Мін/макс</string>
<string name="rendering_value_translucent_pink_name">Напівпрозорий рожевий</string>
@ -4005,4 +4005,9 @@
<string name="delete_waypoints">Видалити маршрутні точки</string>
<string name="copy_to_map_markers">Копіювати до позначок мапи</string>
<string name="copy_to_map_favorites">Копіювати до закладок</string>
<string name="upload_photo">Вивантаження</string>
<string name="upload_photo_completed">Вивантаження завершено</string>
<string name="uploading_count">Вивантаження %1$d з %2$d</string>
<string name="uploaded_count">Вивантажено %1$d з %2$d</string>
<string name="toast_select_edits_for_upload">Виберіть зміни для вивантаження</string>
</resources>

View file

@ -2430,7 +2430,7 @@
<string name="average">平均</string>
<string name="of">%1$d 的 %2$d</string>
<string name="ascent_descent">上升/下降</string>
<string name="moving_time">動時間</string>
<string name="moving_time">動時間</string>
<string name="max_min">最大/最小</string>
<string name="min_max">最小/最大</string>
<string name="rendering_value_translucent_pink_name">半透明粉紅色</string>
@ -3993,4 +3993,15 @@
<string name="routing_engine_vehicle_type_mtb">登山車</string>
<string name="message_server_error">伺服器錯誤:%1$s</string>
<string name="message_name_is_already_exists">名稱已存在</string>
<string name="delete_online_routing_engine">刪除此線上路線引擎?</string>
<string name="context_menu_read_full">讀取全部</string>
<string name="context_menu_edit_descr">編輯描述</string>
<string name="delete_waypoints">刪除航點</string>
<string name="copy_to_map_markers">複製到地圖標記</string>
<string name="copy_to_map_favorites">複製到收藏</string>
<string name="upload_photo">正在上傳</string>
<string name="upload_photo_completed">已完成上傳</string>
<string name="uploading_count">正在上傳 %1$d共 %2$d</string>
<string name="uploaded_count">已上傳 %1$d共 %2$d</string>
<string name="toast_select_edits_for_upload">選取要上傳的檔案</string>
</resources>

View file

@ -12,6 +12,7 @@
-->
<string name="hillshade_slope_contour_lines">Hillshade / Slope / Contour lines</string>
<string name="toast_select_edits_for_upload">Select edits for upload</string>
<string name="uploaded_count">Uploaded %1$d of %2$d</string>
<string name="uploading_count">Uploading %1$d of %2$d</string>
@ -55,7 +56,7 @@
<string name="rename_track">Rename track</string>
<string name="edit_track">Edit track</string>
<string name="upload_to_openstreetmap">Upload to OpenStreetMap</string>
<string name="analyze_by_intervals">Analyze by intervals (split interval)</string>
<string name="analyze_by_intervals">Analyze split intervals</string>
<string name="shared_string_empty">Empty</string>
<string name="select_folder_descr">Select folder or add new one</string>
<string name="select_folder">Select folder</string>

View file

@ -14,10 +14,10 @@
android:title="@string/shared_string_maps"/>
<Preference
android:key="contour_lines_and_hillshade_memory"
android:key="terrain_memory_used"
android:layout="@layout/data_storage_memory_used_item"
android:icon="@drawable/ic_map"
android:title="@string/contour_lines_and_hillshade"/>
android:title="@string/hillshade_slope_contour_lines"/>
<Preference
android:key="tracks_memory_used"

View file

@ -22,7 +22,7 @@
android:layout="@layout/preference_with_descr"
android:persistent="false"
android:title="@string/application_dir"
app:fragment="net.osmand.plus.settings.fragments.DataStorageFragment"
app:fragment="net.osmand.plus.settings.datastorage.DataStorageFragment"
tools:icon="@drawable/ic_action_folder" />
<Preference

View file

@ -2296,13 +2296,13 @@ public class OsmandAidlApi {
return false;
}
public boolean importProfileV2(final Uri profileUri, ArrayList<String> settingsTypeKeys, boolean replace,
String latestChanges, int version) {
public boolean importProfileV2(final Uri profileUri, List<String> settingsTypeKeys, boolean replace,
boolean silent, String latestChanges, int version) {
if (profileUri != null) {
Bundle bundle = new Bundle();
bundle.putStringArrayList(SettingsHelper.SETTINGS_TYPE_LIST_KEY, settingsTypeKeys);
bundle.putStringArrayList(SettingsHelper.SETTINGS_TYPE_LIST_KEY, new ArrayList<>(settingsTypeKeys));
bundle.putBoolean(REPLACE_KEY, replace);
bundle.putBoolean(SILENT_IMPORT_KEY, true);
bundle.putBoolean(SILENT_IMPORT_KEY, silent);
bundle.putString(SettingsHelper.SETTINGS_LATEST_CHANGES_KEY, latestChanges);
bundle.putInt(SettingsHelper.SETTINGS_VERSION_KEY, version);

View file

@ -1270,7 +1270,7 @@ public class OsmandAidlServiceV2 extends Service implements AidlCallbackListener
try {
OsmandAidlApi api = getApi("importProfile");
return api != null && api.importProfileV2(params.getProfileSettingsUri(), params.getSettingsTypeKeys(),
params.isReplace(), params.getLatestChanges(), params.getVersion());
params.isReplace(), params.isSilent(), params.getLatestChanges(), params.getVersion());
} catch (Exception e) {
handleException(e);
return false;

View file

@ -51,6 +51,7 @@ import net.osmand.AndroidUtils;
import net.osmand.Location;
import net.osmand.PlatformUtil;
import net.osmand.data.LatLon;
import net.osmand.plus.helpers.AndroidUiHelper;
import net.osmand.plus.settings.backend.ApplicationMode;
import net.osmand.plus.views.DirectionDrawable;
import net.osmand.plus.widgets.TextViewEx;
@ -87,6 +88,7 @@ public class UiUtilities {
public enum CustomRadioButtonType {
START,
CENTER,
END,
}
@ -454,10 +456,10 @@ public class UiUtilities {
int radius = AndroidUtils.dpToPx(app, 4);
boolean isLayoutRtl = AndroidUtils.isLayoutRtl(app);
TextView startButtonText = buttonsView.findViewById(R.id.left_button);
View startButtonContainer = buttonsView.findViewById(R.id.left_button_container);
TextView endButtonText = buttonsView.findViewById(R.id.right_button);
View centerButtonContainer = buttonsView.findViewById(R.id.center_button_container);
View endButtonContainer = buttonsView.findViewById(R.id.right_button_container);
GradientDrawable background = new GradientDrawable();
background.setColor(UiUtilities.getColorWithAlpha(activeColor, 0.1f));
background.setStroke(AndroidUtils.dpToPx(app, 1), UiUtilities.getColorWithAlpha(activeColor, 0.5f));
@ -467,20 +469,56 @@ public class UiUtilities {
} else {
background.setCornerRadii(new float[]{radius, radius, 0, 0, 0, 0, radius, radius});
}
TextView startButtonText = startButtonContainer.findViewById(R.id.left_button);
TextView endButtonText = endButtonContainer.findViewById(R.id.right_button);
endButtonContainer.setBackgroundColor(Color.TRANSPARENT);
endButtonText.setTextColor(activeColor);
startButtonContainer.setBackgroundDrawable(background);
startButtonText.setTextColor(textColor);
if (centerButtonContainer != null) {
TextView centerButtonText = centerButtonContainer.findViewById(R.id.center_button);
centerButtonText.setTextColor(activeColor);
centerButtonContainer.setBackgroundColor(Color.TRANSPARENT);
}
} else if (buttonType == CustomRadioButtonType.CENTER) {
background.setCornerRadii(new float[] {0, 0, 0, 0, 0, 0, 0, 0});
centerButtonContainer.setBackgroundDrawable(background);
AndroidUiHelper.updateVisibility(centerButtonContainer, true);
TextView centerButtonText = centerButtonContainer.findViewById(R.id.center_button);
centerButtonText.setTextColor(textColor);
if (endButtonContainer != null) {
TextView endButtonText = endButtonContainer.findViewById(R.id.right_button);
endButtonText.setTextColor(activeColor);
endButtonContainer.setBackgroundColor(Color.TRANSPARENT);
}
if (startButtonContainer != null) {
TextView startButtonText = startButtonContainer.findViewById(R.id.left_button);
startButtonText.setTextColor(activeColor);
startButtonContainer.setBackgroundColor(Color.TRANSPARENT);
}
} else {
if (isLayoutRtl) {
background.setCornerRadii(new float[] {radius, radius, 0, 0, 0, 0, radius, radius});
} else {
background.setCornerRadii(new float[]{0, 0, radius, radius, radius, radius, 0, 0});
}
TextView startButtonText = startButtonContainer.findViewById(R.id.left_button);
TextView endButtonText = endButtonContainer.findViewById(R.id.right_button);
endButtonContainer.setBackgroundDrawable(background);
endButtonText.setTextColor(textColor);
startButtonContainer.setBackgroundColor(Color.TRANSPARENT);
startButtonText.setTextColor(activeColor);
if (centerButtonContainer != null) {
TextView centerButtonText = centerButtonContainer.findViewById(R.id.center_button);
centerButtonText.setTextColor(activeColor);
centerButtonContainer.setBackgroundColor(Color.TRANSPARENT);
}
}
}

View file

@ -139,7 +139,7 @@ import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.settings.fragments.BaseSettingsFragment;
import net.osmand.plus.settings.fragments.BaseSettingsFragment.SettingsScreenType;
import net.osmand.plus.settings.fragments.ConfigureProfileFragment;
import net.osmand.plus.settings.fragments.DataStorageFragment;
import net.osmand.plus.settings.datastorage.DataStorageFragment;
import net.osmand.plus.track.TrackAppearanceFragment;
import net.osmand.plus.track.TrackMenuFragment;
import net.osmand.plus.views.AddGpxPointBottomSheetHelper.NewGpxPoint;
@ -651,7 +651,9 @@ public class MapActivity extends OsmandActionBarActivity implements DownloadEven
protected void onNewIntent(final Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
intentHelper.parseLaunchIntents();
if (!intentHelper.parseLaunchIntents()) {
intentHelper.parseContentIntent();
}
}
@Override

View file

@ -40,7 +40,7 @@ import java.util.Map;
public class SavingTrackHelper extends SQLiteOpenHelper {
public final static String DATABASE_NAME = "tracks"; //$NON-NLS-1$
public final static int DATABASE_VERSION = 6;
public final static int DATABASE_VERSION = 7;
public final static String TRACK_NAME = "track"; //$NON-NLS-1$
public final static String TRACK_COL_DATE = "date"; //$NON-NLS-1$
@ -59,6 +59,8 @@ public class SavingTrackHelper extends SQLiteOpenHelper {
public final static String POINT_COL_CATEGORY = "category"; //$NON-NLS-1$
public final static String POINT_COL_DESCRIPTION = "description"; //$NON-NLS-1$
public final static String POINT_COL_COLOR = "color"; //$NON-NLS-1$
public final static String POINT_COL_ICON = "icon"; //$NON-NLS-1$
public final static String POINT_COL_BACKGROUND = "background"; //$NON-NLS-1$
public final static float NO_HEADING = -1.0f;
@ -92,7 +94,10 @@ public class SavingTrackHelper extends SQLiteOpenHelper {
+ TRACK_COL_DATE + ", " + TRACK_COL_HEADING + ")"
+ " VALUES (?, ?, ?, ?, ?, ?, ?)"; //$NON-NLS-1$ //$NON-NLS-2$
insertPointsScript = "INSERT INTO " + POINT_NAME + " VALUES (?, ?, ?, ?, ?, ?, ?)"; //$NON-NLS-1$ //$NON-NLS-2$
insertPointsScript = "INSERT INTO " + POINT_NAME + " (" + POINT_COL_LAT + ", " + POINT_COL_LON + ", "
+ POINT_COL_DATE + ", " + POINT_COL_DESCRIPTION + ", " + POINT_COL_NAME + ", "
+ POINT_COL_CATEGORY + ", " + POINT_COL_COLOR + ", " + POINT_COL_ICON + ", "
+ POINT_COL_BACKGROUND + ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"; //$NON-NLS-1$ //$NON-NLS-2$
}
@Override
@ -112,7 +117,7 @@ public class SavingTrackHelper extends SQLiteOpenHelper {
try {
db.execSQL("CREATE TABLE " + POINT_NAME + " (" + POINT_COL_LAT + " double, " + POINT_COL_LON + " double, " //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ POINT_COL_DATE + " long, " + POINT_COL_DESCRIPTION + " text, " + POINT_COL_NAME + " text, "
+ POINT_COL_CATEGORY + " text, " + POINT_COL_COLOR + " long" + ")"); //$NON-NLS-1$ //$NON-NLS-2$
+ POINT_COL_CATEGORY + " text, " + POINT_COL_COLOR + " long, " + POINT_COL_ICON + " text, " + POINT_COL_BACKGROUND + " text )"); //$NON-NLS-1$ //$NON-NLS-2$
} catch (RuntimeException e) {
// ignore if already exists
}
@ -136,6 +141,10 @@ public class SavingTrackHelper extends SQLiteOpenHelper {
if (oldVersion < 6) {
db.execSQL("ALTER TABLE " + TRACK_NAME + " ADD " + TRACK_COL_HEADING + " float");
}
if (oldVersion < 7) {
db.execSQL("ALTER TABLE " + POINT_NAME + " ADD " + POINT_COL_ICON + " text");
db.execSQL("ALTER TABLE " + POINT_NAME + " ADD " + POINT_COL_BACKGROUND + " text");
}
}
@ -294,7 +303,8 @@ public class SavingTrackHelper extends SQLiteOpenHelper {
private void collectDBPoints(SQLiteDatabase db, Map<String, GPXFile> dataTracks) {
Cursor query = db.rawQuery("SELECT " + POINT_COL_LAT + "," + POINT_COL_LON + "," + POINT_COL_DATE + "," //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ POINT_COL_DESCRIPTION + "," + POINT_COL_NAME + "," + POINT_COL_CATEGORY + "," + POINT_COL_COLOR + " FROM " + POINT_NAME+" ORDER BY " + POINT_COL_DATE +" ASC", null); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ POINT_COL_DESCRIPTION + "," + POINT_COL_NAME + "," + POINT_COL_CATEGORY + "," + POINT_COL_COLOR + ","
+ POINT_COL_ICON + "," + POINT_COL_BACKGROUND + " FROM " + POINT_NAME + " ORDER BY " + POINT_COL_DATE + " ASC", null); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
if (query.moveToFirst()) {
do {
WptPt pt = new WptPt();
@ -309,6 +319,8 @@ public class SavingTrackHelper extends SQLiteOpenHelper {
if (color != 0) {
pt.setColor(color);
}
pt.setIconName(query.getString(7));
pt.setBackgroundType(query.getString(8));
// check if name is extension (needed for audio/video plugin & josm integration)
if (pt.name != null && pt.name.length() > 4 && pt.name.charAt(pt.name.length() - 4) == '.') {
@ -370,7 +382,7 @@ public class SavingTrackHelper extends SQLiteOpenHelper {
if (!newInterval) {
segment.points.add(pt);
}
String date = new SimpleDateFormat("yyyy-MM-dd", Locale.US).format(new Date(time));; //$NON-NLS-1$
String date = new SimpleDateFormat("yyyy-MM-dd", Locale.US).format(new Date(time)); //$NON-NLS-1$
if (dataTracks.containsKey(date)) {
GPXFile gpx = dataTracks.get(date);
gpx.tracks.add(track);
@ -529,7 +541,7 @@ public class SavingTrackHelper extends SQLiteOpenHelper {
ctx.getSelectedGpxHelper().addPoint(pt, currentTrack.getModifiableGpxFile());
currentTrack.getModifiableGpxFile().modifiedTime = time;
points++;
execWithClose(insertPointsScript, new Object[] { lat, lon, time, description, name, category, color });
execWithClose(insertPointsScript, new Object[]{lat, lon, time, description, name, category, color, iconName, backgroundName});
return pt;
}
@ -549,6 +561,8 @@ public class SavingTrackHelper extends SQLiteOpenHelper {
params.add(name);
params.add(category);
params.add(color);
params.add(iconName);
params.add(iconBackground);
params.add(pt.getLatitude());
params.add(pt.getLongitude());
@ -563,7 +577,9 @@ public class SavingTrackHelper extends SQLiteOpenHelper {
+ POINT_COL_DESCRIPTION + "=?, "
+ POINT_COL_NAME + "=?, "
+ POINT_COL_CATEGORY + "=?, "
+ POINT_COL_COLOR + "=? "
+ POINT_COL_COLOR + "=?, "
+ POINT_COL_ICON + "=?, "
+ POINT_COL_BACKGROUND + "=? "
+ "WHERE "
+ POINT_COL_LAT + "=? AND "
+ POINT_COL_LON + "=? AND "

View file

@ -33,6 +33,7 @@ public class UploadPhotoProgressBottomSheet extends MenuBottomSheetDialogFragmen
private int progress;
private int maxProgress;
private boolean uploadingFinished;
@Override
public void createMenuItems(Bundle savedInstanceState) {
@ -44,17 +45,12 @@ public class UploadPhotoProgressBottomSheet extends MenuBottomSheetDialogFragmen
uploadedPhotosCounter = view.findViewById(R.id.description);
progressBar = view.findViewById(R.id.progress_bar);
progressBar.setMax(maxProgress);
String titleProgress = getString(progress == maxProgress? R.string.upload_photo_completed: R.string.upload_photo);
String descriptionProgress;
if (progress == maxProgress) {
descriptionProgress = getString(R.string.uploaded_count, progress, maxProgress);
} else {
descriptionProgress = getString(R.string.uploading_count, progress, maxProgress);
}
int descriptionId = uploadingFinished ? R.string.uploaded_count : R.string.uploading_count;
BaseBottomSheetItem descriptionItem = new BottomSheetItemWithDescription.Builder()
.setDescription(descriptionProgress)
.setTitle(titleProgress)
.setDescription(getString(descriptionId, progress, maxProgress))
.setTitle(getString(uploadingFinished ? R.string.upload_photo_completed : R.string.upload_photo))
.setCustomView(view)
.create();
items.add(descriptionItem);
@ -74,9 +70,10 @@ public class UploadPhotoProgressBottomSheet extends MenuBottomSheetDialogFragmen
}
private void updateProgress(int progress) {
int descriptionId = uploadingFinished ? R.string.uploaded_count : R.string.uploading_count;
progressBar.setProgress(progress);
uploadedPhotosCounter.setText((getString(R.string.uploading_count, progress, maxProgress)));
uploadedPhotosTitle.setText(progress == maxProgress ? R.string.upload_photo_completed : R.string.upload_photo);
uploadedPhotosCounter.setText(getString(descriptionId, progress, maxProgress));
uploadedPhotosTitle.setText(uploadingFinished ? R.string.upload_photo_completed : R.string.upload_photo);
}
@Override
@ -87,13 +84,10 @@ public class UploadPhotoProgressBottomSheet extends MenuBottomSheetDialogFragmen
@Override
public void uploadPhotosFinished() {
updateProgress(maxProgress);
if (progress == maxProgress) {
uploadedPhotosCounter.setText((getString(R.string.uploaded_count, progress, maxProgress)));
setDismissButtonTextId(R.string.shared_string_close);
uploadingFinished = true;
updateProgress(progress);
UiUtilities.setupDialogButton(nightMode, dismissButton, getDismissButtonType(), getDismissButtonTextId());
}
}
@Override
public void onDismiss(@NonNull DialogInterface dialog) {
@ -104,6 +98,11 @@ public class UploadPhotoProgressBottomSheet extends MenuBottomSheetDialogFragmen
}
}
@Override
protected int getDismissButtonTextId() {
return uploadingFinished ? R.string.shared_string_close : R.string.shared_string_cancel;
}
public static UploadPhotosListener showInstance(@NonNull FragmentManager fragmentManager, int maxProgress, OnDismissListener listener) {
UploadPhotoProgressBottomSheet fragment = new UploadPhotoProgressBottomSheet();
fragment.setRetainInstance(true);

View file

@ -292,10 +292,6 @@ public class DownloadActivityType {
public IndexItem parseIndexItem(OsmandApplication ctx, XmlPullParser parser) {
if (TRAVEL_FILE == this && !Version.isDeveloperVersion(ctx)) {
//todo remove "if" when .travel.obf will be used in production
return null;
}
String name = parser.getAttributeValue(null, "name"); //$NON-NLS-1$
if (!isAccepted(name)) {
return null;

View file

@ -102,7 +102,7 @@ class SettingsImportTask extends BaseLoadAsyncTask<Void, Void, String> {
}
} else {
Map<ExportSettingsType, List<?>> allSettingsMap = getSettingsToOperate(pluginIndependentItems, false);
List<SettingsItem> settingsList = settingsHelper.getFilteredSettingsItems(allSettingsMap, settingsTypes, false);
List<SettingsItem> settingsList = settingsHelper.getFilteredSettingsItems(allSettingsMap, settingsTypes, pluginIndependentItems, false);
settingsHelper.checkDuplicates(file, settingsList, settingsList, getDuplicatesListener(file, replace));
}
}

View file

@ -421,7 +421,7 @@ public class MenuBuilder {
new Thread(new Runnable() {
@Override
public void run() {
if (openDBAPI.checkPrivateKeyValid(baseUrl, name, privateKey)) {
if (openDBAPI.checkPrivateKeyValid(app, baseUrl, name, privateKey)) {
app.runInUIThread(new Runnable() {
@Override
public void run() {

View file

@ -34,6 +34,7 @@ import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@ -45,14 +46,13 @@ public class UploadPhotosAsyncTask extends AsyncTask<Void, Integer, Void> {
private final OsmandApplication app;
private final WeakReference<MapActivity> activityRef;
private UploadPhotosListener listener;
private final OpenDBAPI openDBAPI = new OpenDBAPI();
private final LatLon latLon;
private final List<Uri> data;
private final String[] placeId;
private final Map<String, String> params;
private final GetImageCardsListener imageCardListener;
private UploadPhotosListener listener;
public UploadPhotosAsyncTask(MapActivity activity, List<Uri> data, LatLon latLon, String[] placeId,
Map<String, String> params, GetImageCardsListener imageCardListener) {
@ -87,13 +87,16 @@ public class UploadPhotosAsyncTask extends AsyncTask<Void, Integer, Void> {
}
protected Void doInBackground(Void... uris) {
List<Uri> uploadedPhotoUris = new ArrayList<>();
for (int i = 0; i < data.size(); i++) {
if (isCancelled()) {
break;
}
Uri uri = data.get(i);
handleSelectedImage(uri);
publishProgress(i + 1);
if (handleSelectedImage(uri)) {
uploadedPhotoUris.add(uri);
publishProgress(uploadedPhotoUris.size());
}
}
return null;
}
@ -105,12 +108,13 @@ public class UploadPhotosAsyncTask extends AsyncTask<Void, Integer, Void> {
}
}
private void handleSelectedImage(final Uri uri) {
private boolean handleSelectedImage(final Uri uri) {
boolean success = false;
InputStream inputStream = null;
try {
inputStream = app.getContentResolver().openInputStream(uri);
if (inputStream != null) {
uploadImageToPlace(inputStream);
success = uploadImageToPlace(inputStream);
}
} catch (Exception e) {
LOG.error(e);
@ -118,11 +122,13 @@ public class UploadPhotosAsyncTask extends AsyncTask<Void, Integer, Void> {
} finally {
Algorithms.closeStream(inputStream);
}
return success;
}
private void uploadImageToPlace(InputStream image) {
private boolean uploadImageToPlace(InputStream image) {
boolean success = false;
InputStream serverData = new ByteArrayInputStream(compressImageToJpeg(image));
final String baseUrl = OPRConstants.getBaseUrl(app);
String baseUrl = OPRConstants.getBaseUrl(app);
// all these should be constant
String url = baseUrl + "api/ipfs/image";
String response = NetworkUtils.sendPostDataRequest(url, "file", "compressed.jpeg", serverData);
@ -131,17 +137,15 @@ public class UploadPhotosAsyncTask extends AsyncTask<Void, Integer, Void> {
try {
StringBuilder error = new StringBuilder();
String privateKey = app.getSettings().OPR_ACCESS_TOKEN.get();
String username = app.getSettings().OPR_USERNAME.get();
String name = app.getSettings().OPR_BLOCKCHAIN_NAME.get();
res = openDBAPI.uploadImage(
placeId,
baseUrl,
privateKey,
username,
name,
response, error);
if (res != 200) {
app.showToastMessage(error.toString());
} else {
//ok, continue
}
} catch (FailedVerificationException e) {
LOG.error(e);
@ -151,6 +155,7 @@ public class UploadPhotosAsyncTask extends AsyncTask<Void, Integer, Void> {
//image was uploaded but not added to blockchain
checkTokenAndShowScreen();
} else {
success = true;
String str = app.getString(R.string.successfully_uploaded_pattern, 1, 1);
app.showToastMessage(str);
//refresh the image
@ -163,6 +168,7 @@ public class UploadPhotosAsyncTask extends AsyncTask<Void, Integer, Void> {
} else {
checkTokenAndShowScreen();
}
return success;
}
//This method runs on non main thread
@ -170,7 +176,7 @@ public class UploadPhotosAsyncTask extends AsyncTask<Void, Integer, Void> {
String baseUrl = OPRConstants.getBaseUrl(app);
String name = app.getSettings().OPR_USERNAME.get();
String privateKey = app.getSettings().OPR_ACCESS_TOKEN.get();
if (openDBAPI.checkPrivateKeyValid(baseUrl, name, privateKey)) {
if (openDBAPI.checkPrivateKeyValid(app, baseUrl, name, privateKey)) {
app.showToastMessage(R.string.cannot_upload_image);
} else {
app.runInUIThread(new Runnable() {

View file

@ -43,7 +43,9 @@ public class SelectedGpxMenuController extends MenuController {
@Override
public void buttonPressed() {
mapContextMenu.hide(false);
TrackMenuFragment.showInstance(mapActivity, selectedGpxPoint.getSelectedGpxFile());
WptPt wptPt = selectedGpxPoint.selectedPoint;
LatLon latLon = new LatLon(wptPt.lat, wptPt.lon);
TrackMenuFragment.showInstance(mapActivity, selectedGpxPoint.getSelectedGpxFile(), latLon);
}
};
leftTitleButtonController.caption = mapActivity.getString(R.string.shared_string_open_track);

View file

@ -7,6 +7,7 @@ import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.MarginLayoutParams;
import android.widget.ImageView;
import android.widget.TextView;
@ -35,6 +36,7 @@ import net.osmand.plus.OsmAndFormatter;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.UiUtilities;
import net.osmand.plus.UiUtilities.CustomRadioButtonType;
import net.osmand.plus.helpers.AndroidUiHelper;
import net.osmand.plus.helpers.GpxUiHelper;
import net.osmand.plus.helpers.GpxUiHelper.GPXDataSetAxisType;
@ -42,7 +44,6 @@ import net.osmand.plus.helpers.GpxUiHelper.GPXDataSetType;
import net.osmand.plus.helpers.GpxUiHelper.LineGraphType;
import net.osmand.plus.helpers.GpxUiHelper.OrderedLineDataSet;
import net.osmand.plus.track.TrackDisplayHelper;
import net.osmand.plus.views.controls.PagerSlidingTabStrip;
import net.osmand.plus.views.controls.PagerSlidingTabStrip.CustomTabProvider;
import net.osmand.plus.views.controls.WrapContentHeightViewPager.ViewAtPositionInterface;
import net.osmand.util.Algorithms;
@ -51,6 +52,7 @@ import net.osmand.util.MapUtils;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
@ -72,23 +74,23 @@ public class GPXItemPagerAdapter extends PagerAdapter implements CustomTabProvid
private GpxDisplayItem gpxItem;
private GPXTabItemType[] tabTypes;
private PagerSlidingTabStrip tabs;
private SparseArray<View> views = new SparseArray<>();
private SegmentActionsListener actionsListener;
private boolean chartClicked;
private boolean nightMode;
public GPXItemPagerAdapter(@NonNull PagerSlidingTabStrip tabs,
public GPXItemPagerAdapter(@NonNull OsmandApplication app,
@NonNull GpxDisplayItem gpxItem,
@NonNull TrackDisplayHelper displayHelper,
@NonNull SegmentActionsListener actionsListener) {
boolean nightMode, @NonNull SegmentActionsListener actionsListener) {
super();
this.tabs = tabs;
this.app = app;
this.gpxItem = gpxItem;
this.nightMode = nightMode;
this.displayHelper = displayHelper;
this.actionsListener = actionsListener;
app = (OsmandApplication) tabs.getContext().getApplicationContext();
iconsCache = app.getUIUtilities();
fetchTabTypes();
}
@ -556,40 +558,64 @@ public class GPXItemPagerAdapter extends PagerAdapter implements CustomTabProvid
return view == object;
}
int singleTabLayoutId[] = {R.layout.center_button_container};
int doubleTabsLayoutIds[] = {R.layout.left_button_container, R.layout.right_button_container};
int tripleTabsLayoutIds[] = {R.layout.left_button_container, R.layout.center_button_container, R.layout.right_button_container};
@Override
public View getCustomTabView(@NonNull ViewGroup parent, int position) {
View tab = LayoutInflater.from(parent.getContext()).inflate(R.layout.gpx_tab, parent, false);
int layoutId;
int count = getCount();
if (count == 1) {
layoutId = singleTabLayoutId[position];
} else if (count == 2) {
layoutId = doubleTabsLayoutIds[position];
} else {
layoutId = tripleTabsLayoutIds[position];
}
ViewGroup tab = (ViewGroup) UiUtilities.getInflater(parent.getContext(), nightMode).inflate(layoutId, parent, false);
tab.setTag(tabTypes[position].name());
deselect(tab);
TextView title = (TextView) tab.getChildAt(0);
if (title != null) {
title.setText(getPageTitle(position));
}
return tab;
}
@Override
public void select(View tab) {
GPXTabItemType tabType = GPXTabItemType.valueOf((String) tab.getTag());
ImageView img = tab.findViewById(R.id.tab_image);
switch (tabs.getTabSelectionType()) {
case ALPHA:
img.setAlpha(tabs.getTabTextSelectedAlpha());
break;
case SOLID_COLOR:
img.setImageDrawable(iconsCache.getPaintedIcon(tabType.getIconId(), tabs.getTextColor()));
break;
}
int index = Arrays.asList(tabTypes).indexOf(tabType);
View parent = (View) tab.getParent();
UiUtilities.updateCustomRadioButtons(app, parent, nightMode, getCustomRadioButtonType(index));
}
@Override
public void deselect(View tab) {
GPXTabItemType tabType = GPXTabItemType.valueOf((String) tab.getTag());
ImageView img = tab.findViewById(R.id.tab_image);
switch (tabs.getTabSelectionType()) {
case ALPHA:
img.setAlpha(tabs.getTabTextAlpha());
break;
case SOLID_COLOR:
img.setImageDrawable(iconsCache.getPaintedIcon(tabType.getIconId(), tabs.getTabInactiveTextColor()));
break;
}
@Override
public void tabStylesUpdated(View tabsContainer, int currentPosition) {
ViewGroup.MarginLayoutParams params = (MarginLayoutParams) tabsContainer.getLayoutParams();
params.height = app.getResources().getDimensionPixelSize(R.dimen.dialog_button_height);
tabsContainer.setLayoutParams(params);
UiUtilities.updateCustomRadioButtons(app, tabsContainer, nightMode, getCustomRadioButtonType(currentPosition));
}
private CustomRadioButtonType getCustomRadioButtonType(int index) {
int count = getCount();
CustomRadioButtonType type = CustomRadioButtonType.CENTER;
if (count == 2) {
type = index > 0 ? CustomRadioButtonType.END : CustomRadioButtonType.START;
} else if (count == 3) {
if (index == 0) {
type = CustomRadioButtonType.START;
} else if (index == 2) {
type = CustomRadioButtonType.END;
}
}
return type;
}
@Override

View file

@ -6,7 +6,6 @@ import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import net.osmand.AndroidUtils;
import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem;
@ -56,7 +55,7 @@ public class SegmentGPXAdapter extends ArrayAdapter<GpxDisplayItem> {
WrapContentHeightViewPager pager = row.findViewById(R.id.pager);
PagerSlidingTabStrip tabLayout = row.findViewById(R.id.sliding_tabs);
pager.setAdapter(new GPXItemPagerAdapter(tabLayout, item, displayHelper, listener));
pager.setAdapter(new GPXItemPagerAdapter(app, item, displayHelper, nightMode, listener));
if (create) {
tabLayout.setViewPager(pager);
} else {
@ -72,15 +71,8 @@ public class SegmentGPXAdapter extends ArrayAdapter<GpxDisplayItem> {
View row = UiUtilities.getInflater(context, nightMode).inflate(R.layout.gpx_list_item_tab_content, root, false);
PagerSlidingTabStrip tabLayout = row.findViewById(R.id.sliding_tabs);
tabLayout.setTabBackground(R.color.color_transparent);
tabLayout.setIndicatorColorResource(nightMode ? R.color.active_color_primary_dark : R.color.active_color_primary_light);
tabLayout.setIndicatorBgColorResource(nightMode ? R.color.divider_color_dark : R.color.divider_color_light);
tabLayout.setIndicatorHeight(AndroidUtils.dpToPx(context, 1f));
if (!nightMode) {
tabLayout.setTextColor(tabLayout.getIndicatorColor());
tabLayout.setTabInactiveTextColor(ContextCompat.getColor(row.getContext(), R.color.text_color_secondary_light));
}
tabLayout.setTextSize(AndroidUtils.spToPx(context, 12f));
tabLayout.setTabBackground(AndroidUtils.resolveAttribute(context, R.attr.btn_bg_border_inactive));
tabLayout.setIndicatorHeight(0);
tabLayout.setShouldExpand(true);
WrapContentHeightViewPager pager = row.findViewById(R.id.pager);
pager.setSwipeable(false);

View file

@ -9,6 +9,7 @@ import net.osmand.osm.io.NetworkUtils;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.Version;
import net.osmand.plus.onlinerouting.engine.OnlineRoutingEngine;
import net.osmand.plus.onlinerouting.engine.OnlineRoutingEngine.OnlineRoutingResponse;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.util.Algorithms;
@ -82,12 +83,12 @@ public class OnlineRoutingHelper {
}
@Nullable
public OnlineRoutingResponse calculateRouteOnline(@NonNull OnlineRoutingEngine engine,
private OnlineRoutingResponse calculateRouteOnline(@NonNull OnlineRoutingEngine engine,
@NonNull List<LatLon> path,
boolean leftSideNavigation) throws IOException, JSONException {
String url = engine.getFullUrl(path);
String content = makeRequest(url);
return engine.parseServerResponse(content, leftSideNavigation);
return engine.parseServerResponse(content, app, leftSideNavigation);
}
@NonNull

View file

@ -1,24 +0,0 @@
package net.osmand.plus.onlinerouting;
import net.osmand.Location;
import net.osmand.plus.routing.RouteDirectionInfo;
import java.util.List;
public class OnlineRoutingResponse {
private List<Location> route;
private List<RouteDirectionInfo> directions;
public OnlineRoutingResponse(List<Location> route, List<RouteDirectionInfo> directions) {
this.route = route;
this.directions = directions;
}
public List<Location> getRoute() {
return route;
}
public List<RouteDirectionInfo> getDirections() {
return directions;
}
}

View file

@ -5,9 +5,9 @@ import androidx.annotation.Nullable;
import net.osmand.Location;
import net.osmand.data.LatLon;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.onlinerouting.EngineParameter;
import net.osmand.plus.onlinerouting.OnlineRoutingResponse;
import net.osmand.plus.onlinerouting.VehicleType;
import net.osmand.plus.routing.RouteDirectionInfo;
import net.osmand.router.TurnType;
@ -83,11 +83,9 @@ public class GraphhopperEngine extends OnlineRoutingEngine {
@Nullable
@Override
public OnlineRoutingResponse parseServerResponse(@NonNull String content,
public OnlineRoutingResponse parseServerResponse(@NonNull JSONObject root,
@NonNull OsmandApplication app,
boolean leftSideNavigation) throws JSONException {
JSONObject obj = new JSONObject(content);
JSONObject root = obj.getJSONArray("paths").getJSONObject(0);
String encoded = root.getString("points");
List<LatLon> points = GeoPolylineParserUtil.parse(encoded, GeoPolylineParserUtil.PRECISION_5);
if (isEmpty(points)) return null;
@ -96,25 +94,20 @@ public class GraphhopperEngine extends OnlineRoutingEngine {
JSONArray instructions = root.getJSONArray("instructions");
List<RouteDirectionInfo> directions = new ArrayList<>();
for (int i = 0; i < instructions.length(); i++) {
JSONObject item = instructions.getJSONObject(i);
int sign = Integer.parseInt(item.getString("sign"));
int distance = (int) Math.round(Double.parseDouble(item.getString("distance")));
String description = item.getString("text");
String streetName = item.getString("street_name");
int timeInSeconds = (int) Math.round(Integer.parseInt(item.getString("time")) / 1000f);
JSONArray interval = item.getJSONArray("interval");
JSONObject instruction = instructions.getJSONObject(i);
int distance = (int) Math.round(instruction.getDouble("distance"));
String description = instruction.getString("text");
String streetName = instruction.getString("street_name");
int timeInSeconds = Math.round(instruction.getInt("time") / 1000f);
JSONArray interval = instruction.getJSONArray("interval");
int startPointOffset = interval.getInt(0);
int endPointOffset = interval.getInt(1);
float averageSpeed = (float) distance / timeInSeconds;
TurnType turnType = identifyTurnType(sign, leftSideNavigation);
// TODO turnType.setTurnAngle()
TurnType turnType = parseTurnType(instruction, leftSideNavigation);
RouteDirectionInfo direction = new RouteDirectionInfo(averageSpeed, turnType);
direction.routePointOffset = startPointOffset;
if (turnType != null && turnType.isRoundAbout()) {
direction.routeEndPointOffset = endPointOffset;
}
direction.setDescriptionRoute(description);
direction.setStreetName(streetName);
direction.setDistance(distance);
@ -123,27 +116,33 @@ public class GraphhopperEngine extends OnlineRoutingEngine {
return new OnlineRoutingResponse(route, directions);
}
@Override
public boolean parseServerMessage(@NonNull StringBuilder sb,
@NonNull String content) throws JSONException {
JSONObject obj = new JSONObject(content);
if (obj.has("message")) {
String message = obj.getString("message");
sb.append(message);
@NonNull
private TurnType parseTurnType(@NonNull JSONObject instruction,
boolean leftSide) throws JSONException {
int sign = instruction.getInt("sign");
TurnType turnType = identifyTurnType(sign, leftSide);
if (turnType == null) {
turnType = TurnType.straight();
} else if (turnType.isRoundAbout()) {
if (instruction.has("exit_number")) {
int exit = instruction.getInt("exit_number");
turnType.setExitOut(exit);
}
return obj.has("paths");
if (instruction.has("turn_angle")) {
float angle = (float) instruction.getDouble("turn_angle");
turnType.setTurnAngle(angle);
}
} else {
// TODO turnType.setTurnAngle()
}
return turnType;
}
/**
* @param sign - a number which specifies the turn type to show (Graphhopper API value)
* @return a TurnType object defined in OsmAnd which is equivalent to a value from the Graphhopper API
*
* For future compatibility it is important that all clients
* are able to handle also unknown instruction sign numbers
*/
@Nullable
public static TurnType identifyTurnType(int sign, boolean leftSide) {
int id = INVALID_ID;
Integer id = null;
if (sign == -98) {
// an U-turn without the knowledge
@ -192,6 +191,7 @@ public class GraphhopperEngine extends OnlineRoutingEngine {
} else if (sign == 4) {
// the finish instruction before the last point
id = TurnType.C;
} else if (sign == 5) {
// the instruction before a via point
@ -209,6 +209,18 @@ public class GraphhopperEngine extends OnlineRoutingEngine {
id = TurnType.TRU;
}
return id != INVALID_ID ? TurnType.valueOf(id, leftSide) : null;
return id != null ? TurnType.valueOf(id, leftSide) : null;
}
@NonNull
@Override
protected String getErrorMessageKey() {
return "message";
}
@NonNull
@Override
protected String getRootArrayKey() {
return "paths";
}
}

View file

@ -8,15 +8,18 @@ import androidx.annotation.Nullable;
import net.osmand.GPXUtilities.WptPt;
import net.osmand.Location;
import net.osmand.data.LatLon;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.onlinerouting.EngineParameter;
import net.osmand.plus.onlinerouting.OnlineRoutingFactory;
import net.osmand.plus.onlinerouting.OnlineRoutingResponse;
import net.osmand.plus.onlinerouting.VehicleType;
import net.osmand.plus.routing.RouteDirectionInfo;
import net.osmand.plus.routing.RouteProvider;
import net.osmand.util.Algorithms;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.Arrays;
@ -33,7 +36,6 @@ public abstract class OnlineRoutingEngine implements Cloneable {
public final static String ONLINE_ROUTING_ENGINE_PREFIX = "online_routing_engine_";
public final static VehicleType CUSTOM_VEHICLE = new VehicleType("", R.string.shared_string_custom);
public final static int INVALID_ID = -1;
private final Map<String, String> params = new HashMap<>();
private final List<VehicleType> allowedVehicles = new ArrayList<>();
@ -98,10 +100,32 @@ public abstract class OnlineRoutingEngine implements Cloneable {
@NonNull
public abstract String getStandardUrl();
public OnlineRoutingResponse parseServerResponse(@NonNull String content,
@NonNull OsmandApplication app,
boolean leftSideNavigation) throws JSONException {
JSONObject root = parseRootResponseObject(content);
return root != null ? parseServerResponse(root, app, leftSideNavigation) : null;
}
@Nullable
public abstract OnlineRoutingResponse parseServerResponse(@NonNull String content,
protected abstract OnlineRoutingResponse parseServerResponse(@NonNull JSONObject root,
@NonNull OsmandApplication app,
boolean leftSideNavigation) throws JSONException;
@Nullable
protected JSONObject parseRootResponseObject(@NonNull String content) throws JSONException {
JSONObject fullJSON = new JSONObject(content);
String responseArrayKey = getRootArrayKey();
JSONArray array = null;
if (fullJSON.has(responseArrayKey)) {
array = fullJSON.getJSONArray(responseArrayKey);
}
return array != null && array.length() > 0 ? array.getJSONObject(0) : null;
}
@NonNull
protected abstract String getRootArrayKey();
@NonNull
protected List<Location> convertRouteToLocationsList(@NonNull List<LatLon> route) {
List<Location> result = new ArrayList<>();
@ -192,8 +216,19 @@ public abstract class OnlineRoutingEngine implements Cloneable {
return CUSTOM_VEHICLE;
}
public abstract boolean parseServerMessage(@NonNull StringBuilder sb,
@NonNull String content) throws JSONException;
public boolean checkServerResponse(@NonNull StringBuilder errorMessage,
@NonNull String content) throws JSONException {
JSONObject obj = new JSONObject(content);
String messageKey = getErrorMessageKey();
if (obj.has(messageKey)) {
String message = obj.getString(messageKey);
errorMessage.append(message);
}
return obj.has(getRootArrayKey());
}
@NonNull
protected abstract String getErrorMessageKey();
@NonNull
@Override
@ -201,11 +236,6 @@ public abstract class OnlineRoutingEngine implements Cloneable {
return OnlineRoutingFactory.createEngine(getType(), getParams());
}
@NonNull
public static String generateKey() {
return ONLINE_ROUTING_ENGINE_PREFIX + System.currentTimeMillis();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
@ -215,4 +245,27 @@ public abstract class OnlineRoutingEngine implements Cloneable {
if (getType() != engine.getType()) return false;
return Algorithms.objectEquals(getParams(), engine.getParams());
}
@NonNull
public static String generateKey() {
return ONLINE_ROUTING_ENGINE_PREFIX + System.currentTimeMillis();
}
public static class OnlineRoutingResponse {
private List<Location> route;
private List<RouteDirectionInfo> directions;
public OnlineRoutingResponse(List<Location> route, List<RouteDirectionInfo> directions) {
this.route = route;
this.directions = directions;
}
public List<Location> getRoute() {
return route;
}
public List<RouteDirectionInfo> getDirections() {
return directions;
}
}
}

View file

@ -5,9 +5,9 @@ import androidx.annotation.Nullable;
import net.osmand.Location;
import net.osmand.data.LatLon;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.onlinerouting.EngineParameter;
import net.osmand.plus.onlinerouting.OnlineRoutingResponse;
import net.osmand.plus.onlinerouting.VehicleType;
import org.json.JSONArray;
@ -80,11 +80,10 @@ public class OrsEngine extends OnlineRoutingEngine {
@Nullable
@Override
public OnlineRoutingResponse parseServerResponse(@NonNull String content,
public OnlineRoutingResponse parseServerResponse(@NonNull JSONObject root,
@NonNull OsmandApplication app,
boolean leftSideNavigation) throws JSONException {
JSONObject obj = new JSONObject(content);
JSONArray array = obj.getJSONArray("features").getJSONObject(0)
.getJSONObject("geometry").getJSONArray("coordinates");
JSONArray array = root.getJSONObject("geometry").getJSONArray("coordinates");
List<LatLon> points = new ArrayList<>();
for (int i = 0; i < array.length(); i++) {
JSONArray point = array.getJSONArray(i);
@ -99,14 +98,15 @@ public class OrsEngine extends OnlineRoutingEngine {
return null;
}
@NonNull
@Override
public boolean parseServerMessage(@NonNull StringBuilder sb,
@NonNull String content) throws JSONException {
JSONObject obj = new JSONObject(content);
if (obj.has("error")) {
String message = obj.getString("error");
sb.append(message);
protected String getErrorMessageKey() {
return "error";
}
return obj.has("features");
@NonNull
@Override
protected String getRootArrayKey() {
return "features";
}
}

View file

@ -5,19 +5,26 @@ import androidx.annotation.Nullable;
import net.osmand.Location;
import net.osmand.data.LatLon;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.onlinerouting.EngineParameter;
import net.osmand.plus.onlinerouting.OnlineRoutingResponse;
import net.osmand.plus.onlinerouting.VehicleType;
import net.osmand.plus.routing.RouteCalculationResult;
import net.osmand.plus.routing.RouteDirectionInfo;
import net.osmand.router.TurnType;
import net.osmand.util.GeoPolylineParserUtil;
import net.osmand.util.MapUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import static net.osmand.util.Algorithms.isEmpty;
import static net.osmand.util.Algorithms.objectEquals;
public class OsrmEngine extends OnlineRoutingEngine {
@ -69,26 +76,162 @@ public class OsrmEngine extends OnlineRoutingEngine {
@Nullable
@Override
public OnlineRoutingResponse parseServerResponse(@NonNull String content,
public OnlineRoutingResponse parseServerResponse(@NonNull JSONObject root,
@NonNull OsmandApplication app,
boolean leftSideNavigation) throws JSONException {
JSONObject obj = new JSONObject(content);
String encoded = obj.getJSONArray("routes").getJSONObject(0).getString("geometry");
List<LatLon> points = GeoPolylineParserUtil.parse(encoded, GeoPolylineParserUtil.PRECISION_5);
if (!isEmpty(points)) {
String encodedPoints = root.getString("geometry");
List<LatLon> points = GeoPolylineParserUtil.parse(encodedPoints, GeoPolylineParserUtil.PRECISION_5);
if (isEmpty(points)) return null;
List<Location> route = convertRouteToLocationsList(points);
return new OnlineRoutingResponse(route, null);
List<RouteDirectionInfo> directions = new ArrayList<>();
int startSearchingId = 0;
JSONArray legs = root.getJSONArray("legs");
for (int i = 0; i < legs.length(); i++) {
JSONObject leg = legs.getJSONObject(i);
if (!leg.has("steps")) continue;
JSONArray steps = leg.getJSONArray("steps");
for (int j = 0; j < steps.length(); j++) {
JSONObject instruction = steps.getJSONObject(j);
JSONObject maneuver = instruction.getJSONObject("maneuver");
String maneuverType = maneuver.getString("type");
JSONArray location = maneuver.getJSONArray("location");
double lon = location.getDouble(0);
double lat = location.getDouble(1);
Integer routePointOffset = getLocationIndexInList(route, startSearchingId, lat, lon);
if (routePointOffset == null) continue;
startSearchingId = routePointOffset;
// in meters
int distance = (int) Math.round(instruction.getDouble("distance"));
// in seconds
int duration = (int) Math.round(instruction.getDouble("duration"));
float averageSpeed = (float) distance / duration;
TurnType turnType = parseTurnType(maneuver, leftSideNavigation);
RouteDirectionInfo direction = new RouteDirectionInfo(averageSpeed, turnType);
direction.setDistance(distance);
String streetName = instruction.getString("name");
String description = "";
if (!objectEquals(maneuverType, "arrive")) {
description = RouteCalculationResult.toString(turnType, app, false) + " " + streetName;
}
description = description.trim();
direction.setStreetName(streetName);
direction.setDescriptionRoute(description);
direction.routePointOffset = routePointOffset;
directions.add(direction);
}
}
return new OnlineRoutingResponse(route, directions);
}
@Nullable
private Integer getLocationIndexInList(@NonNull List<Location> locations,
int startIndex, double lat, double lon) {
for (int i = startIndex; i < locations.size(); i++) {
Location l = locations.get(i);
if (MapUtils.areLatLonEqual(l, lat, lon)) {
return i;
}
}
return null;
}
@NonNull
private TurnType parseTurnType(@NonNull JSONObject maneuver,
boolean leftSide) throws JSONException {
TurnType turnType = null;
String type = maneuver.getString("type");
String modifier = null;
if (maneuver.has("modifier")) {
modifier = maneuver.getString("modifier");
}
if (objectEquals(type, "roundabout")
|| objectEquals(type, "rotary")
|| objectEquals(type, "roundabout turn")) {
if (maneuver.has("exit")) {
int exit = maneuver.getInt("exit");
turnType = TurnType.getExitTurn(exit, 0.0f, leftSide);
} else if (modifier != null) {
// for simple roundabout turn without "exit" parameter
turnType = identifyTurnType(modifier, leftSide);
}
} else {
// for other maneuver types find TurnType
// like a basic turn into direction of the modifier
if (modifier != null) {
turnType = identifyTurnType(modifier, leftSide);
}
}
if (turnType == null) {
turnType = TurnType.straight();
}
int bearingBefore = maneuver.getInt("bearing_before");
int bearingAfter = maneuver.getInt("bearing_after");
float angle = (float) MapUtils.degreesDiff(bearingAfter, bearingBefore);
turnType.setTurnAngle(angle);
return turnType;
}
@Nullable
private TurnType identifyTurnType(@NonNull String modifier,
boolean leftSide) {
Integer id = null;
switch (modifier) {
case "uturn":
id = TurnType.TU;
break;
case "sharp right":
id = TurnType.TSHR;
break;
case "right":
id = TurnType.TR;
break;
case "slight right":
id = TurnType.TSLR;
break;
case "straight":
id = TurnType.C;
break;
case "slight left":
id = TurnType.TSLL;
break;
case "left":
id = TurnType.TL;
break;
case "sharp left":
id = TurnType.TSHL;
break;
}
return id != null ? TurnType.valueOf(id, leftSide) : null;
}
@NonNull
@Override
public boolean parseServerMessage(@NonNull StringBuilder sb,
@NonNull String content) throws JSONException {
JSONObject obj = new JSONObject(content);
if (obj.has("message")) {
String message = obj.getString("message");
sb.append(message);
protected String getErrorMessageKey() {
return "message";
}
return obj.has("routes");
@NonNull
@Override
protected String getRootArrayKey() {
return "routes";
}
}

View file

@ -458,15 +458,15 @@ public class OnlineRoutingEngineFragment extends BaseOsmAndFragment {
new Thread(new Runnable() {
@Override
public void run() {
StringBuilder message = new StringBuilder();
StringBuilder errorMessage = new StringBuilder();
boolean resultOk = false;
try {
String response = helper.makeRequest(exampleCard.getEditedText());
resultOk = requestedEngine.parseServerMessage(message, response);
resultOk = requestedEngine.checkServerResponse(errorMessage, response);
} catch (IOException | JSONException e) {
message.append(e.toString());
errorMessage.append(e.toString());
}
showTestResults(resultOk, message.toString(), location);
showTestResults(resultOk, errorMessage.toString(), location);
}
}).start();
}

View file

@ -3,10 +3,15 @@ package net.osmand.plus.osmedit.opr;
import android.net.TrafficStats;
import android.os.Build;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonSyntaxException;
import com.google.gson.reflect.TypeToken;
import net.osmand.PlatformUtil;
import net.osmand.osm.io.NetworkUtils;
import net.osmand.plus.OsmandApplication;
import net.osmand.util.Algorithms;
import org.apache.commons.logging.Log;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
@ -27,6 +32,7 @@ import java.security.KeyPair;
import java.security.Security;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
@ -40,7 +46,7 @@ public class OpenDBAPI {
public static final String PURPOSE = "osmand-android";
private static final Log log = PlatformUtil.getLog(SecUtils.class);
private static final String checkLoginEndpoint = "api/auth/user-check-loginkey?";
private static final String LOGIN_SUCCESS_MESSAGE = "{\"result\":\"OK\"}";
private static final String LOGIN_SUCCESS_MESSAGE = "\"result\":\"OK\"";
private static final int THREAD_ID = 11200;
/*
@ -51,7 +57,7 @@ public class OpenDBAPI {
* Need to encode key
* Do not call on mainThread
*/
public boolean checkPrivateKeyValid(String baseUrl, String username, String privateKey) {
public boolean checkPrivateKeyValid(OsmandApplication app, String baseUrl, String username, String privateKey) {
String url = null;
try {
String purposeParam = "purpose=" + PURPOSE;
@ -65,9 +71,29 @@ public class OpenDBAPI {
} catch (UnsupportedEncodingException e) {
return false;
}
StringBuilder response = new StringBuilder();
return (NetworkUtils.sendGetRequest(url,null,response) == null) &&
response.toString().contains(LOGIN_SUCCESS_MESSAGE);
String error = NetworkUtils.sendGetRequest(url, null, response);
if (error == null) {
String responseStr = response.toString();
try {
Map<String, String> map = new Gson().fromJson(
responseStr, new TypeToken<HashMap<String, String>>() {
}.getType()
);
if (!Algorithms.isEmpty(map) && map.containsKey("blockchain-name")) {
String blockchainName = map.get("blockchain-name");
app.getSettings().OPR_BLOCKCHAIN_NAME.set(blockchainName);
} else {
return false;
}
} catch (JsonSyntaxException e) {
return false;
}
return responseStr.contains(LOGIN_SUCCESS_MESSAGE);
} else {
return false;
}
}
public int uploadImage(String[] placeId, String baseUrl, String privateKey, String username, String image, StringBuilder sb) throws FailedVerificationException {

View file

@ -711,7 +711,7 @@ public class RouteCalculationResult {
if (directions != null && directions.size() > 1) {
for (int i = 1; i < directions.size();) {
RouteDirectionInfo r = directions.get(i);
if (r.getTurnType() != null && r.getTurnType().getValue() == TurnType.C) {
if (r.getTurnType().getValue() == TurnType.C) {
RouteDirectionInfo prev = directions.get(i - 1);
prev.setAverageSpeed((prev.distance + r.distance)
/ (prev.distance / prev.getAverageSpeed() + r.distance / r.getAverageSpeed()));

View file

@ -21,7 +21,7 @@ import net.osmand.data.LocationPoint;
import net.osmand.data.WptLocationPoint;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.onlinerouting.OnlineRoutingHelper;
import net.osmand.plus.onlinerouting.OnlineRoutingResponse;
import net.osmand.plus.onlinerouting.engine.OnlineRoutingEngine.OnlineRoutingResponse;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.settings.backend.CommonPreference;
import net.osmand.plus.R;
@ -1206,7 +1206,7 @@ public class RouteProvider {
helper.calculateRouteOnline(stringKey, getPathFromParams(params), params.leftSide);
if (response != null) {
params.intermediates = null;
return new RouteCalculationResult(response.getRoute(), response.getDirections(), params, null, true);
return new RouteCalculationResult(response.getRoute(), response.getDirections(), params, null, false);
} else {
return new RouteCalculationResult("Route is empty");
}

View file

@ -1171,6 +1171,9 @@ public class OsmandSettings {
public final OsmandPreference<String> OPR_USERNAME =
new StringPreference(this, "opr_username_secret", "").makeGlobal();
public final OsmandPreference<String> OPR_BLOCKCHAIN_NAME =
new StringPreference(this, "opr_blockchain_name", "").makeGlobal();
// this value boolean is synchronized with settings_pref.xml preference offline POI/Bugs edition
public final OsmandPreference<Boolean> OFFLINE_EDITION = new BooleanPreference(this, "offline_osm_editing", true).makeGlobal().makeShared();
public final OsmandPreference<Boolean> USE_DEV_URL = new BooleanPreference(this, "use_dev_url", false).makeGlobal().makeShared();

View file

@ -480,19 +480,21 @@ public class SettingsHelper {
typesMap.putAll(getMyPlacesItems());
typesMap.putAll(getResourcesItems());
return getFilteredSettingsItems(typesMap, settingsTypes, export);
return getFilteredSettingsItems(typesMap, settingsTypes, Collections.<SettingsItem>emptyList(), export);
}
public List<SettingsItem> getFilteredSettingsItems(Map<ExportSettingsType, List<?>> allSettingsMap,
List<ExportSettingsType> settingsTypes, boolean export) {
List<SettingsItem> settingsItems = new ArrayList<>();
public List<SettingsItem> getFilteredSettingsItems(
Map<ExportSettingsType, List<?>> allSettingsMap, List<ExportSettingsType> settingsTypes,
@NonNull List<SettingsItem> settingsItems, boolean export
) {
List<SettingsItem> filteredSettingsItems = new ArrayList<>();
for (ExportSettingsType settingsType : settingsTypes) {
List<?> settingsDataObjects = allSettingsMap.get(settingsType);
if (settingsDataObjects != null) {
settingsItems.addAll(prepareSettingsItems(settingsDataObjects, export));
filteredSettingsItems.addAll(prepareSettingsItems(settingsDataObjects, settingsItems, export));
}
}
return settingsItems;
return filteredSettingsItems;
}
public Map<ExportSettingsCategory, SettingsCategoryItems> getSettingsByCategory(boolean addProfiles) {
@ -693,8 +695,8 @@ public class SettingsHelper {
return files;
}
public List<SettingsItem> prepareSettingsItems(List<?> data, boolean export) {
List<SettingsItem> settingsItems = new ArrayList<>();
public List<SettingsItem> prepareSettingsItems(List<?> data, List<SettingsItem> settingsItems, boolean export) {
List<SettingsItem> result = new ArrayList<>();
List<QuickAction> quickActions = new ArrayList<>();
List<PoiUIFilter> poiUIFilters = new ArrayList<>();
List<ITileSource> tileSourceTemplates = new ArrayList<>();
@ -719,13 +721,15 @@ public class SettingsHelper {
try {
File file = (File) object;
if (file.getName().endsWith(IndexConstants.GPX_FILE_EXT)) {
settingsItems.add(new GpxSettingsItem(app, file));
result.add(new GpxSettingsItem(app, file));
} else {
settingsItems.add(new FileSettingsItem(app, file));
result.add(new FileSettingsItem(app, file));
}
} catch (IllegalArgumentException e) {
LOG.warn("Trying to export unsuported file type", e);
}
} else if (object instanceof FileSettingsItem) {
result.add((FileSettingsItem) object);
} else if (object instanceof AvoidRoadInfo) {
avoidRoads.add((AvoidRoadInfo) object);
} else if (object instanceof ApplicationModeBean) {
@ -746,65 +750,100 @@ public class SettingsHelper {
} else if (object instanceof HistoryEntry) {
historyEntries.add((HistoryEntry) object);
} else if (object instanceof GlobalSettingsItem) {
settingsItems.add((GlobalSettingsItem) object);
result.add((GlobalSettingsItem) object);
} else if (object instanceof OnlineRoutingEngine) {
onlineRoutingEngines.add((OnlineRoutingEngine) object);
}
}
if (!quickActions.isEmpty()) {
settingsItems.add(new QuickActionsSettingsItem(app, quickActions));
QuickActionsSettingsItem baseItem = getBaseItem(SettingsItemType.QUICK_ACTIONS, QuickActionsSettingsItem.class, settingsItems);
result.add(new QuickActionsSettingsItem(app, baseItem, quickActions));
}
if (!poiUIFilters.isEmpty()) {
settingsItems.add(new PoiUiFiltersSettingsItem(app, poiUIFilters));
PoiUiFiltersSettingsItem baseItem = getBaseItem(SettingsItemType.POI_UI_FILTERS, PoiUiFiltersSettingsItem.class, settingsItems);
result.add(new PoiUiFiltersSettingsItem(app, baseItem, poiUIFilters));
}
if (!tileSourceTemplates.isEmpty()) {
settingsItems.add(new MapSourcesSettingsItem(app, tileSourceTemplates));
MapSourcesSettingsItem baseItem = getBaseItem(SettingsItemType.MAP_SOURCES, MapSourcesSettingsItem.class, settingsItems);
result.add(new MapSourcesSettingsItem(app, baseItem, tileSourceTemplates));
}
if (!avoidRoads.isEmpty()) {
settingsItems.add(new AvoidRoadsSettingsItem(app, avoidRoads));
AvoidRoadsSettingsItem baseItem = getBaseItem(SettingsItemType.AVOID_ROADS, AvoidRoadsSettingsItem.class, settingsItems);
result.add(new AvoidRoadsSettingsItem(app, baseItem, avoidRoads));
}
if (!appModeBeans.isEmpty()) {
for (ApplicationModeBean modeBean : appModeBeans) {
if (export) {
ApplicationMode mode = ApplicationMode.valueOfStringKey(modeBean.stringKey, null);
if (mode != null) {
settingsItems.add(new ProfileSettingsItem(app, mode));
result.add(new ProfileSettingsItem(app, mode));
}
} else {
settingsItems.add(new ProfileSettingsItem(app, null, modeBean));
result.add(new ProfileSettingsItem(app, getBaseProfileSettingsItem(modeBean, settingsItems), modeBean));
}
}
}
if (!osmNotesPointList.isEmpty()) {
settingsItems.add(new OsmNotesSettingsItem(app, osmNotesPointList));
OsmNotesSettingsItem baseItem = getBaseItem(SettingsItemType.OSM_NOTES, OsmNotesSettingsItem.class, settingsItems);
result.add(new OsmNotesSettingsItem(app, baseItem, osmNotesPointList));
}
if (!osmEditsPointList.isEmpty()) {
settingsItems.add(new OsmEditsSettingsItem(app, osmEditsPointList));
OsmEditsSettingsItem baseItem = getBaseItem(SettingsItemType.OSM_EDITS, OsmEditsSettingsItem.class, settingsItems);
result.add(new OsmEditsSettingsItem(app, baseItem, osmEditsPointList));
}
if (!favoriteGroups.isEmpty()) {
settingsItems.add(new FavoritesSettingsItem(app, favoriteGroups));
FavoritesSettingsItem baseItem = getBaseItem(SettingsItemType.FAVOURITES, FavoritesSettingsItem.class, settingsItems);
result.add(new FavoritesSettingsItem(app, baseItem, favoriteGroups));
}
if (!markersGroups.isEmpty()) {
List<MapMarker> mapMarkers = new ArrayList<>();
for (MapMarkersGroup group : markersGroups) {
mapMarkers.addAll(group.getMarkers());
}
settingsItems.add(new MarkersSettingsItem(app, mapMarkers));
MarkersSettingsItem baseItem = getBaseItem(SettingsItemType.ACTIVE_MARKERS, MarkersSettingsItem.class, settingsItems);
result.add(new MarkersSettingsItem(app, baseItem, mapMarkers));
}
if (!markersHistoryGroups.isEmpty()) {
List<MapMarker> mapMarkers = new ArrayList<>();
for (MapMarkersGroup group : markersHistoryGroups) {
mapMarkers.addAll(group.getMarkers());
}
settingsItems.add(new HistoryMarkersSettingsItem(app, mapMarkers));
HistoryMarkersSettingsItem baseItem = getBaseItem(SettingsItemType.HISTORY_MARKERS, HistoryMarkersSettingsItem.class, settingsItems);
result.add(new HistoryMarkersSettingsItem(app, baseItem, mapMarkers));
}
if (!historyEntries.isEmpty()) {
settingsItems.add(new SearchHistorySettingsItem(app, historyEntries));
SearchHistorySettingsItem baseItem = getBaseItem(SettingsItemType.SEARCH_HISTORY, SearchHistorySettingsItem.class, settingsItems);
result.add(new SearchHistorySettingsItem(app, baseItem, historyEntries));
}
if (!onlineRoutingEngines.isEmpty()) {
settingsItems.add(new OnlineRoutingSettingsItem(app, onlineRoutingEngines));
OnlineRoutingSettingsItem baseItem = getBaseItem(SettingsItemType.ONLINE_ROUTING_ENGINES, OnlineRoutingSettingsItem.class, settingsItems);
result.add(new OnlineRoutingSettingsItem(app, baseItem, onlineRoutingEngines));
}
return settingsItems;
return result;
}
@Nullable
private ProfileSettingsItem getBaseProfileSettingsItem(ApplicationModeBean modeBean, List<SettingsItem> settingsItems) {
for (SettingsItem settingsItem : settingsItems) {
if (settingsItem.getType() == SettingsItemType.PROFILE) {
ProfileSettingsItem profileItem = (ProfileSettingsItem) settingsItem;
ApplicationModeBean bean = profileItem.getModeBean();
if (Algorithms.objectEquals(bean.stringKey, modeBean.stringKey) && Algorithms.objectEquals(bean.userProfileName, modeBean.userProfileName)) {
return profileItem;
}
}
}
return null;
}
@Nullable
private <T> T getBaseItem(SettingsItemType settingsItemType, Class<T> clazz, List<SettingsItem> settingsItems) {
for (SettingsItem settingsItem : settingsItems) {
if (settingsItem.getType() == settingsItemType && clazz.isInstance(settingsItem)) {
return clazz.cast(settingsItem);
}
}
return null;
}
public static Map<ExportSettingsCategory, SettingsCategoryItems> getSettingsToOperateByCategory(List<SettingsItem> items, boolean importComplete) {

View file

@ -19,13 +19,13 @@ import net.osmand.plus.base.bottomsheetmenu.BaseBottomSheetItem;
import net.osmand.plus.base.bottomsheetmenu.BottomSheetItemWithDescription;
import net.osmand.plus.base.bottomsheetmenu.simpleitems.TitleItem;
import net.osmand.plus.settings.fragments.BaseSettingsFragment;
import net.osmand.plus.settings.fragments.DataStorageMenuItem;
import net.osmand.plus.settings.datastorage.item.StorageItem;
import org.apache.commons.logging.Log;
import java.io.File;
import static net.osmand.plus.settings.fragments.DataStorageHelper.MANUALLY_SPECIFIED;
import static net.osmand.plus.settings.datastorage.DataStorageHelper.MANUALLY_SPECIFIED;
public class ChangeDataStorageBottomSheet extends BasePreferenceBottomSheet {
@ -39,8 +39,8 @@ public class ChangeDataStorageBottomSheet extends BasePreferenceBottomSheet {
public final static String MOVE_DATA = "move_data";
public final static String CHOSEN_DIRECTORY = "chosen_storage";
private DataStorageMenuItem currentDirectory;
private DataStorageMenuItem newDirectory;
private StorageItem currentDirectory;
private StorageItem newDirectory;
@Override
public void createMenuItems(Bundle savedInstanceState) {
@ -126,11 +126,11 @@ public class ChangeDataStorageBottomSheet extends BasePreferenceBottomSheet {
items.add(baseItem);
}
public void setCurrentDirectory(DataStorageMenuItem currentDirectory) {
public void setCurrentDirectory(StorageItem currentDirectory) {
this.currentDirectory = currentDirectory;
}
public void setNewDirectory(DataStorageMenuItem newDirectory) {
public void setNewDirectory(StorageItem newDirectory) {
this.newDirectory = newDirectory;
}
@ -158,8 +158,8 @@ public class ChangeDataStorageBottomSheet extends BasePreferenceBottomSheet {
return true;
}
public static boolean showInstance(FragmentManager fm, String prefId, DataStorageMenuItem currentDirectory,
DataStorageMenuItem newDirectory, Fragment target, boolean usedOnMap) {
public static boolean showInstance(FragmentManager fm, String prefId, StorageItem currentDirectory,
StorageItem newDirectory, Fragment target, boolean usedOnMap) {
try {
if (fm.findFragmentByTag(TAG) == null) {
Bundle args = new Bundle();

View file

@ -1,8 +1,7 @@
package net.osmand.plus.settings.fragments;
package net.osmand.plus.settings.datastorage;
import android.Manifest;
import android.annotation.SuppressLint;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.drawable.Drawable;
@ -26,7 +25,6 @@ import net.osmand.AndroidUtils;
import net.osmand.FileUtils;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.ProgressImplementation;
import net.osmand.plus.R;
import net.osmand.plus.UiUtilities;
import net.osmand.plus.activities.MapActivity;
@ -34,20 +32,21 @@ import net.osmand.plus.activities.OsmandActionBarActivity;
import net.osmand.plus.download.DownloadActivity;
import net.osmand.plus.settings.bottomsheets.ChangeDataStorageBottomSheet;
import net.osmand.plus.settings.bottomsheets.SelectFolderBottomSheet;
import net.osmand.util.Algorithms;
import net.osmand.plus.settings.datastorage.item.MemoryItem;
import net.osmand.plus.settings.datastorage.item.StorageItem;
import net.osmand.plus.settings.datastorage.task.MoveFilesTask;
import net.osmand.plus.settings.datastorage.task.RefreshUsedMemoryTask;
import net.osmand.plus.settings.datastorage.task.ReloadDataTask;
import net.osmand.plus.settings.fragments.BaseSettingsFragment;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.text.DecimalFormat;
import java.util.ArrayList;
import static net.osmand.plus.settings.fragments.DataStorageHelper.INTERNAL_STORAGE;
import static net.osmand.plus.settings.fragments.DataStorageHelper.MANUALLY_SPECIFIED;
import static net.osmand.plus.settings.fragments.DataStorageHelper.OTHER_MEMORY;
import static net.osmand.plus.settings.fragments.DataStorageHelper.TILES_MEMORY;
import static net.osmand.plus.settings.datastorage.DataStorageHelper.INTERNAL_STORAGE;
import static net.osmand.plus.settings.datastorage.DataStorageHelper.MANUALLY_SPECIFIED;
import static net.osmand.plus.settings.datastorage.DataStorageHelper.OTHER_MEMORY;
import static net.osmand.plus.settings.datastorage.DataStorageHelper.TILES_MEMORY;
import static net.osmand.plus.settings.bottomsheets.ChangeDataStorageBottomSheet.CHOSEN_DIRECTORY;
import static net.osmand.plus.settings.bottomsheets.ChangeDataStorageBottomSheet.MOVE_DATA;
import static net.osmand.plus.settings.bottomsheets.SelectFolderBottomSheet.NEW_PATH;
@ -60,17 +59,17 @@ public class DataStorageFragment extends BaseSettingsFragment implements DataSto
private final static String CHANGE_DIRECTORY_BUTTON = "change_directory";
private final static String OSMAND_USAGE = "osmand_usage";
private ArrayList<DataStorageMenuItem> menuItems;
private ArrayList<DataStorageMemoryItem> memoryItems;
private ArrayList<StorageItem> storageItems;
private ArrayList<MemoryItem> memoryItems;
private ArrayList<CheckBoxPreference> dataStorageRadioButtonsGroup;
private Preference changeButton;
private DataStorageMenuItem currentDataStorage;
private StorageItem currentDataStorage;
private String tmpManuallySpecifiedPath;
private DataStorageHelper dataStorageHelper;
private boolean calculateTilesBtnPressed;
private DataStorageHelper.RefreshMemoryUsedInfo calculateMemoryTask;
private DataStorageHelper.RefreshMemoryUsedInfo calculateTilesMemoryTask;
private RefreshUsedMemoryTask calculateMemoryTask;
private RefreshUsedMemoryTask calculateTilesMemoryTask;
private OsmandApplication app;
private OsmandActionBarActivity activity;
@ -95,11 +94,11 @@ public class DataStorageFragment extends BaseSettingsFragment implements DataSto
return;
}
menuItems = dataStorageHelper.getStorageItems();
storageItems = dataStorageHelper.getStorageItems();
memoryItems = dataStorageHelper.getMemoryInfoItems();
dataStorageRadioButtonsGroup = new ArrayList<>();
for (DataStorageMenuItem item : menuItems) {
for (StorageItem item : storageItems) {
CheckBoxPreference preference = new CheckBoxPreference(activity);
preference.setKey(item.getKey());
preference.setTitle(item.getTitle());
@ -136,7 +135,7 @@ public class DataStorageFragment extends BaseSettingsFragment implements DataSto
Bundle resultData = (Bundle) newValue;
if (resultData.containsKey(ChangeDataStorageBottomSheet.TAG)) {
boolean moveMaps = resultData.getBoolean(MOVE_DATA);
DataStorageMenuItem newDataStorage = resultData.getParcelable(CHOSEN_DIRECTORY);
StorageItem newDataStorage = resultData.getParcelable(CHOSEN_DIRECTORY);
if (newDataStorage != null) {
if (tmpManuallySpecifiedPath != null) {
String directory = tmpManuallySpecifiedPath;
@ -154,9 +153,9 @@ public class DataStorageFragment extends BaseSettingsFragment implements DataSto
if (pathChanged) {
tmpManuallySpecifiedPath = resultData.getString(NEW_PATH);
if (tmpManuallySpecifiedPath != null) {
DataStorageMenuItem manuallySpecified = null;
StorageItem manuallySpecified = null;
try {
manuallySpecified = (DataStorageMenuItem) dataStorageHelper.getManuallySpecified().clone();
manuallySpecified = (StorageItem) dataStorageHelper.getManuallySpecified().clone();
manuallySpecified.setDirectory(tmpManuallySpecifiedPath);
} catch (CloneNotSupportedException e) {
return false;
@ -170,7 +169,7 @@ public class DataStorageFragment extends BaseSettingsFragment implements DataSto
//show necessary dialog
String key = preference.getKey();
if (key != null) {
DataStorageMenuItem newDataStorage = dataStorageHelper.getStorage(key);
StorageItem newDataStorage = dataStorageHelper.getStorage(key);
if (newDataStorage != null) {
if (!currentDataStorage.getKey().equals(newDataStorage.getKey())) {
if (newDataStorage.getType() == OsmandSettings.EXTERNAL_STORAGE_TYPE_DEFAULT
@ -212,7 +211,7 @@ public class DataStorageFragment extends BaseSettingsFragment implements DataSto
final View itemView = holder.itemView;
if (preference instanceof CheckBoxPreference) {
DataStorageMenuItem item = dataStorageHelper.getStorage(key);
StorageItem item = dataStorageHelper.getStorage(key);
if (item != null) {
TextView tvTitle = itemView.findViewById(android.R.id.title);
TextView tvSummary = itemView.findViewById(R.id.summary);
@ -267,7 +266,7 @@ public class DataStorageFragment extends BaseSettingsFragment implements DataSto
TextView tvSummary = itemView.findViewById(R.id.summary);
tvSummary.setText(DataStorageHelper.getFormattedMemoryInfo(totalUsageBytes, memoryUnitsFormats));
} else {
for (DataStorageMemoryItem mi : memoryItems) {
for (MemoryItem mi : memoryItems) {
if (key.equals(mi.getKey())) {
TextView tvMemory = itemView.findViewById(R.id.memory);
String summary = "";
@ -326,7 +325,7 @@ public class DataStorageFragment extends BaseSettingsFragment implements DataSto
}
private void showFolderSelectionDialog() {
DataStorageMenuItem manuallySpecified = dataStorageHelper.getManuallySpecified();
StorageItem manuallySpecified = dataStorageHelper.getManuallySpecified();
if (manuallySpecified != null) {
SelectFolderBottomSheet.showInstance(getFragmentManager(), manuallySpecified.getKey(),
manuallySpecified.getDirectory(), DataStorageFragment.this,
@ -335,11 +334,11 @@ public class DataStorageFragment extends BaseSettingsFragment implements DataSto
}
}
private void moveData(final DataStorageMenuItem currentStorage, final DataStorageMenuItem newStorage) {
private void moveData(final StorageItem currentStorage, final StorageItem newStorage) {
File fromDirectory = new File(currentStorage.getDirectory());
File toDirectory = new File(newStorage.getDirectory());
@SuppressLint("StaticFieldLeak")
MoveFilesToDifferentDirectory task = new MoveFilesToDifferentDirectory(activity, fromDirectory, toDirectory) {
MoveFilesTask task = new MoveFilesTask(activity, fromDirectory, toDirectory) {
@NonNull
@ -405,7 +404,7 @@ public class DataStorageFragment extends BaseSettingsFragment implements DataSto
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
private void confirm(OsmandApplication app, OsmandActionBarActivity activity, DataStorageMenuItem newStorageDirectory, boolean silentRestart) {
private void confirm(OsmandApplication app, OsmandActionBarActivity activity, StorageItem newStorageDirectory, boolean silentRestart) {
String newDirectory = newStorageDirectory.getDirectory();
int type = newStorageDirectory.getType();
File newDirectoryFile = new File(newDirectory);
@ -454,7 +453,7 @@ public class DataStorageFragment extends BaseSettingsFragment implements DataSto
}
protected void reloadData() {
new ReloadData(activity, app).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void) null);
new ReloadDataTask(activity, app).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void) null);
}
@Override
@ -463,204 +462,10 @@ public class DataStorageFragment extends BaseSettingsFragment implements DataSto
}
@Override
public void onFinishUpdating(String taskKey) {
public void onFinishUpdating(String tag) {
updateAllSettings();
if (taskKey != null && taskKey.equals(TILES_MEMORY)) {
if (tag != null && tag.equals(TILES_MEMORY)) {
app.getSettings().OSMAND_USAGE_SPACE.set(dataStorageHelper.getTotalUsedBytes());
}
}
public static class MoveFilesToDifferentDirectory extends AsyncTask<Void, Void, Boolean> {
protected WeakReference<OsmandActionBarActivity> activity;
private WeakReference<Context> context;
private File from;
private File to;
protected ProgressImplementation progress;
private Runnable runOnSuccess;
private int movedCount;
private long movedSize;
private int copiedCount;
private long copiedSize;
private int failedCount;
private long failedSize;
private String exceptionMessage;
public MoveFilesToDifferentDirectory(OsmandActionBarActivity activity, File from, File to) {
this.activity = new WeakReference<>(activity);
this.context = new WeakReference<>((Context) activity);
this.from = from;
this.to = to;
}
public void setRunOnSuccess(Runnable runOnSuccess) {
this.runOnSuccess = runOnSuccess;
}
public int getMovedCount() {
return movedCount;
}
public int getCopiedCount() {
return copiedCount;
}
public int getFailedCount() {
return failedCount;
}
public long getMovedSize() {
return movedSize;
}
public long getCopiedSize() {
return copiedSize;
}
public long getFailedSize() {
return failedSize;
}
@Override
protected void onPreExecute() {
Context ctx = context.get();
if (context == null) {
return;
}
movedCount = 0;
copiedCount = 0;
failedCount = 0;
progress = ProgressImplementation.createProgressDialog(
ctx, ctx.getString(R.string.copying_osmand_files),
ctx.getString(R.string.copying_osmand_files_descr, to.getPath()),
ProgressDialog.STYLE_HORIZONTAL);
}
@Override
protected void onPostExecute(Boolean result) {
Context ctx = context.get();
if (ctx == null) {
return;
}
if (result != null) {
if (result.booleanValue() && runOnSuccess != null) {
runOnSuccess.run();
} else if (!result.booleanValue()) {
Toast.makeText(ctx, ctx.getString(R.string.shared_string_io_error) + ": " + exceptionMessage, Toast.LENGTH_LONG).show();
}
}
try {
if (progress.getDialog().isShowing()) {
progress.getDialog().dismiss();
}
} catch (Exception e) {
//ignored
}
}
private void movingFiles(File f, File t, int depth) throws IOException {
Context ctx = context.get();
if (ctx == null) {
return;
}
if (depth <= 2) {
progress.startTask(ctx.getString(R.string.copying_osmand_one_file_descr, t.getName()), -1);
}
if (f.isDirectory()) {
t.mkdirs();
File[] lf = f.listFiles();
if (lf != null) {
for (int i = 0; i < lf.length; i++) {
if (lf[i] != null) {
movingFiles(lf[i], new File(t, lf[i].getName()), depth + 1);
}
}
}
f.delete();
} else if (f.isFile()) {
if (t.exists()) {
Algorithms.removeAllFiles(t);
}
boolean rnm = false;
long fileSize = f.length();
try {
rnm = f.renameTo(t);
movedCount++;
movedSize += fileSize;
} catch (RuntimeException e) {
}
if (!rnm) {
FileInputStream fin = new FileInputStream(f);
FileOutputStream fout = new FileOutputStream(t);
try {
progress.startTask(ctx.getString(R.string.copying_osmand_one_file_descr, t.getName()), (int) (f.length() / 1024));
Algorithms.streamCopy(fin, fout, progress, 1024);
copiedCount++;
copiedSize += fileSize;
} catch (IOException e) {
failedCount++;
failedSize += fileSize;
} finally {
fin.close();
fout.close();
}
f.delete();
}
}
if (depth <= 2) {
progress.finishTask();
}
}
@Override
protected Boolean doInBackground(Void... params) {
to.mkdirs();
try {
movingFiles(from, to, 0);
} catch (IOException e) {
exceptionMessage = e.getMessage();
return false;
}
return true;
}
}
public static class ReloadData extends AsyncTask<Void, Void, Boolean> {
private WeakReference<Context> ctx;
protected ProgressImplementation progress;
private OsmandApplication app;
public ReloadData(Context ctx, OsmandApplication app) {
this.ctx = new WeakReference<>(ctx);
this.app = app;
}
@Override
protected void onPreExecute() {
Context c = ctx.get();
if (c == null) {
return;
}
progress = ProgressImplementation.createProgressDialog(c, c.getString(R.string.loading_data),
c.getString(R.string.loading_data), ProgressDialog.STYLE_HORIZONTAL);
}
@Override
protected void onPostExecute(Boolean result) {
try {
if (progress.getDialog().isShowing()) {
progress.getDialog().dismiss();
}
} catch (Exception e) {
//ignored
}
}
@Override
protected Boolean doInBackground(Void... params) {
app.getResourceManager().reloadIndexes(progress, new ArrayList<String>());
return true;
}
}
}

View file

@ -0,0 +1,321 @@
package net.osmand.plus.settings.datastorage;
import android.os.Build;
import androidx.annotation.NonNull;
import net.osmand.IndexConstants;
import net.osmand.ValueHolder;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.R;
import net.osmand.plus.settings.datastorage.item.DirectoryItem;
import net.osmand.plus.settings.datastorage.item.DirectoryItem.CheckingType;
import net.osmand.plus.settings.datastorage.item.MemoryItem;
import net.osmand.plus.settings.datastorage.item.StorageItem;
import net.osmand.plus.settings.datastorage.task.RefreshUsedMemoryTask;
import java.io.File;
import java.text.DecimalFormat;
import java.util.ArrayList;
import static net.osmand.IndexConstants.AV_INDEX_DIR;
import static net.osmand.IndexConstants.BACKUP_INDEX_DIR;
import static net.osmand.IndexConstants.GPX_INDEX_DIR;
import static net.osmand.IndexConstants.MAPS_PATH;
import static net.osmand.IndexConstants.ROADS_INDEX_DIR;
import static net.osmand.IndexConstants.SRTM_INDEX_DIR;
import static net.osmand.IndexConstants.TILES_INDEX_DIR;
import static net.osmand.IndexConstants.WIKIVOYAGE_INDEX_DIR;
import static net.osmand.IndexConstants.WIKI_INDEX_DIR;
import static net.osmand.plus.settings.datastorage.item.DirectoryItem.CheckingType.EXTENSIONS;
import static net.osmand.plus.settings.datastorage.item.DirectoryItem.CheckingType.PREFIX;
public class DataStorageHelper {
public final static String INTERNAL_STORAGE = "internal_storage";
public final static String EXTERNAL_STORAGE = "external_storage";
public final static String SHARED_STORAGE = "shared_storage";
public final static String MULTIUSER_STORAGE = "multiuser_storage";
public final static String MANUALLY_SPECIFIED = "manually_specified";
public final static String MAPS_MEMORY = "maps_memory_used";
public final static String TERRAIN_MEMORY = "terrain_memory_used";
public final static String TRACKS_MEMORY = "tracks_memory_used";
public final static String NOTES_MEMORY = "notes_memory_used";
public final static String TILES_MEMORY = "tiles_memory_used";
public final static String OTHER_MEMORY = "other_memory_used";
private OsmandApplication app;
private ArrayList<StorageItem> storageItems = new ArrayList<>();
private StorageItem currentDataStorage;
private StorageItem manuallySpecified;
private ArrayList<MemoryItem> memoryItems = new ArrayList<>();
private MemoryItem mapsMemory;
private MemoryItem terrainMemory;
private MemoryItem tracksMemory;
private MemoryItem notesMemory;
private MemoryItem tilesMemory;
private MemoryItem otherMemory;
private int currentStorageType;
private String currentStoragePath;
public DataStorageHelper(@NonNull OsmandApplication app) {
this.app = app;
prepareData();
}
private void prepareData() {
initStorageItems();
initUsedMemoryItems();
}
private void initStorageItems() {
OsmandSettings settings = app.getSettings();
if (settings.getExternalStorageDirectoryTypeV19() >= 0) {
currentStorageType = settings.getExternalStorageDirectoryTypeV19();
} else {
ValueHolder<Integer> vh = new ValueHolder<Integer>();
if (vh.value != null && vh.value >= 0) {
currentStorageType = vh.value;
} else {
currentStorageType = 0;
}
}
currentStoragePath = settings.getExternalStorageDirectory().getAbsolutePath();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
//internal storage
String path = settings.getInternalAppPath().getAbsolutePath();
File dir = new File(path);
int iconId = R.drawable.ic_action_phone;
StorageItem internalStorageItem = StorageItem.builder()
.setKey(INTERNAL_STORAGE)
.setTitle(app.getString(R.string.storage_directory_internal_app))
.setDirectory(path)
.setDescription(app.getString(R.string.internal_app_storage_description))
.setType(OsmandSettings.EXTERNAL_STORAGE_TYPE_INTERNAL_FILE)
.setIconResId(iconId)
.createItem();
addItem(internalStorageItem);
//shared storage
dir = settings.getDefaultInternalStorage();
path = dir.getAbsolutePath();
iconId = R.drawable.ic_action_phone;
StorageItem sharedStorageItem = StorageItem.builder()
.setKey(SHARED_STORAGE)
.setTitle(app.getString(R.string.storage_directory_shared))
.setDirectory(path)
.setType(OsmandSettings.EXTERNAL_STORAGE_TYPE_DEFAULT)
.setIconResId(iconId)
.createItem();
addItem(sharedStorageItem);
//external storage
File[] externals = app.getExternalFilesDirs(null);
if (externals != null) {
int i = 0;
for (File external : externals) {
if (external != null) {
++i;
dir = external;
path = dir.getAbsolutePath();
iconId = getIconForStorageType(dir);
StorageItem externalStorageItem = StorageItem.builder()
.setKey(EXTERNAL_STORAGE + i)
.setTitle(app.getString(R.string.storage_directory_external) + " " + i)
.setDirectory(path)
.setType(OsmandSettings.EXTERNAL_STORAGE_TYPE_EXTERNAL_FILE)
.setIconResId(iconId)
.createItem();
addItem(externalStorageItem);
}
}
}
//multi user storage
File[] obbDirs = app.getObbDirs();
if (obbDirs != null) {
int i = 0;
for (File obb : obbDirs) {
if (obb != null) {
++i;
dir = obb;
path = dir.getAbsolutePath();
iconId = getIconForStorageType(dir);
StorageItem multiuserStorageItem = StorageItem.builder()
.setKey(MULTIUSER_STORAGE + i)
.setTitle(app.getString(R.string.storage_directory_multiuser) + " " + i)
.setDirectory(path)
.setType(OsmandSettings.EXTERNAL_STORAGE_TYPE_OBB)
.setIconResId(iconId)
.createItem();
addItem(multiuserStorageItem);
}
}
}
}
//manually specified storage
manuallySpecified = StorageItem.builder()
.setKey(MANUALLY_SPECIFIED)
.setTitle(app.getString(R.string.storage_directory_manual))
.setDirectory(currentStoragePath)
.setType(OsmandSettings.EXTERNAL_STORAGE_TYPE_SPECIFIED)
.setIconResId(R.drawable.ic_action_folder)
.createItem();
storageItems.add(manuallySpecified);
if (currentDataStorage == null) {
currentDataStorage = manuallySpecified;
}
}
private void initUsedMemoryItems() {
mapsMemory = MemoryItem.builder()
.setKey(MAPS_MEMORY)
.setExtensions(IndexConstants.BINARY_MAP_INDEX_EXT)
.setDirectories(
createDirectory(MAPS_PATH, false, EXTENSIONS, true),
createDirectory(ROADS_INDEX_DIR, true, EXTENSIONS, true),
createDirectory(WIKI_INDEX_DIR, true, EXTENSIONS, true),
createDirectory(WIKIVOYAGE_INDEX_DIR, true, EXTENSIONS, true),
createDirectory(BACKUP_INDEX_DIR, true, EXTENSIONS, true))
.createItem();
memoryItems.add(mapsMemory);
terrainMemory = MemoryItem.builder()
.setKey(TERRAIN_MEMORY)
.setExtensions(IndexConstants.BINARY_SRTM_MAP_INDEX_EXT)
.setDirectories(
createDirectory(SRTM_INDEX_DIR, true, EXTENSIONS, true),
createDirectory(TILES_INDEX_DIR, false, PREFIX, false))
.setPrefixes("Hillshade", "Slope")
.createItem();
memoryItems.add(terrainMemory);
tracksMemory = MemoryItem.builder()
.setKey(TRACKS_MEMORY)
// .setExtensions(IndexConstants.GPX_FILE_EXT, ".gpx.bz2")
.setDirectories(
createDirectory(GPX_INDEX_DIR, true, EXTENSIONS, true))
.createItem();
memoryItems.add(tracksMemory);
notesMemory = MemoryItem.builder()
.setKey(NOTES_MEMORY)
// .setExtensions("")
.setDirectories(
createDirectory(AV_INDEX_DIR, true, EXTENSIONS, true))
.createItem();
memoryItems.add(notesMemory);
tilesMemory = MemoryItem.builder()
.setKey(TILES_MEMORY)
// .setExtensions("")
.setDirectories(
createDirectory(TILES_INDEX_DIR, true, EXTENSIONS, true))
.createItem();
memoryItems.add(tilesMemory);
otherMemory = MemoryItem.builder()
.setKey(OTHER_MEMORY)
.createItem();
memoryItems.add(otherMemory);
}
public ArrayList<StorageItem> getStorageItems() {
return storageItems;
}
private int getIconForStorageType(File dir) {
return R.drawable.ic_action_folder;
}
public StorageItem getCurrentStorage() {
return currentDataStorage;
}
private void addItem(StorageItem item) {
if (currentStorageType == item.getType() && currentStoragePath.equals(item.getDirectory())) {
currentDataStorage = item;
}
storageItems.add(item);
}
public StorageItem getManuallySpecified() {
return manuallySpecified;
}
public StorageItem getStorage(String key) {
if (storageItems != null && key != null) {
for (StorageItem storageItem : storageItems) {
if (key.equals(storageItem.getKey())) {
return storageItem;
}
}
}
return null;
}
public ArrayList<MemoryItem> getMemoryInfoItems() {
return memoryItems;
}
public RefreshUsedMemoryTask calculateMemoryUsedInfo(UpdateMemoryInfoUIAdapter uiAdapter) {
File rootDir = new File(currentStoragePath);
RefreshUsedMemoryTask task = new RefreshUsedMemoryTask(uiAdapter, otherMemory, rootDir, null, null, OTHER_MEMORY);
task.execute(mapsMemory, terrainMemory, tracksMemory, notesMemory);
return task;
}
public RefreshUsedMemoryTask calculateTilesMemoryUsed(UpdateMemoryInfoUIAdapter listener) {
File rootDir = new File(tilesMemory.getDirectories()[0].getAbsolutePath());
RefreshUsedMemoryTask task = new RefreshUsedMemoryTask(listener, otherMemory, rootDir, null, terrainMemory.getPrefixes(), TILES_MEMORY);
task.execute(tilesMemory);
return task;
}
public long getTotalUsedBytes() {
long total = 0;
if (memoryItems != null && memoryItems.size() > 0) {
for (MemoryItem mi : memoryItems) {
total += mi.getUsedMemoryBytes();
}
return total;
}
return -1;
}
public DirectoryItem createDirectory(@NonNull String relativePath,
boolean processInternalDirectories,
CheckingType checkingType,
boolean addUnmatchedToOtherMemory) {
String path = app.getAppPath(relativePath).getAbsolutePath();
return new DirectoryItem(path, processInternalDirectories, checkingType, addUnmatchedToOtherMemory);
}
public static String getFormattedMemoryInfo(long bytes, String[] formatStrings) {
int type = 0;
double memory = (double) bytes / 1024;
while (memory > 1024 && type < formatStrings.length) {
++type;
memory = memory / 1024;
}
String formattedUsed = new DecimalFormat("#.##").format(memory);
return String.format(formatStrings[type], formattedUsed);
}
public interface UpdateMemoryInfoUIAdapter {
void onMemoryInfoUpdate();
void onFinishUpdating(String tag);
}
}

View file

@ -0,0 +1,40 @@
package net.osmand.plus.settings.datastorage.item;
public class DirectoryItem {
private final String absolutePath;
private final boolean processInternalDirectories;
private final CheckingType checkingType;
private final boolean addUnmatchedToOtherMemory;
public enum CheckingType {
EXTENSIONS,
PREFIX
}
public DirectoryItem(String absolutePath,
boolean processInternalDirectories,
CheckingType checkingType,
boolean addUnmatchedToOtherMemory) {
this.absolutePath = absolutePath;
this.processInternalDirectories = processInternalDirectories;
this.checkingType = checkingType;
this.addUnmatchedToOtherMemory = addUnmatchedToOtherMemory;
}
public String getAbsolutePath() {
return absolutePath;
}
public boolean shouldProcessInternalDirectories() {
return processInternalDirectories;
}
public CheckingType getCheckingType() {
return checkingType;
}
public boolean shouldAddUnmatchedToOtherMemory() {
return addUnmatchedToOtherMemory;
}
}

View file

@ -1,16 +1,18 @@
package net.osmand.plus.settings.fragments;
package net.osmand.plus.settings.datastorage.item;
public class DataStorageMemoryItem {
public final static int EXTENSIONS = 0;
public final static int PREFIX = 1;
public class MemoryItem {
private String key;
private String[] extensions;
private String[] prefixes;
private Directory[] directories;
private final String[] extensions;
private final String[] prefixes;
private final DirectoryItem[] directories;
private long usedMemoryBytes;
private DataStorageMemoryItem(String key, String[] extensions, String[] prefixes, long usedMemoryBytes, Directory[] directories) {
private MemoryItem(String key,
String[] extensions,
String[] prefixes,
long usedMemoryBytes,
DirectoryItem[] directories) {
this.key = key;
this.extensions = extensions;
this.prefixes = prefixes;
@ -42,7 +44,7 @@ public class DataStorageMemoryItem {
return prefixes;
}
public Directory[] getDirectories() {
public DirectoryItem[] getDirectories() {
return directories;
}
@ -54,7 +56,7 @@ public class DataStorageMemoryItem {
private String key;
private String[] extensions;
private String[] prefixes;
private Directory[] directories;
private DirectoryItem[] directories;
private long usedMemoryBytes;
public DataStorageMemoryItemBuilder setKey(String key) {
@ -72,7 +74,7 @@ public class DataStorageMemoryItem {
return this;
}
public DataStorageMemoryItemBuilder setDirectories(Directory ... directories) {
public DataStorageMemoryItemBuilder setDirectories(DirectoryItem... directories) {
this.directories = directories;
return this;
}
@ -82,38 +84,8 @@ public class DataStorageMemoryItem {
return this;
}
public DataStorageMemoryItem createItem() {
return new DataStorageMemoryItem(key, extensions, prefixes, usedMemoryBytes, directories);
}
}
public static class Directory {
private String absolutePath;
private boolean goDeeper;
private int checkingType;
private boolean skipOther;
public Directory(String absolutePath, boolean goDeeper, int checkingType, boolean skipOther) {
this.absolutePath = absolutePath;
this.goDeeper = goDeeper;
this.checkingType = checkingType;
this.skipOther = skipOther;
}
public String getAbsolutePath() {
return absolutePath;
}
public boolean isGoDeeper() {
return goDeeper;
}
public int getCheckingType() {
return checkingType;
}
public boolean isSkipOther() {
return skipOther;
public MemoryItem createItem() {
return new MemoryItem(key, extensions, prefixes, usedMemoryBytes, directories);
}
}
}

View file

@ -1,11 +1,11 @@
package net.osmand.plus.settings.fragments;
package net.osmand.plus.settings.datastorage.item;
import android.os.Parcel;
import android.os.Parcelable;
import androidx.annotation.IdRes;
public class DataStorageMenuItem implements Parcelable, Cloneable {
public class StorageItem implements Parcelable, Cloneable {
private String key;
private int type;
@ -15,8 +15,12 @@ public class DataStorageMenuItem implements Parcelable, Cloneable {
@IdRes
private int iconResId;
private DataStorageMenuItem(String key, int type, String title, String description,
String directory, int iconResId) {
private StorageItem(String key,
int type,
String title,
String description,
String directory,
int iconResId) {
this.key = key;
this.type = type;
this.title = title;
@ -25,7 +29,7 @@ public class DataStorageMenuItem implements Parcelable, Cloneable {
this.iconResId = iconResId;
}
private DataStorageMenuItem(Parcel in) {
private StorageItem(Parcel in) {
key = in.readString();
type = in.readInt();
title = in.readString();
@ -99,16 +103,16 @@ public class DataStorageMenuItem implements Parcelable, Cloneable {
dest.writeString(directory);
}
public static final Parcelable.Creator<DataStorageMenuItem> CREATOR = new Parcelable.Creator<DataStorageMenuItem>() {
public static final Parcelable.Creator<StorageItem> CREATOR = new Parcelable.Creator<StorageItem>() {
@Override
public DataStorageMenuItem createFromParcel(Parcel source) {
return new DataStorageMenuItem(source);
public StorageItem createFromParcel(Parcel source) {
return new StorageItem(source);
}
@Override
public DataStorageMenuItem[] newArray(int size) {
return new DataStorageMenuItem[size];
public StorageItem[] newArray(int size) {
return new StorageItem[size];
}
};
@ -151,14 +155,14 @@ public class DataStorageMenuItem implements Parcelable, Cloneable {
return this;
}
public DataStorageMenuItem createItem() {
return new DataStorageMenuItem(key, type, title, description, directory, iconResId);
public StorageItem createItem() {
return new StorageItem(key, type, title, description, directory, iconResId);
}
}
@Override
public Object clone() throws CloneNotSupportedException {
return DataStorageMenuItem.builder()
return StorageItem.builder()
.setKey(this.key)
.setTitle(this.title)
.setDescription(this.description)

View file

@ -0,0 +1,173 @@
package net.osmand.plus.settings.datastorage.task;
import android.app.ProgressDialog;
import android.content.Context;
import android.os.AsyncTask;
import android.widget.Toast;
import net.osmand.plus.ProgressImplementation;
import net.osmand.plus.R;
import net.osmand.plus.activities.OsmandActionBarActivity;
import net.osmand.util.Algorithms;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.ref.WeakReference;
public class MoveFilesTask extends AsyncTask<Void, Void, Boolean> {
protected WeakReference<OsmandActionBarActivity> activity;
private WeakReference<Context> context;
private File from;
private File to;
protected ProgressImplementation progress;
private Runnable runOnSuccess;
private int movedCount;
private long movedSize;
private int copiedCount;
private long copiedSize;
private int failedCount;
private long failedSize;
private String exceptionMessage;
public MoveFilesTask(OsmandActionBarActivity activity, File from, File to) {
this.activity = new WeakReference<>(activity);
this.context = new WeakReference<>((Context) activity);
this.from = from;
this.to = to;
}
public void setRunOnSuccess(Runnable runOnSuccess) {
this.runOnSuccess = runOnSuccess;
}
public int getMovedCount() {
return movedCount;
}
public int getCopiedCount() {
return copiedCount;
}
public int getFailedCount() {
return failedCount;
}
public long getMovedSize() {
return movedSize;
}
public long getCopiedSize() {
return copiedSize;
}
public long getFailedSize() {
return failedSize;
}
@Override
protected void onPreExecute() {
Context ctx = context.get();
if (context == null) {
return;
}
movedCount = 0;
copiedCount = 0;
failedCount = 0;
progress = ProgressImplementation.createProgressDialog(
ctx, ctx.getString(R.string.copying_osmand_files),
ctx.getString(R.string.copying_osmand_files_descr, to.getPath()),
ProgressDialog.STYLE_HORIZONTAL);
}
@Override
protected void onPostExecute(Boolean result) {
Context ctx = context.get();
if (ctx == null) {
return;
}
if (result != null) {
if (result.booleanValue() && runOnSuccess != null) {
runOnSuccess.run();
} else if (!result.booleanValue()) {
Toast.makeText(ctx, ctx.getString(R.string.shared_string_io_error) + ": " + exceptionMessage, Toast.LENGTH_LONG).show();
}
}
try {
if (progress.getDialog().isShowing()) {
progress.getDialog().dismiss();
}
} catch (Exception e) {
//ignored
}
}
private void movingFiles(File f, File t, int depth) throws IOException {
Context ctx = context.get();
if (ctx == null) {
return;
}
if (depth <= 2) {
progress.startTask(ctx.getString(R.string.copying_osmand_one_file_descr, t.getName()), -1);
}
if (f.isDirectory()) {
t.mkdirs();
File[] lf = f.listFiles();
if (lf != null) {
for (int i = 0; i < lf.length; i++) {
if (lf[i] != null) {
movingFiles(lf[i], new File(t, lf[i].getName()), depth + 1);
}
}
}
f.delete();
} else if (f.isFile()) {
if (t.exists()) {
Algorithms.removeAllFiles(t);
}
boolean rnm = false;
long fileSize = f.length();
try {
rnm = f.renameTo(t);
movedCount++;
movedSize += fileSize;
} catch (RuntimeException e) {
}
if (!rnm) {
FileInputStream fin = new FileInputStream(f);
FileOutputStream fout = new FileOutputStream(t);
try {
progress.startTask(ctx.getString(R.string.copying_osmand_one_file_descr, t.getName()), (int) (f.length() / 1024));
Algorithms.streamCopy(fin, fout, progress, 1024);
copiedCount++;
copiedSize += fileSize;
} catch (IOException e) {
failedCount++;
failedSize += fileSize;
} finally {
fin.close();
fout.close();
}
f.delete();
}
}
if (depth <= 2) {
progress.finishTask();
}
}
@Override
protected Boolean doInBackground(Void... params) {
to.mkdirs();
try {
movingFiles(from, to, 0);
} catch (IOException e) {
exceptionMessage = e.getMessage();
return false;
}
return true;
}
}

View file

@ -0,0 +1,232 @@
package net.osmand.plus.settings.datastorage.task;
import android.os.AsyncTask;
import androidx.annotation.NonNull;
import net.osmand.plus.settings.datastorage.DataStorageHelper.UpdateMemoryInfoUIAdapter;
import net.osmand.plus.settings.datastorage.item.DirectoryItem;
import net.osmand.plus.settings.datastorage.item.DirectoryItem.CheckingType;
import net.osmand.plus.settings.datastorage.item.MemoryItem;
import java.io.File;
import static net.osmand.plus.settings.datastorage.DataStorageFragment.UI_REFRESH_TIME_MS;
import static net.osmand.util.Algorithms.objectEquals;
public class RefreshUsedMemoryTask extends AsyncTask<MemoryItem, Void, Void> {
private final UpdateMemoryInfoUIAdapter uiAdapter;
private final File root;
private final MemoryItem otherMemoryItem;
private final String[] directoriesToSkip;
private final String[] filePrefixesToSkip;
private final String tag;
private long lastRefreshTime;
public RefreshUsedMemoryTask(UpdateMemoryInfoUIAdapter uiAdapter,
MemoryItem otherMemoryItem,
File root,
String[] directoriesToSkip,
String[] filePrefixesToSkip,
String tag) {
this.uiAdapter = uiAdapter;
this.otherMemoryItem = otherMemoryItem;
this.root = root;
this.directoriesToSkip = directoriesToSkip;
this.filePrefixesToSkip = filePrefixesToSkip;
this.tag = tag;
}
@Override
protected Void doInBackground(MemoryItem... items) {
lastRefreshTime = System.currentTimeMillis();
if (root.canRead()) {
calculateMultiTypes(root, items);
}
return null;
}
private void calculateMultiTypes(File rootDir,
MemoryItem... items) {
File[] subFiles = rootDir.listFiles();
if (subFiles != null) {
for (File file : subFiles) {
if (isCancelled()) break;
if (file.isDirectory()) {
if (!shouldSkipDirectory(file)) {
processDirectory(file, items);
}
} else if (file.isFile()) {
if (!shouldSkipFile(file)) {
processFile(rootDir, file, items);
}
}
refreshUI();
}
}
}
private boolean shouldSkipDirectory(@NonNull File dir) {
if (directoriesToSkip != null) {
for (String dirToSkipPath : directoriesToSkip) {
String dirPath = dir.getAbsolutePath();
if (objectEquals(dirPath, dirToSkipPath)) {
return true;
}
}
}
return false;
}
private boolean shouldSkipFile(@NonNull File file) {
if (filePrefixesToSkip != null) {
String fileName = file.getName().toLowerCase();
for (String prefixToAvoid : filePrefixesToSkip) {
String prefix = prefixToAvoid.toLowerCase();
if (fileName.startsWith(prefix)) {
return true;
}
}
}
return false;
}
private void processDirectory(@NonNull File directory,
@NonNull MemoryItem... items) {
String directoryPath = directory.getAbsolutePath();
for (MemoryItem memoryItem : items) {
DirectoryItem[] targetDirectories = memoryItem.getDirectories();
if (targetDirectories != null) {
for (DirectoryItem dir : targetDirectories) {
String allowedDirPath = dir.getAbsolutePath();
boolean isPerfectlyMatch = objectEquals(directoryPath, allowedDirPath);
boolean isParentDirectory = !isPerfectlyMatch && (directoryPath.startsWith(allowedDirPath));
boolean isMatchDirectory = isPerfectlyMatch || isParentDirectory;
if (isPerfectlyMatch) {
calculateMultiTypes(directory, items);
return;
} else if (isParentDirectory && dir.shouldProcessInternalDirectories()) {
calculateMultiTypes(directory, items);
return;
} else if (isMatchDirectory && !dir.shouldAddUnmatchedToOtherMemory()) {
return;
}
}
}
}
// Current directory did not match to any type
otherMemoryItem.addBytes(calculateFolderSize(directory));
}
private void processFile(@NonNull File rootDir,
@NonNull File file,
@NonNull MemoryItem... items) {
for (MemoryItem item : items) {
DirectoryItem[] targetDirectories = item.getDirectories();
if (targetDirectories == null) continue;
String rootDirPath = rootDir.getAbsolutePath();
for (DirectoryItem targetDirectory : targetDirectories) {
String allowedDirPath = targetDirectory.getAbsolutePath();
boolean processInternal = targetDirectory.shouldProcessInternalDirectories();
if (objectEquals(rootDirPath, allowedDirPath)
|| (rootDirPath.startsWith(allowedDirPath) && processInternal)) {
CheckingType checkingType = targetDirectory.getCheckingType();
switch (checkingType) {
case EXTENSIONS: {
if (isSuitableExtension(file, item)) {
item.addBytes(file.length());
return;
}
break;
}
case PREFIX: {
if (isSuitablePrefix(file, item)) {
item.addBytes(file.length());
return;
}
break;
}
}
if (!targetDirectory.shouldAddUnmatchedToOtherMemory()) {
return;
}
}
}
}
// Current file did not match any type
otherMemoryItem.addBytes(file.length());
}
private boolean isSuitableExtension(@NonNull File file,
@NonNull MemoryItem item) {
String[] extensions = item.getExtensions();
if (extensions != null) {
for (String extension : extensions) {
if (file.getAbsolutePath().endsWith(extension)) {
return true;
}
}
}
return extensions == null;
}
private boolean isSuitablePrefix(@NonNull File file,
@NonNull MemoryItem item) {
String[] prefixes = item.getPrefixes();
if (prefixes != null) {
for (String prefix : prefixes) {
if (file.getName().toLowerCase().startsWith(prefix.toLowerCase())) {
return true;
}
}
}
return prefixes == null;
}
private long calculateFolderSize(@NonNull File dir) {
long bytes = 0;
if (dir.isDirectory()) {
File[] files = dir.listFiles();
if (files == null) return 0;
for (File file : files) {
if (isCancelled()) {
break;
}
if (file.isDirectory()) {
bytes += calculateFolderSize(file);
} else if (file.isFile()) {
bytes += file.length();
}
}
}
return bytes;
}
@Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
if (uiAdapter != null) {
uiAdapter.onMemoryInfoUpdate();
}
}
@Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
if (uiAdapter != null) {
uiAdapter.onFinishUpdating(tag);
}
}
private void refreshUI() {
long currentTime = System.currentTimeMillis();
if ((currentTime - lastRefreshTime) > UI_REFRESH_TIME_MS) {
lastRefreshTime = currentTime;
publishProgress();
}
}
}

View file

@ -0,0 +1,50 @@
package net.osmand.plus.settings.datastorage.task;
import android.app.ProgressDialog;
import android.content.Context;
import android.os.AsyncTask;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.ProgressImplementation;
import net.osmand.plus.R;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
public class ReloadDataTask extends AsyncTask<Void, Void, Boolean> {
private WeakReference<Context> ctx;
protected ProgressImplementation progress;
private OsmandApplication app;
public ReloadDataTask(Context ctx, OsmandApplication app) {
this.ctx = new WeakReference<>(ctx);
this.app = app;
}
@Override
protected void onPreExecute() {
Context c = ctx.get();
if (c == null) {
return;
}
progress = ProgressImplementation.createProgressDialog(c, c.getString(R.string.loading_data),
c.getString(R.string.loading_data), ProgressDialog.STYLE_HORIZONTAL);
}
@Override
protected void onPostExecute(Boolean result) {
try {
if (progress.getDialog().isShowing()) {
progress.getDialog().dismiss();
}
} catch (Exception e) {
//ignored
}
}
@Override
protected Boolean doInBackground(Void... params) {
app.getResourceManager().reloadIndexes(progress, new ArrayList<String>());
return true;
}
}

View file

@ -73,6 +73,7 @@ import net.osmand.plus.settings.bottomsheets.ChangeGeneralProfilesPrefBottomShee
import net.osmand.plus.settings.bottomsheets.EditTextPreferenceBottomSheet;
import net.osmand.plus.settings.bottomsheets.MultiSelectPreferencesBottomSheet;
import net.osmand.plus.settings.bottomsheets.SingleSelectPreferenceBottomSheet;
import net.osmand.plus.settings.datastorage.DataStorageFragment;
import net.osmand.plus.settings.preferences.ListPreferenceEx;
import net.osmand.plus.settings.preferences.MultiSelectBooleanPreference;
import net.osmand.plus.settings.preferences.SwitchPreferenceEx;

View file

@ -1,485 +0,0 @@
package net.osmand.plus.settings.fragments;
import android.os.AsyncTask;
import android.os.Build;
import net.osmand.IndexConstants;
import net.osmand.ValueHolder;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.R;
import java.io.File;
import java.text.DecimalFormat;
import java.util.ArrayList;
import static net.osmand.plus.settings.fragments.DataStorageFragment.UI_REFRESH_TIME_MS;
import static net.osmand.plus.settings.fragments.DataStorageMemoryItem.Directory;
import static net.osmand.plus.settings.fragments.DataStorageMemoryItem.EXTENSIONS;
import static net.osmand.plus.settings.fragments.DataStorageMemoryItem.PREFIX;
public class DataStorageHelper {
public final static String INTERNAL_STORAGE = "internal_storage";
public final static String EXTERNAL_STORAGE = "external_storage";
public final static String SHARED_STORAGE = "shared_storage";
public final static String MULTIUSER_STORAGE = "multiuser_storage";
public final static String MANUALLY_SPECIFIED = "manually_specified";
public final static String MAPS_MEMORY = "maps_memory_used";
public final static String SRTM_AND_HILLSHADE_MEMORY = "contour_lines_and_hillshade_memory";
public final static String TRACKS_MEMORY = "tracks_memory_used";
public final static String NOTES_MEMORY = "notes_memory_used";
public final static String TILES_MEMORY = "tiles_memory_used";
public final static String OTHER_MEMORY = "other_memory_used";
private ArrayList<DataStorageMenuItem> menuItems = new ArrayList<>();
private DataStorageMenuItem currentDataStorage;
private DataStorageMenuItem manuallySpecified;
private ArrayList<DataStorageMemoryItem> memoryItems = new ArrayList<>();
private DataStorageMemoryItem mapsMemory;
private DataStorageMemoryItem srtmAndHillshadeMemory;
private DataStorageMemoryItem tracksMemory;
private DataStorageMemoryItem notesMemory;
private DataStorageMemoryItem tilesMemory;
private DataStorageMemoryItem otherMemory;
private int currentStorageType;
private String currentStoragePath;
public DataStorageHelper(OsmandApplication app) {
prepareData(app);
}
private void prepareData(OsmandApplication app) {
if (app == null) {
return;
}
OsmandSettings settings = app.getSettings();
if (settings.getExternalStorageDirectoryTypeV19() >= 0) {
currentStorageType = settings.getExternalStorageDirectoryTypeV19();
} else {
ValueHolder<Integer> vh = new ValueHolder<Integer>();
if (vh.value != null && vh.value >= 0) {
currentStorageType = vh.value;
} else {
currentStorageType = 0;
}
}
currentStoragePath = settings.getExternalStorageDirectory().getAbsolutePath();
String path;
File dir;
int iconId;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
//internal storage
path = settings.getInternalAppPath().getAbsolutePath();
dir = new File(path);
iconId = R.drawable.ic_action_phone;
DataStorageMenuItem internalStorageItem = DataStorageMenuItem.builder()
.setKey(INTERNAL_STORAGE)
.setTitle(app.getString(R.string.storage_directory_internal_app))
.setDirectory(path)
.setDescription(app.getString(R.string.internal_app_storage_description))
.setType(OsmandSettings.EXTERNAL_STORAGE_TYPE_INTERNAL_FILE)
.setIconResId(iconId)
.createItem();
addItem(internalStorageItem);
//shared_storage
dir = settings.getDefaultInternalStorage();
path = dir.getAbsolutePath();
iconId = R.drawable.ic_action_phone;
DataStorageMenuItem sharedStorageItem = DataStorageMenuItem.builder()
.setKey(SHARED_STORAGE)
.setTitle(app.getString(R.string.storage_directory_shared))
.setDirectory(path)
.setType(OsmandSettings.EXTERNAL_STORAGE_TYPE_DEFAULT)
.setIconResId(iconId)
.createItem();
addItem(sharedStorageItem);
//external storage
File[] externals = app.getExternalFilesDirs(null);
if (externals != null) {
int i = 0;
for (File external : externals) {
if (external != null) {
++i;
dir = external;
path = dir.getAbsolutePath();
iconId = getIconForStorageType(dir);
DataStorageMenuItem externalStorageItem = DataStorageMenuItem.builder()
.setKey(EXTERNAL_STORAGE + i)
.setTitle(app.getString(R.string.storage_directory_external) + " " + i)
.setDirectory(path)
.setType(OsmandSettings.EXTERNAL_STORAGE_TYPE_EXTERNAL_FILE)
.setIconResId(iconId)
.createItem();
addItem(externalStorageItem);
}
}
}
//multi user storage
File[] obbDirs = app.getObbDirs();
if (obbDirs != null) {
int i = 0;
for (File obb : obbDirs) {
if (obb != null) {
++i;
dir = obb;
path = dir.getAbsolutePath();
iconId = getIconForStorageType(dir);
DataStorageMenuItem multiuserStorageItem = DataStorageMenuItem.builder()
.setKey(MULTIUSER_STORAGE + i)
.setTitle(app.getString(R.string.storage_directory_multiuser) + " " + i)
.setDirectory(path)
.setType(OsmandSettings.EXTERNAL_STORAGE_TYPE_OBB)
.setIconResId(iconId)
.createItem();
addItem(multiuserStorageItem);
}
}
}
}
//manually specified storage
manuallySpecified = DataStorageMenuItem.builder()
.setKey(MANUALLY_SPECIFIED)
.setTitle(app.getString(R.string.storage_directory_manual))
.setDirectory(currentStoragePath)
.setType(OsmandSettings.EXTERNAL_STORAGE_TYPE_SPECIFIED)
.setIconResId(R.drawable.ic_action_folder)
.createItem();
menuItems.add(manuallySpecified);
if (currentDataStorage == null) {
currentDataStorage = manuallySpecified;
}
initMemoryUsed(app);
}
private void initMemoryUsed(OsmandApplication app) {
mapsMemory = DataStorageMemoryItem.builder()
.setKey(MAPS_MEMORY)
.setExtensions(IndexConstants.BINARY_MAP_INDEX_EXT)
.setDirectories(
new Directory(app.getAppPath(IndexConstants.MAPS_PATH).getAbsolutePath(), false, EXTENSIONS, false),
new Directory(app.getAppPath(IndexConstants.ROADS_INDEX_DIR).getAbsolutePath(), true, EXTENSIONS, false),
new Directory(app.getAppPath(IndexConstants.WIKI_INDEX_DIR).getAbsolutePath(), true, EXTENSIONS, false),
new Directory(app.getAppPath(IndexConstants.WIKIVOYAGE_INDEX_DIR).getAbsolutePath(), true, EXTENSIONS, false),
new Directory(app.getAppPath(IndexConstants.BACKUP_INDEX_DIR).getAbsolutePath(), true, EXTENSIONS, false))
.createItem();
memoryItems.add(mapsMemory);
srtmAndHillshadeMemory = DataStorageMemoryItem.builder()
.setKey(SRTM_AND_HILLSHADE_MEMORY)
.setExtensions(IndexConstants.BINARY_SRTM_MAP_INDEX_EXT)
.setDirectories(
new Directory(app.getAppPath(IndexConstants.SRTM_INDEX_DIR).getAbsolutePath(), true, EXTENSIONS, false),
new Directory(app.getAppPath(IndexConstants.TILES_INDEX_DIR).getAbsolutePath(), false, PREFIX, true))
.setPrefixes("Hillshade")
.createItem();
memoryItems.add(srtmAndHillshadeMemory);
tracksMemory = DataStorageMemoryItem.builder()
.setKey(TRACKS_MEMORY)
// .setExtensions(IndexConstants.GPX_FILE_EXT, ".gpx.bz2")
.setDirectories(
new Directory(app.getAppPath(IndexConstants.GPX_INDEX_DIR).getAbsolutePath(), true, EXTENSIONS, false))
.createItem();
memoryItems.add(tracksMemory);
notesMemory = DataStorageMemoryItem.builder()
.setKey(NOTES_MEMORY)
// .setExtensions("")
.setDirectories(
new Directory(app.getAppPath(IndexConstants.AV_INDEX_DIR).getAbsolutePath(), true, EXTENSIONS, false))
.createItem();
memoryItems.add(notesMemory);
tilesMemory = DataStorageMemoryItem.builder()
.setKey(TILES_MEMORY)
// .setExtensions("")
.setDirectories(
new Directory(app.getAppPath(IndexConstants.TILES_INDEX_DIR).getAbsolutePath(), true, EXTENSIONS, false))
.createItem();
memoryItems.add(tilesMemory);
otherMemory = DataStorageMemoryItem.builder()
.setKey(OTHER_MEMORY)
.createItem();
memoryItems.add(otherMemory);
}
public ArrayList<DataStorageMenuItem> getStorageItems() {
return menuItems;
}
private int getIconForStorageType(File dir) {
return R.drawable.ic_action_folder;
}
public DataStorageMenuItem getCurrentStorage() {
return currentDataStorage;
}
private void addItem(DataStorageMenuItem item) {
if (currentStorageType == item.getType() && currentStoragePath.equals(item.getDirectory())) {
currentDataStorage = item;
}
menuItems.add(item);
}
public DataStorageMenuItem getManuallySpecified() {
return manuallySpecified;
}
public DataStorageMenuItem getStorage(String key) {
if (menuItems != null && key != null) {
for (DataStorageMenuItem menuItem : menuItems) {
if (key.equals(menuItem.getKey())) {
return menuItem;
}
}
}
return null;
}
public int getCurrentType() {
return currentStorageType;
}
public String getCurrentPath() {
return currentStoragePath;
}
public ArrayList<DataStorageMemoryItem> getMemoryInfoItems() {
return memoryItems;
}
public RefreshMemoryUsedInfo calculateMemoryUsedInfo(UpdateMemoryInfoUIAdapter listener) {
File rootDir = new File(currentStoragePath);
RefreshMemoryUsedInfo task = new RefreshMemoryUsedInfo(listener, otherMemory, rootDir, null, null, OTHER_MEMORY);
task.execute(mapsMemory, srtmAndHillshadeMemory, tracksMemory, notesMemory);
return task;
}
public RefreshMemoryUsedInfo calculateTilesMemoryUsed(UpdateMemoryInfoUIAdapter listener) {
File rootDir = new File(tilesMemory.getDirectories()[0].getAbsolutePath());
RefreshMemoryUsedInfo task = new RefreshMemoryUsedInfo(listener, otherMemory, rootDir, null, srtmAndHillshadeMemory.getPrefixes(), TILES_MEMORY);
task.execute(tilesMemory);
return task;
}
public static class RefreshMemoryUsedInfo extends AsyncTask<DataStorageMemoryItem, Void, Void> {
private UpdateMemoryInfoUIAdapter listener;
private File rootDir;
private DataStorageMemoryItem otherMemory;
private String[] directoriesToAvoid;
private String[] prefixesToAvoid;
private String taskKey;
private long lastRefreshTime;
public RefreshMemoryUsedInfo(UpdateMemoryInfoUIAdapter listener, DataStorageMemoryItem otherMemory, File rootDir, String[] directoriesToAvoid, String[] prefixesToAvoid, String taskKey) {
this.listener = listener;
this.otherMemory = otherMemory;
this.rootDir = rootDir;
this.directoriesToAvoid = directoriesToAvoid;
this.prefixesToAvoid = prefixesToAvoid;
this.taskKey = taskKey;
}
@Override
protected Void doInBackground(DataStorageMemoryItem... items) {
lastRefreshTime = System.currentTimeMillis();
if (rootDir.canRead()) {
calculateMultiTypes(rootDir, items);
}
return null;
}
private void calculateMultiTypes(File rootDir, DataStorageMemoryItem... items) {
File[] subFiles = rootDir.listFiles();
for (File file : subFiles) {
if (isCancelled()) {
break;
}
nextFile : {
if (file.isDirectory()) {
//check current directory should be avoid
if (directoriesToAvoid != null) {
for (String directoryToAvoid : directoriesToAvoid) {
if (file.getAbsolutePath().equals(directoryToAvoid)) {
break nextFile;
}
}
}
//check current directory matched items type
for (DataStorageMemoryItem item : items) {
Directory[] directories = item.getDirectories();
if (directories == null) {
continue;
}
for (Directory dir : directories) {
if (file.getAbsolutePath().equals(dir.getAbsolutePath())
|| (file.getAbsolutePath().startsWith(dir.getAbsolutePath()))) {
if (dir.isGoDeeper()) {
calculateMultiTypes(file, items);
break nextFile;
} else if (dir.isSkipOther()) {
break nextFile;
}
}
}
}
//current directory did not match to any type
otherMemory.addBytes(getDirectorySize(file));
} else if (file.isFile()) {
//check current file should be avoid
if (prefixesToAvoid != null) {
for (String prefixToAvoid : prefixesToAvoid) {
if (file.getName().toLowerCase().startsWith(prefixToAvoid.toLowerCase())) {
break nextFile;
}
}
}
//check current file matched items type
for (DataStorageMemoryItem item : items) {
Directory[] directories = item.getDirectories();
if (directories == null) {
continue;
}
for (Directory dir : directories) {
if (rootDir.getAbsolutePath().equals(dir.getAbsolutePath())
|| (rootDir.getAbsolutePath().startsWith(dir.getAbsolutePath()) && dir.isGoDeeper())) {
int checkingType = dir.getCheckingType();
switch (checkingType) {
case EXTENSIONS : {
String[] extensions = item.getExtensions();
if (extensions != null) {
for (String extension : extensions) {
if (file.getAbsolutePath().endsWith(extension)) {
item.addBytes(file.length());
break nextFile;
}
}
} else {
item.addBytes(file.length());
break nextFile;
}
break ;
}
case PREFIX : {
String[] prefixes = item.getPrefixes();
if (prefixes != null) {
for (String prefix : prefixes) {
if (file.getName().toLowerCase().startsWith(prefix.toLowerCase())) {
item.addBytes(file.length());
break nextFile;
}
}
} else {
item.addBytes(file.length());
break nextFile;
}
break ;
}
}
if (dir.isSkipOther()) {
break nextFile;
}
}
}
}
//current file did not match any type
otherMemory.addBytes(file.length());
}
}
refreshUI();
}
}
private long getDirectorySize(File dir) {
long bytes = 0;
if (dir.isDirectory()) {
File[] files = dir.listFiles();
for (File file : files) {
if (isCancelled()) {
break;
}
if (file.isDirectory()) {
bytes += getDirectorySize(file);
} else if (file.isFile()) {
bytes += file.length();
}
}
}
return bytes;
}
@Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
if (listener != null) {
listener.onMemoryInfoUpdate();
}
}
@Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
if (listener != null) {
listener.onFinishUpdating(taskKey);
}
}
private void refreshUI() {
long currentTime = System.currentTimeMillis();
if ((currentTime - lastRefreshTime) > UI_REFRESH_TIME_MS) {
lastRefreshTime = currentTime;
publishProgress();
}
}
}
public long getTotalUsedBytes() {
long total = 0;
if (memoryItems != null && memoryItems.size() > 0) {
for (DataStorageMemoryItem mi : memoryItems) {
total += mi.getUsedMemoryBytes();
}
return total;
}
return -1;
}
public static String getFormattedMemoryInfo(long bytes, String[] formatStrings) {
int type = 0;
double memory = (double) bytes / 1024;
while (memory > 1024 && type < formatStrings.length) {
++type;
memory = memory / 1024;
}
String formattedUsed = new DecimalFormat("#.##").format(memory);
return String.format(formatStrings[type], formattedUsed);
}
public interface UpdateMemoryInfoUIAdapter {
void onMemoryInfoUpdate();
void onFinishUpdating(String taskKey);
}
}

View file

@ -36,6 +36,7 @@ import org.apache.commons.logging.Log;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Locale;
@ -150,7 +151,7 @@ public class ExportSettingsFragment extends BaseSettingsListFragment {
showExportProgressDialog();
File tempDir = FileUtils.getTempDir(app);
String fileName = getFileName();
List<SettingsItem> items = app.getSettingsHelper().prepareSettingsItems(adapter.getData(), true);
List<SettingsItem> items = app.getSettingsHelper().prepareSettingsItems(adapter.getData(), Collections.<SettingsItem>emptyList(), true);
progress.setMax(getMaxProgress(items));
app.getSettingsHelper().exportSettings(tempDir, fileName, getSettingsExportListener(), items, true);
}

View file

@ -22,6 +22,8 @@ import net.osmand.plus.profiles.SelectProfileBottomSheet.DialogMode;
import net.osmand.plus.profiles.SelectProfileBottomSheet.OnSelectProfileCallback;
import net.osmand.plus.settings.backend.ApplicationMode;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.settings.datastorage.DataStorageHelper;
import net.osmand.plus.settings.datastorage.item.StorageItem;
import net.osmand.plus.settings.preferences.ListPreferenceEx;
import net.osmand.plus.settings.preferences.SwitchPreferenceEx;
@ -181,7 +183,7 @@ public class GlobalSettingsFragment extends BaseSettingsFragment
externalStorageDir.setIcon(getActiveIcon(R.drawable.ic_action_folder));
DataStorageHelper holder = new DataStorageHelper(app);
DataStorageMenuItem currentStorage = holder.getCurrentStorage();
StorageItem currentStorage = holder.getCurrentStorage();
long totalUsed = app.getSettings().OSMAND_USAGE_SPACE.get();
if (totalUsed > 0) {
String[] usedMemoryFormats = new String[] {

View file

@ -18,57 +18,24 @@ import androidx.fragment.app.FragmentManager;
import com.google.android.material.appbar.CollapsingToolbarLayout;
import net.osmand.IndexConstants;
import net.osmand.PlatformUtil;
import net.osmand.map.ITileSource;
import net.osmand.map.TileSourceManager.TileSourceTemplate;
import net.osmand.plus.AppInitializer;
import net.osmand.plus.FavouritesDbHelper.FavoriteGroup;
import net.osmand.plus.OsmandPlugin;
import net.osmand.plus.R;
import net.osmand.plus.SQLiteTileSource;
import net.osmand.plus.UiUtilities;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.audionotes.AudioVideoNotesPlugin;
import net.osmand.plus.download.ReloadIndexesTask;
import net.osmand.plus.download.ReloadIndexesTask.ReloadIndexesListener;
import net.osmand.plus.helpers.AvoidSpecificRoads.AvoidRoadInfo;
import net.osmand.plus.helpers.SearchHistoryHelper.HistoryEntry;
import net.osmand.plus.mapmarkers.MapMarker;
import net.osmand.plus.mapmarkers.MapMarkersGroup;
import net.osmand.plus.onlinerouting.engine.OnlineRoutingEngine;
import net.osmand.plus.osmedit.OpenstreetmapPoint;
import net.osmand.plus.osmedit.OsmNotesPoint;
import net.osmand.plus.poi.PoiUIFilter;
import net.osmand.plus.quickaction.QuickAction;
import net.osmand.plus.settings.backend.ApplicationMode.ApplicationModeBean;
import net.osmand.plus.settings.backend.ExportSettingsType;
import net.osmand.plus.settings.backend.backup.AvoidRoadsSettingsItem;
import net.osmand.plus.settings.backend.backup.FavoritesSettingsItem;
import net.osmand.plus.settings.backend.backup.FileSettingsItem;
import net.osmand.plus.settings.backend.backup.GlobalSettingsItem;
import net.osmand.plus.settings.backend.backup.GpxSettingsItem;
import net.osmand.plus.settings.backend.backup.HistoryMarkersSettingsItem;
import net.osmand.plus.settings.backend.backup.MapSourcesSettingsItem;
import net.osmand.plus.settings.backend.backup.MarkersSettingsItem;
import net.osmand.plus.settings.backend.backup.OnlineRoutingSettingsItem;
import net.osmand.plus.settings.backend.backup.OsmEditsSettingsItem;
import net.osmand.plus.settings.backend.backup.OsmNotesSettingsItem;
import net.osmand.plus.settings.backend.backup.PoiUiFiltersSettingsItem;
import net.osmand.plus.settings.backend.backup.ProfileSettingsItem;
import net.osmand.plus.settings.backend.backup.QuickActionsSettingsItem;
import net.osmand.plus.settings.backend.backup.SearchHistorySettingsItem;
import net.osmand.plus.settings.backend.backup.SettingsHelper;
import net.osmand.plus.settings.backend.backup.SettingsHelper.ImportAsyncTask;
import net.osmand.plus.settings.backend.backup.SettingsItem;
import net.osmand.plus.settings.backend.backup.SettingsItemType;
import net.osmand.util.Algorithms;
import org.apache.commons.logging.Log;
import java.io.File;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
public class ImportSettingsFragment extends BaseSettingsListFragment {
@ -177,7 +144,7 @@ public class ImportSettingsFragment extends BaseSettingsListFragment {
}
private void importItems() {
List<SettingsItem> selectedItems = getSettingsItemsFromData(adapter.getData());
List<SettingsItem> selectedItems = settingsHelper.prepareSettingsItems(adapter.getData(), settingsItems, false);
if (file != null && settingsItems != null) {
duplicateStartTime = System.currentTimeMillis();
settingsHelper.checkDuplicates(file, settingsItems, selectedItems, getDuplicatesListener());
@ -272,181 +239,6 @@ public class ImportSettingsFragment extends BaseSettingsListFragment {
this.settingsItems = settingsItems;
}
@Nullable
private ProfileSettingsItem getBaseProfileSettingsItem(ApplicationModeBean modeBean) {
for (SettingsItem settingsItem : settingsItems) {
if (settingsItem.getType() == SettingsItemType.PROFILE) {
ProfileSettingsItem profileItem = (ProfileSettingsItem) settingsItem;
ApplicationModeBean bean = profileItem.getModeBean();
if (Algorithms.objectEquals(bean.stringKey, modeBean.stringKey) && Algorithms.objectEquals(bean.userProfileName, modeBean.userProfileName)) {
return profileItem;
}
}
}
return null;
}
@Nullable
private QuickActionsSettingsItem getBaseQuickActionsSettingsItem() {
for (SettingsItem settingsItem : settingsItems) {
if (settingsItem.getType() == SettingsItemType.QUICK_ACTIONS) {
return (QuickActionsSettingsItem) settingsItem;
}
}
return null;
}
@Nullable
private PoiUiFiltersSettingsItem getBasePoiUiFiltersSettingsItem() {
for (SettingsItem settingsItem : settingsItems) {
if (settingsItem.getType() == SettingsItemType.POI_UI_FILTERS) {
return (PoiUiFiltersSettingsItem) settingsItem;
}
}
return null;
}
@Nullable
private MapSourcesSettingsItem getBaseMapSourcesSettingsItem() {
for (SettingsItem settingsItem : settingsItems) {
if (settingsItem.getType() == SettingsItemType.MAP_SOURCES) {
return (MapSourcesSettingsItem) settingsItem;
}
}
return null;
}
@Nullable
private AvoidRoadsSettingsItem getBaseAvoidRoadsSettingsItem() {
for (SettingsItem settingsItem : settingsItems) {
if (settingsItem.getType() == SettingsItemType.AVOID_ROADS) {
return (AvoidRoadsSettingsItem) settingsItem;
}
}
return null;
}
@Nullable
private <T> T getBaseItem(SettingsItemType settingsItemType, Class<T> clazz) {
for (SettingsItem settingsItem : settingsItems) {
if (settingsItem.getType() == settingsItemType && clazz.isInstance(settingsItem)) {
return clazz.cast(settingsItem);
}
}
return null;
}
private List<SettingsItem> getSettingsItemsFromData(List<?> data) {
List<SettingsItem> settingsItems = new ArrayList<>();
List<ApplicationModeBean> appModeBeans = new ArrayList<>();
List<QuickAction> quickActions = new ArrayList<>();
List<PoiUIFilter> poiUIFilters = new ArrayList<>();
List<ITileSource> tileSourceTemplates = new ArrayList<>();
List<AvoidRoadInfo> avoidRoads = new ArrayList<>();
List<OsmNotesPoint> osmNotesPointList = new ArrayList<>();
List<OpenstreetmapPoint> osmEditsPointList = new ArrayList<>();
List<FavoriteGroup> favoriteGroups = new ArrayList<>();
List<MapMarkersGroup> markersGroups = new ArrayList<>();
List<MapMarkersGroup> markersHistoryGroups = new ArrayList<>();
List<HistoryEntry> historyEntries = new ArrayList<>();
List<OnlineRoutingEngine> onlineRoutingEngines = new ArrayList<>();
for (Object object : data) {
if (object instanceof ApplicationModeBean) {
appModeBeans.add((ApplicationModeBean) object);
} else if (object instanceof QuickAction) {
quickActions.add((QuickAction) object);
} else if (object instanceof PoiUIFilter) {
poiUIFilters.add((PoiUIFilter) object);
} else if (object instanceof TileSourceTemplate || object instanceof SQLiteTileSource) {
tileSourceTemplates.add((ITileSource) object);
} else if (object instanceof File) {
File file = (File) object;
if (file.getName().endsWith(IndexConstants.GPX_FILE_EXT)) {
settingsItems.add(new GpxSettingsItem(app, file));
} else {
settingsItems.add(new FileSettingsItem(app, file));
}
} else if (object instanceof FileSettingsItem) {
settingsItems.add((FileSettingsItem) object);
} else if (object instanceof AvoidRoadInfo) {
avoidRoads.add((AvoidRoadInfo) object);
} else if (object instanceof OsmNotesPoint) {
osmNotesPointList.add((OsmNotesPoint) object);
} else if (object instanceof OpenstreetmapPoint) {
osmEditsPointList.add((OpenstreetmapPoint) object);
} else if (object instanceof FavoriteGroup) {
favoriteGroups.add((FavoriteGroup) object);
} else if (object instanceof GlobalSettingsItem) {
settingsItems.add((GlobalSettingsItem) object);
} else if (object instanceof MapMarkersGroup) {
MapMarkersGroup markersGroup = (MapMarkersGroup) object;
if (ExportSettingsType.ACTIVE_MARKERS.name().equals(markersGroup.getId())) {
markersGroups.add((MapMarkersGroup) object);
} else if (ExportSettingsType.HISTORY_MARKERS.name().equals(markersGroup.getId())) {
markersHistoryGroups.add((MapMarkersGroup) object);
}
} else if (object instanceof HistoryEntry) {
historyEntries.add((HistoryEntry) object);
} else if (object instanceof OnlineRoutingEngine) {
onlineRoutingEngines.add((OnlineRoutingEngine) object);
}
}
if (!appModeBeans.isEmpty()) {
for (ApplicationModeBean modeBean : appModeBeans) {
settingsItems.add(new ProfileSettingsItem(app, getBaseProfileSettingsItem(modeBean), modeBean));
}
}
if (!quickActions.isEmpty()) {
settingsItems.add(new QuickActionsSettingsItem(app, getBaseQuickActionsSettingsItem(), quickActions));
}
if (!poiUIFilters.isEmpty()) {
settingsItems.add(new PoiUiFiltersSettingsItem(app, getBasePoiUiFiltersSettingsItem(), poiUIFilters));
}
if (!tileSourceTemplates.isEmpty()) {
settingsItems.add(new MapSourcesSettingsItem(app, getBaseMapSourcesSettingsItem(), tileSourceTemplates));
}
if (!avoidRoads.isEmpty()) {
settingsItems.add(new AvoidRoadsSettingsItem(app, getBaseAvoidRoadsSettingsItem(), avoidRoads));
}
if (!osmNotesPointList.isEmpty()) {
OsmNotesSettingsItem baseItem = getBaseItem(SettingsItemType.OSM_NOTES, OsmNotesSettingsItem.class);
settingsItems.add(new OsmNotesSettingsItem(app, baseItem, osmNotesPointList));
}
if (!osmEditsPointList.isEmpty()) {
OsmEditsSettingsItem baseItem = getBaseItem(SettingsItemType.OSM_EDITS, OsmEditsSettingsItem.class);
settingsItems.add(new OsmEditsSettingsItem(app, baseItem, osmEditsPointList));
}
if (!favoriteGroups.isEmpty()) {
FavoritesSettingsItem baseItem = getBaseItem(SettingsItemType.FAVOURITES, FavoritesSettingsItem.class);
settingsItems.add(new FavoritesSettingsItem(app, baseItem, favoriteGroups));
}
if (!markersGroups.isEmpty()) {
List<MapMarker> mapMarkers = new ArrayList<>();
for (MapMarkersGroup group : markersGroups) {
mapMarkers.addAll(group.getMarkers());
}
MarkersSettingsItem baseItem = getBaseItem(SettingsItemType.ACTIVE_MARKERS, MarkersSettingsItem.class);
settingsItems.add(new MarkersSettingsItem(app, baseItem, mapMarkers));
}
if (!markersHistoryGroups.isEmpty()) {
List<MapMarker> mapMarkers = new ArrayList<>();
for (MapMarkersGroup group : markersHistoryGroups) {
mapMarkers.addAll(group.getMarkers());
}
HistoryMarkersSettingsItem baseItem = getBaseItem(SettingsItemType.HISTORY_MARKERS, HistoryMarkersSettingsItem.class);
settingsItems.add(new HistoryMarkersSettingsItem(app, baseItem, mapMarkers));
}
if (!historyEntries.isEmpty()) {
SearchHistorySettingsItem baseItem = getBaseItem(SettingsItemType.SEARCH_HISTORY, SearchHistorySettingsItem.class);
settingsItems.add(new SearchHistorySettingsItem(app, baseItem, historyEntries));
}
if (!onlineRoutingEngines.isEmpty()) {
OnlineRoutingSettingsItem baseItem = getBaseItem(SettingsItemType.ONLINE_ROUTING_ENGINES, OnlineRoutingSettingsItem.class);
settingsItems.add(new OnlineRoutingSettingsItem(app, baseItem, onlineRoutingEngines));
}
return settingsItems;
}
public void setFile(File file) {
this.file = file;
}

View file

@ -47,7 +47,7 @@ public class SegmentsCard extends BaseCard {
WrapContentHeightViewPager pager = segmentView.findViewById(R.id.pager);
PagerSlidingTabStrip tabLayout = segmentView.findViewById(R.id.sliding_tabs);
pager.setAdapter(new GPXItemPagerAdapter(tabLayout, displayItem, displayHelper, listener));
pager.setAdapter(new GPXItemPagerAdapter(app, displayItem, displayHelper, nightMode, listener));
tabLayout.setViewPager(pager);
container.addView(segmentView);

View file

@ -149,6 +149,7 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
private Location lastLocation;
private UpdateLocationViewCache updateLocationViewCache;
private boolean locationUpdateStarted;
private LatLon latLon;
private int menuTitleHeight;
private int toolbarHeightPx;
@ -259,6 +260,10 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
this.selectedGpxFile = selectedGpxFile;
}
public void setLatLon(LatLon latLon) {
this.latLon = latLon;
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = super.onCreateView(inflater, container, savedInstanceState);
@ -556,10 +561,9 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
MapActivity mapActivity = getMapActivity();
View view = overviewCard.getView();
if (mapActivity != null && view != null) {
MapContextMenu menu = mapActivity.getContextMenu();
TextView distanceText = (TextView) view.findViewById(R.id.distance);
ImageView direction = (ImageView) view.findViewById(R.id.direction);
app.getUIUtilities().updateLocationView(updateLocationViewCache, direction, distanceText, menu.getLatLon());
app.getUIUtilities().updateLocationView(updateLocationViewCache, direction, distanceText, latLon);
}
}
@ -1113,7 +1117,7 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
selectedGpxFile = app.getSelectedGpxHelper().getSelectedFileByPath(path);
}
if (selectedGpxFile != null) {
showInstance(mapActivity, selectedGpxFile);
showInstance(mapActivity, selectedGpxFile, null);
} else if (!Algorithms.isEmpty(path)) {
String title = app.getString(R.string.loading_smth, "");
final ProgressDialog progress = ProgressDialog.show(mapActivity, title, app.getString(R.string.loading_data));
@ -1126,7 +1130,7 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
if (mapActivity != null) {
OsmandApplication app = mapActivity.getMyApplication();
SelectedGpxFile selectedGpxFile = app.getSelectedGpxHelper().selectGpxFile(result, true, false);
showInstance(mapActivity, selectedGpxFile);
showInstance(mapActivity, selectedGpxFile, null);
}
if (progress != null && AndroidUtils.isActivityNotDestroyed(mapActivity)) {
progress.dismiss();
@ -1138,7 +1142,7 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
}
}
public static boolean showInstance(@NonNull MapActivity mapActivity, SelectedGpxFile selectedGpxFile) {
public static boolean showInstance(@NonNull MapActivity mapActivity, SelectedGpxFile selectedGpxFile, @Nullable LatLon latLon) {
try {
Bundle args = new Bundle();
args.putInt(ContextMenuFragment.MENU_STATE_KEY, MenuState.HEADER_ONLY);
@ -1148,6 +1152,14 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
fragment.setRetainInstance(true);
fragment.setSelectedGpxFile(selectedGpxFile);
if (latLon != null) {
fragment.setLatLon(latLon);
} else {
QuadRect rect = selectedGpxFile.getGpxFile().getRect();
LatLon latLonRect = new LatLon(rect.centerY(), rect.centerX());
fragment.setLatLon(latLonRect);
}
mapActivity.getSupportFragmentManager()
.beginTransaction()
.replace(R.id.fragmentContainer, fragment, TAG)

View file

@ -68,6 +68,7 @@ public class PagerSlidingTabStrip extends HorizontalScrollView {
public View getCustomTabView(@NonNull ViewGroup parent, int position);
public void select(View tab);
public void deselect(View tab);
public void tabStylesUpdated(View tabsContainer, int currentPosition);
}
public interface OnTabReselectedListener {
@ -307,6 +308,10 @@ public class PagerSlidingTabStrip extends HorizontalScrollView {
}
}
public int getCurrentPosition() {
return currentPosition;
}
private void addTab(final int position, CharSequence title, View tabView) {
TextView textView = (TextView) tabView.findViewById(R.id.tab_title);
if (textView != null) {
@ -332,41 +337,31 @@ public class PagerSlidingTabStrip extends HorizontalScrollView {
private void updateTabStyles() {
tabsContainer.setBackgroundResource(tabBackgroundResId);
if (pager.getAdapter() instanceof CustomTabProvider) {
((CustomTabProvider) pager.getAdapter()).tabStylesUpdated(tabsContainer, currentPosition);
} else {
for (int i = 0; i < tabCount; i++) {
View v = tabsContainer.getChildAt(i);
v.setBackgroundResource(tabBackgroundResId);
v.setPadding(tabPadding, v.getPaddingTop(), tabPadding, v.getPaddingBottom());
TextView tab_title = (TextView) v.findViewById(R.id.tab_title);
if (tab_title != null) {
tab_title.setTextSize(TypedValue.COMPLEX_UNIT_PX, tabTextSize);
tab_title.setTypeface(tabTypeface, pager.getCurrentItem() == i ? tabTypefaceSelectedStyle : tabTypefaceStyle);
TextView tabTitle = v.findViewById(R.id.tab_title);
if (tabTitle != null) {
tabTitle.setTextSize(TypedValue.COMPLEX_UNIT_PX, tabTextSize);
tabTitle.setTypeface(tabTypeface, pager.getCurrentItem() == i ? tabTypefaceSelectedStyle : tabTypefaceStyle);
switch (tabSelectionType) {
case ALPHA:
float alpha = pager.getCurrentItem() == i ? tabTextSelectedAlpha : tabTextAlpha;
tab_title.setAlpha(alpha);
tab_title.setTextColor(tabTextColor);
tabTitle.setAlpha(alpha);
tabTitle.setTextColor(tabTextColor);
break;
case SOLID_COLOR:
tab_title.setAlpha(OPAQUE);
tab_title.setTextColor(pager.getCurrentItem() == i ? tabTextColor : tabInactiveTextColor);
tabTitle.setAlpha(OPAQUE);
tabTitle.setTextColor(pager.getCurrentItem() == i ? tabTextColor : tabInactiveTextColor);
break;
}
if (pager.getAdapter() instanceof CustomTabProvider) {
if (pager.getCurrentItem() == i) {
((CustomTabProvider) pager.getAdapter()).select(v);
} else {
((CustomTabProvider) pager.getAdapter()).deselect(v);
}
}
// setAllCaps() is only available from API 14, so the upper case is made manually if we are on a
// pre-ICS-build
if (textAllCaps) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
tab_title.setAllCaps(true);
} else {
tab_title.setText(tab_title.getText().toString().toUpperCase(locale));
tabTitle.setAllCaps(true);
}
}
}
@ -558,7 +553,10 @@ public class PagerSlidingTabStrip extends HorizontalScrollView {
private void notSelected(View tab) {
if (tab != null) {
TextView title = (TextView) tab.findViewById(R.id.tab_title);
if (pager.getAdapter() instanceof CustomTabProvider) {
((CustomTabProvider) pager.getAdapter()).deselect(tab);
} else {
TextView title = tab.findViewById(R.id.tab_title);
if (title != null) {
title.setTypeface(tabTypeface, tabTypefaceStyle);
switch (tabSelectionType) {
@ -570,15 +568,16 @@ public class PagerSlidingTabStrip extends HorizontalScrollView {
break;
}
}
if (pager.getAdapter() instanceof CustomTabProvider) {
((CustomTabProvider) pager.getAdapter()).deselect(tab);
}
}
}
private void selected(View tab) {
if (tab != null) {
TextView title = (TextView) tab.findViewById(R.id.tab_title);
if (pager.getAdapter() instanceof CustomTabProvider) {
((CustomTabProvider) pager.getAdapter()).select(tab);
} else {
TextView title = tab.findViewById(R.id.tab_title);
if (title != null) {
title.setTypeface(tabTypeface, tabTypefaceSelectedStyle);
switch (tabSelectionType) {
@ -589,8 +588,6 @@ public class PagerSlidingTabStrip extends HorizontalScrollView {
title.setTextColor(tabTextColor);
break;
}
if (pager.getAdapter() instanceof CustomTabProvider) {
((CustomTabProvider) pager.getAdapter()).select(tab);
}
}
}

View file

@ -1,8 +1,12 @@
package net.osmand.plus.wikipedia;
import android.app.Activity;
import android.content.res.Resources;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.text.SpannableString;
import android.text.style.StyleSpan;
import android.view.View;
import android.widget.CompoundButton;
@ -12,6 +16,8 @@ import androidx.core.content.ContextCompat;
import androidx.core.os.ConfigurationCompat;
import androidx.core.os.LocaleListCompat;
import com.google.android.material.snackbar.Snackbar;
import net.osmand.AndroidUtils;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandPlugin;
@ -124,6 +130,12 @@ public class SelectWikiLanguagesBottomSheet extends MenuBottomSheetDialogFragmen
}
}
@Nullable
public MapActivity getMapActivity() {
Activity activity = getActivity();
return (MapActivity) activity;
}
private void initLanguagesData() {
languages = new ArrayList<>();
@ -188,12 +200,44 @@ public class SelectWikiLanguagesBottomSheet extends MenuBottomSheetDialogFragmen
localesForSaving.add(language.getLocale());
}
}
wikiPlugin.setLanguagesToShow(localesForSaving);
wikiPlugin.setShowAllLanguages(isGlobalWikiPoiEnabled);
wikiPlugin.updateWikipediaState();
applyPreferenceWithSnackBar(localesForSaving, isGlobalWikiPoiEnabled);
dismiss();
}
protected final void applyPreference(boolean applyToAllProfiles, List<String> localesForSaving, boolean global) {
if (applyToAllProfiles) {
for (ApplicationMode mode : ApplicationMode.allPossibleValues()) {
wikiPlugin.setLanguagesToShow(mode, localesForSaving);
wikiPlugin.setShowAllLanguages(mode, global);
}
} else {
wikiPlugin.setLanguagesToShow(localesForSaving);
wikiPlugin.setShowAllLanguages(global);
}
wikiPlugin.updateWikipediaState();
}
protected void applyPreferenceWithSnackBar(final List<String> localesForSaving, final boolean global) {
applyPreference(false, localesForSaving, global);
MapActivity mapActivity = getMapActivity();
if (mapActivity != null) {
String modeName = appMode.toHumanString();
String text = app.getString(R.string.changes_applied_to_profile, modeName);
SpannableString message = UiUtilities.createSpannableString(text, new StyleSpan(Typeface.BOLD), modeName);
Snackbar snackbar = Snackbar.make(mapActivity.getLayout(), message, Snackbar.LENGTH_LONG)
.setAction(R.string.apply_to_all_profiles, new View.OnClickListener() {
@Override
public void onClick(View view) {
applyPreference(true, localesForSaving, global);
}
});
UiUtilities.setupSnackbarVerticalLayout(snackbar);
UiUtilities.setupSnackbar(snackbar, nightMode);
snackbar.show();
}
}
private View getCustomButtonView() {
OsmandApplication app = getMyApplication();
if (app == null) {

View file

@ -30,6 +30,7 @@ import net.osmand.plus.search.QuickSearchDialogFragment;
import net.osmand.plus.search.QuickSearchListAdapter;
import net.osmand.plus.search.listitems.QuickSearchBannerListItem;
import net.osmand.plus.search.listitems.QuickSearchFreeBannerListItem;
import net.osmand.plus.settings.backend.ApplicationMode;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.views.layers.DownloadedRegionsLayer;
import net.osmand.plus.views.OsmandMapTileView;
@ -189,26 +190,50 @@ public class WikipediaPlugin extends OsmandPlugin {
return !isShowAllLanguages() && getLanguagesToShow() != null;
}
public boolean hasCustomSettings(ApplicationMode profile) {
return !isShowAllLanguages(profile) && getLanguagesToShow(profile) != null;
}
public boolean hasLanguagesFilter() {
return settings.WIKIPEDIA_POI_ENABLED_LANGUAGES.get() != null;
}
public boolean hasLanguagesFilter(ApplicationMode profile) {
return settings.WIKIPEDIA_POI_ENABLED_LANGUAGES.getModeValue(profile) != null;
}
public boolean isShowAllLanguages() {
return settings.GLOBAL_WIKIPEDIA_POI_ENABLED.get();
}
public boolean isShowAllLanguages(ApplicationMode mode) {
return settings.GLOBAL_WIKIPEDIA_POI_ENABLED.getModeValue(mode);
}
public void setShowAllLanguages(boolean showAllLanguages) {
settings.GLOBAL_WIKIPEDIA_POI_ENABLED.set(showAllLanguages);
}
public void setShowAllLanguages(ApplicationMode mode, boolean showAllLanguages) {
settings.GLOBAL_WIKIPEDIA_POI_ENABLED.setModeValue(mode, showAllLanguages);
}
public List<String> getLanguagesToShow() {
return settings.WIKIPEDIA_POI_ENABLED_LANGUAGES.getStringsList();
}
public List<String> getLanguagesToShow(ApplicationMode mode) {
return settings.WIKIPEDIA_POI_ENABLED_LANGUAGES.getStringsListForProfile(mode);
}
public void setLanguagesToShow(List<String> languagesToShow) {
settings.WIKIPEDIA_POI_ENABLED_LANGUAGES.setStringsList(languagesToShow);
}
public void setLanguagesToShow(ApplicationMode mode, List<String> languagesToShow) {
settings.WIKIPEDIA_POI_ENABLED_LANGUAGES.setStringsListForProfile(mode, languagesToShow);
}
public void toggleWikipediaPoi(boolean enable, CallbackWithObject<Boolean> callback) {
if (enable) {
showWikiOnMap();

View file

@ -1,9 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="gen"/>
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
<classpathentry kind="output" path="bin/classes"/>
</classpath>

View file

@ -1,33 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>Osmand-Nautical</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.ApkBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View file

@ -1,9 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="gen"/>
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
<classpathentry kind="output" path="bin/classes"/>
</classpath>

View file

@ -1,33 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>Osmand-ParkingPlugin</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.ApkBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View file

@ -1,9 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="gen"/>
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
<classpathentry kind="output" path="bin/classes"/>
</classpath>

View file

@ -1,33 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>Osmand-SRTMPlugin</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.ApkBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View file

@ -1,9 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="gen"/>
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
<classpathentry kind="output" path="bin/classes"/>
</classpath>

View file

@ -1,33 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>Osmand-SkiMaps</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.ApkBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>