commit
c941794281
77 changed files with 2630 additions and 1240 deletions
|
@ -1822,6 +1822,25 @@ public class GPXUtilities {
|
||||||
}
|
}
|
||||||
serializer.endTag(null, "metadata");
|
serializer.endTag(null, "metadata");
|
||||||
|
|
||||||
|
for (WptPt l : file.points) {
|
||||||
|
serializer.startTag(null, "wpt"); //$NON-NLS-1$
|
||||||
|
writeWpt(format, serializer, l);
|
||||||
|
serializer.endTag(null, "wpt"); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Route track : file.routes) {
|
||||||
|
serializer.startTag(null, "rte"); //$NON-NLS-1$
|
||||||
|
writeNotNullText(serializer, "name", track.name);
|
||||||
|
writeNotNullText(serializer, "desc", track.desc);
|
||||||
|
|
||||||
|
for (WptPt p : track.points) {
|
||||||
|
serializer.startTag(null, "rtept"); //$NON-NLS-1$
|
||||||
|
writeWpt(format, serializer, p);
|
||||||
|
serializer.endTag(null, "rtept"); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
writeExtensions(serializer, track);
|
||||||
|
serializer.endTag(null, "rte"); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
|
||||||
for (Track track : file.tracks) {
|
for (Track track : file.tracks) {
|
||||||
if (!track.generalTrack) {
|
if (!track.generalTrack) {
|
||||||
|
@ -1844,26 +1863,6 @@ public class GPXUtilities {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Route track : file.routes) {
|
|
||||||
serializer.startTag(null, "rte"); //$NON-NLS-1$
|
|
||||||
writeNotNullText(serializer, "name", track.name);
|
|
||||||
writeNotNullText(serializer, "desc", track.desc);
|
|
||||||
|
|
||||||
for (WptPt p : track.points) {
|
|
||||||
serializer.startTag(null, "rtept"); //$NON-NLS-1$
|
|
||||||
writeWpt(format, serializer, p);
|
|
||||||
serializer.endTag(null, "rtept"); //$NON-NLS-1$
|
|
||||||
}
|
|
||||||
writeExtensions(serializer, track);
|
|
||||||
serializer.endTag(null, "rte"); //$NON-NLS-1$
|
|
||||||
}
|
|
||||||
|
|
||||||
for (WptPt l : file.points) {
|
|
||||||
serializer.startTag(null, "wpt"); //$NON-NLS-1$
|
|
||||||
writeWpt(format, serializer, l);
|
|
||||||
serializer.endTag(null, "wpt"); //$NON-NLS-1$
|
|
||||||
}
|
|
||||||
|
|
||||||
writeExtensions(serializer, file);
|
writeExtensions(serializer, file);
|
||||||
|
|
||||||
serializer.endTag(null, "gpx"); //$NON-NLS-1$
|
serializer.endTag(null, "gpx"); //$NON-NLS-1$
|
||||||
|
|
|
@ -20,7 +20,7 @@ public abstract class StringBundleWriter {
|
||||||
|
|
||||||
public void writeBundle() {
|
public void writeBundle() {
|
||||||
for (Entry<String, Item<?>> entry : bundle.getMap().entrySet()) {
|
for (Entry<String, Item<?>> entry : bundle.getMap().entrySet()) {
|
||||||
writeItem(entry.getKey(), entry.getValue());
|
writeItem("osmand:" + entry.getKey(), entry.getValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -108,18 +108,25 @@ android {
|
||||||
manifest.srcFile "AndroidManifest-debug.xml"
|
manifest.srcFile "AndroidManifest-debug.xml"
|
||||||
}
|
}
|
||||||
full {
|
full {
|
||||||
java.srcDirs = ["src-google"]
|
java.srcDirs = ["src-nogms", "src-google"]
|
||||||
|
}
|
||||||
|
fullGms {
|
||||||
|
java.srcDirs = ["src-gms", "src-google"]
|
||||||
}
|
}
|
||||||
free {
|
free {
|
||||||
java.srcDirs = ["src-google"]
|
java.srcDirs = ["src-nogms", "src-google"]
|
||||||
|
manifest.srcFile "AndroidManifest-free.xml"
|
||||||
|
}
|
||||||
|
freeGms {
|
||||||
|
java.srcDirs = ["src-gms", "src-google"]
|
||||||
manifest.srcFile "AndroidManifest-free.xml"
|
manifest.srcFile "AndroidManifest-free.xml"
|
||||||
}
|
}
|
||||||
freedev {
|
freedev {
|
||||||
java.srcDirs = ["src-google"]
|
java.srcDirs = ["src-nogms", "src-google"]
|
||||||
manifest.srcFile "AndroidManifest-freedev.xml"
|
manifest.srcFile "AndroidManifest-freedev.xml"
|
||||||
}
|
}
|
||||||
freehuawei {
|
freehuawei {
|
||||||
java.srcDirs = ["src-huawei"]
|
java.srcDirs = ["src-nogms", "src-google"]
|
||||||
manifest.srcFile "AndroidManifest-freehuawei.xml"
|
manifest.srcFile "AndroidManifest-freehuawei.xml"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,10 +179,18 @@ android {
|
||||||
dimension "version"
|
dimension "version"
|
||||||
applicationId "net.osmand"
|
applicationId "net.osmand"
|
||||||
}
|
}
|
||||||
|
freeGms {
|
||||||
|
dimension "version"
|
||||||
|
applicationId "net.osmand"
|
||||||
|
}
|
||||||
full {
|
full {
|
||||||
dimension "version"
|
dimension "version"
|
||||||
applicationId "net.osmand.plus"
|
applicationId "net.osmand.plus"
|
||||||
}
|
}
|
||||||
|
fullGms {
|
||||||
|
dimension "version"
|
||||||
|
applicationId "net.osmand.plus"
|
||||||
|
}
|
||||||
freehuawei {
|
freehuawei {
|
||||||
dimension "version"
|
dimension "version"
|
||||||
applicationId "net.osmand.huawei"
|
applicationId "net.osmand.huawei"
|
||||||
|
@ -507,8 +522,10 @@ dependencies {
|
||||||
exclude group: "com.fasterxml.jackson.core"
|
exclude group: "com.fasterxml.jackson.core"
|
||||||
}
|
}
|
||||||
implementation 'com.jaredrummler:colorpicker:1.1.0'
|
implementation 'com.jaredrummler:colorpicker:1.1.0'
|
||||||
|
implementation "org.bouncycastle:bcpkix-jdk15on:1.56"
|
||||||
|
|
||||||
freehuaweiImplementation 'com.huawei.hms:iap:5.0.2.300'
|
freehuaweiImplementation 'com.huawei.hms:iap:5.0.2.300'
|
||||||
|
|
||||||
implementation "org.bouncycastle:bcpkix-jdk15on:1.56"
|
freeGmsImplementation 'com.google.android.gms:play-services-location:17.1.0'
|
||||||
|
fullGmsImplementation 'com.google.android.gms:play-services-location:17.1.0'
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@ android {
|
||||||
jni.srcDirs = []
|
jni.srcDirs = []
|
||||||
jniLibs.srcDirs = ["libs"]
|
jniLibs.srcDirs = ["libs"]
|
||||||
aidl.srcDirs = ["src"]
|
aidl.srcDirs = ["src"]
|
||||||
java.srcDirs = ["src", "src-google"]
|
java.srcDirs = ["src", "src-gms", "src-google"]
|
||||||
resources.srcDirs = ["src"]
|
resources.srcDirs = ["src"]
|
||||||
renderscript.srcDirs = ["src"]
|
renderscript.srcDirs = ["src"]
|
||||||
res.srcDirs = ["res"]
|
res.srcDirs = ["res"]
|
||||||
|
@ -409,6 +409,7 @@ dependencies {
|
||||||
exclude group: "com.fasterxml.jackson.core"
|
exclude group: "com.fasterxml.jackson.core"
|
||||||
}
|
}
|
||||||
implementation 'com.jaredrummler:colorpicker:1.1.0'
|
implementation 'com.jaredrummler:colorpicker:1.1.0'
|
||||||
|
|
||||||
implementation 'org.bouncycastle:bcpkix-jdk15on:1.56'
|
implementation 'org.bouncycastle:bcpkix-jdk15on:1.56'
|
||||||
|
|
||||||
|
implementation 'com.google.android.gms:play-services-location:17.1.0'
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,8 @@
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:layout_marginLeft="@dimen/content_padding"
|
android:layout_marginLeft="@dimen/content_padding"
|
||||||
android:layout_marginStart="@dimen/content_padding"
|
android:layout_marginStart="@dimen/content_padding"
|
||||||
|
android:paddingTop="@dimen/content_padding_small"
|
||||||
|
android:paddingBottom="@dimen/content_padding_small"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<net.osmand.plus.widgets.TextViewEx
|
<net.osmand.plus.widgets.TextViewEx
|
||||||
|
@ -34,7 +36,6 @@
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
android:maxLines="1"
|
|
||||||
android:textColor="?android:textColorPrimary"
|
android:textColor="?android:textColorPrimary"
|
||||||
android:textSize="@dimen/default_list_text_size"
|
android:textSize="@dimen/default_list_text_size"
|
||||||
app:typeface="@string/font_roboto_regular"
|
app:typeface="@string/font_roboto_regular"
|
||||||
|
|
|
@ -0,0 +1,74 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:minHeight="@dimen/bottom_sheet_selected_item_title_height"
|
||||||
|
android:baselineAligned="false">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/basic_item_body"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:background="?attr/selectableItemBackground">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/title"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:textAppearance="@style/TextAppearance.ListItemTitle"
|
||||||
|
tools:text="Some title" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<com.google.android.material.switchmaterial.SwitchMaterial
|
||||||
|
android:id="@+id/switch_button"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
|
android:layout_marginStart="@dimen/bottom_sheet_content_margin"
|
||||||
|
android:layout_marginLeft="@dimen/bottom_sheet_content_margin"
|
||||||
|
android:layout_marginEnd="@dimen/content_padding_half"
|
||||||
|
android:layout_marginRight="@dimen/content_padding_half"
|
||||||
|
tools:checked="true" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/additional_button"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="1dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_marginTop="@dimen/content_padding_half"
|
||||||
|
android:layout_marginBottom="@dimen/content_padding_half"
|
||||||
|
android:background="?attr/divider_color_basic" />
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatImageView
|
||||||
|
android:id="@+id/icon_after_divider"
|
||||||
|
style="@style/Widget.AppCompat.Toolbar.Button.Navigation"
|
||||||
|
android:layout_width="@dimen/acceptable_touch_radius"
|
||||||
|
android:layout_height="@dimen/acceptable_touch_radius"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:layout_marginLeft="@dimen/content_padding"
|
||||||
|
android:layout_marginRight="@dimen/content_padding"
|
||||||
|
app:srcCompat="@drawable/ic_action_track_line_bold_color" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
|
@ -129,6 +129,19 @@
|
||||||
tools:visibility="visible"
|
tools:visibility="visible"
|
||||||
android:visibility="gone" />
|
android:visibility="gone" />
|
||||||
|
|
||||||
|
<net.osmand.plus.widgets.TextViewEx
|
||||||
|
android:id="@+id/error_text"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:letterSpacing="@dimen/description_letter_spacing"
|
||||||
|
android:paddingTop="@dimen/content_padding_half"
|
||||||
|
android:textColor="@color/color_invalid"
|
||||||
|
android:textSize="@dimen/default_desc_text_size"
|
||||||
|
osmand:typeface="@string/font_roboto_regular"
|
||||||
|
tools:text="Error text"
|
||||||
|
tools:visibility="visible"
|
||||||
|
android:visibility="gone" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<View
|
<View
|
||||||
|
|
91
OsmAnd/res/layout/trip_recording_fragment.xml
Normal file
91
OsmAnd/res/layout/trip_recording_fragment.xml
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
<?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"
|
||||||
|
xmlns:osmand="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:paddingStart="@dimen/content_padding"
|
||||||
|
android:paddingLeft="@dimen/content_padding"
|
||||||
|
android:paddingTop="@dimen/bottom_sheet_content_margin"
|
||||||
|
android:paddingEnd="@dimen/content_padding"
|
||||||
|
android:paddingRight="@dimen/content_padding">
|
||||||
|
|
||||||
|
<net.osmand.plus.widgets.TextViewEx
|
||||||
|
android:id="@+id/title"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="@dimen/content_padding"
|
||||||
|
android:letterSpacing="@dimen/text_button_letter_spacing"
|
||||||
|
android:text="@string/monitoring_settings"
|
||||||
|
android:textSize="@dimen/default_list_text_size"
|
||||||
|
osmand:typeface="@string/font_roboto_medium" />
|
||||||
|
|
||||||
|
<include
|
||||||
|
android:id="@+id/show_track_on_map"
|
||||||
|
layout="@layout/bottom_sheet_with_switch_divider_and_additional_button" />
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="1dp"
|
||||||
|
android:layout_marginBottom="@dimen/bottom_sheet_content_margin_small"
|
||||||
|
android:background="?attr/dashboard_divider" />
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="@dimen/content_padding_small" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<net.osmand.plus.widgets.TextViewEx
|
||||||
|
android:id="@+id/interval_value"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:textSize="@dimen/default_list_text_size"
|
||||||
|
tools:text="Interval value" />
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatImageView
|
||||||
|
android:id="@+id/up_down_button"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@null"
|
||||||
|
app:srcCompat="@drawable/ic_action_arrow_down" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<com.google.android.material.slider.RangeSlider
|
||||||
|
android:id="@+id/interval_slider"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:contentDescription="@string/save_track_interval_globally"
|
||||||
|
android:stepSize="1"
|
||||||
|
app:labelBehavior="gone" />
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.SwitchCompat
|
||||||
|
android:id="@+id/confirm_every_run"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_marginBottom="@dimen/content_padding"
|
||||||
|
android:letterSpacing="@dimen/text_button_letter_spacing"
|
||||||
|
android:minHeight="@dimen/context_menu_buttons_bottom_height"
|
||||||
|
android:paddingLeft="@dimen/content_padding_small"
|
||||||
|
android:paddingRight="@dimen/content_padding_small"
|
||||||
|
android:text="@string/confirm_every_run"
|
||||||
|
android:textColor="?android:textColorPrimary"
|
||||||
|
android:textSize="@dimen/default_list_text_size"
|
||||||
|
android:visibility="gone"
|
||||||
|
osmand:typeface="@string/font_roboto_regular"
|
||||||
|
tools:visibility="visible" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -4023,7 +4023,6 @@
|
||||||
<string name="routing_engine_vehicle_type_foot">قدم</string>
|
<string name="routing_engine_vehicle_type_foot">قدم</string>
|
||||||
<string name="routing_engine_vehicle_type_bike">دراجة هوائية</string>
|
<string name="routing_engine_vehicle_type_bike">دراجة هوائية</string>
|
||||||
<string name="routing_engine_vehicle_type_car">سيارة</string>
|
<string name="routing_engine_vehicle_type_car">سيارة</string>
|
||||||
<string name="message_error_recheck_parameters">خطأ، أعد التحقق من المعايير</string>
|
|
||||||
<string name="copy_address">نسخ العنوان</string>
|
<string name="copy_address">نسخ العنوان</string>
|
||||||
<string name="online_routing_engine">محرك التوجيه عبر الإنترنت</string>
|
<string name="online_routing_engine">محرك التوجيه عبر الإنترنت</string>
|
||||||
<string name="online_routing_engines">محركات التوجيه عبر الإنترنت</string>
|
<string name="online_routing_engines">محركات التوجيه عبر الإنترنت</string>
|
||||||
|
|
|
@ -3960,7 +3960,6 @@
|
||||||
<string name="routing_engine_vehicle_type_foot">Chůze</string>
|
<string name="routing_engine_vehicle_type_foot">Chůze</string>
|
||||||
<string name="routing_engine_vehicle_type_bike">Kolo</string>
|
<string name="routing_engine_vehicle_type_bike">Kolo</string>
|
||||||
<string name="routing_engine_vehicle_type_car">Auto</string>
|
<string name="routing_engine_vehicle_type_car">Auto</string>
|
||||||
<string name="message_error_recheck_parameters">Chyba, zkontrolujte parametry</string>
|
|
||||||
<string name="copy_address">Kopírovat adresu</string>
|
<string name="copy_address">Kopírovat adresu</string>
|
||||||
<string name="online_routing_engine">Online navigační služba</string>
|
<string name="online_routing_engine">Online navigační služba</string>
|
||||||
<string name="online_routing_engines">Online navigační služby</string>
|
<string name="online_routing_engines">Online navigační služby</string>
|
||||||
|
|
|
@ -3962,7 +3962,6 @@
|
||||||
<string name="routing_engine_vehicle_type_foot">Zu Fuß</string>
|
<string name="routing_engine_vehicle_type_foot">Zu Fuß</string>
|
||||||
<string name="routing_engine_vehicle_type_bike">Fahrrad</string>
|
<string name="routing_engine_vehicle_type_bike">Fahrrad</string>
|
||||||
<string name="routing_engine_vehicle_type_car">Auto</string>
|
<string name="routing_engine_vehicle_type_car">Auto</string>
|
||||||
<string name="message_error_recheck_parameters">Fehler, Parameter erneut prüfen</string>
|
|
||||||
<string name="shared_string_subtype">Subtyp</string>
|
<string name="shared_string_subtype">Subtyp</string>
|
||||||
<string name="keep_it_empty_if_not">Leer lassen, wenn kein API-Schlüssel vorhanden</string>
|
<string name="keep_it_empty_if_not">Leer lassen, wenn kein API-Schlüssel vorhanden</string>
|
||||||
<string name="copy_address">Adresse kopieren</string>
|
<string name="copy_address">Adresse kopieren</string>
|
||||||
|
|
|
@ -3960,7 +3960,6 @@
|
||||||
<string name="routing_engine_vehicle_type_foot">Piediranto</string>
|
<string name="routing_engine_vehicle_type_foot">Piediranto</string>
|
||||||
<string name="routing_engine_vehicle_type_bike">Biciklo</string>
|
<string name="routing_engine_vehicle_type_bike">Biciklo</string>
|
||||||
<string name="routing_engine_vehicle_type_car">Aŭtomobilo</string>
|
<string name="routing_engine_vehicle_type_car">Aŭtomobilo</string>
|
||||||
<string name="message_error_recheck_parameters">Eraro, rekontrolu parametrojn</string>
|
|
||||||
<string name="copy_address">Kopii adreson</string>
|
<string name="copy_address">Kopii adreson</string>
|
||||||
<string name="online_routing_engine">Enreta navigilo</string>
|
<string name="online_routing_engine">Enreta navigilo</string>
|
||||||
<string name="online_routing_engines">Enretaj navigiloj</string>
|
<string name="online_routing_engines">Enretaj navigiloj</string>
|
||||||
|
|
|
@ -3963,7 +3963,6 @@
|
||||||
<string name="routing_engine_vehicle_type_foot">Peatón</string>
|
<string name="routing_engine_vehicle_type_foot">Peatón</string>
|
||||||
<string name="routing_engine_vehicle_type_bike">Bicicleta</string>
|
<string name="routing_engine_vehicle_type_bike">Bicicleta</string>
|
||||||
<string name="routing_engine_vehicle_type_car">Automóvil</string>
|
<string name="routing_engine_vehicle_type_car">Automóvil</string>
|
||||||
<string name="message_error_recheck_parameters">Error, vuelve a comprobar los parámetros</string>
|
|
||||||
<string name="copy_address">Copiar dirección</string>
|
<string name="copy_address">Copiar dirección</string>
|
||||||
<string name="online_routing_engine">Motor de navegación en línea</string>
|
<string name="online_routing_engine">Motor de navegación en línea</string>
|
||||||
<string name="online_routing_engines">Motores de navegación en línea</string>
|
<string name="online_routing_engines">Motores de navegación en línea</string>
|
||||||
|
|
|
@ -3933,6 +3933,5 @@ Area honi dagokio: %1$s x %2$s</string>
|
||||||
<string name="routing_engine_vehicle_type_foot">Oinez</string>
|
<string name="routing_engine_vehicle_type_foot">Oinez</string>
|
||||||
<string name="routing_engine_vehicle_type_bike">Bizikleta</string>
|
<string name="routing_engine_vehicle_type_bike">Bizikleta</string>
|
||||||
<string name="routing_engine_vehicle_type_car">Kotxea</string>
|
<string name="routing_engine_vehicle_type_car">Kotxea</string>
|
||||||
<string name="message_error_recheck_parameters">Errorea, egiaztatu parametroak berriro</string>
|
|
||||||
<string name="copy_address">Kopiatu helbidea</string>
|
<string name="copy_address">Kopiatu helbidea</string>
|
||||||
</resources>
|
</resources>
|
|
@ -3953,5 +3953,4 @@
|
||||||
<string name="routing_engine_vehicle_type_foot">پا</string>
|
<string name="routing_engine_vehicle_type_foot">پا</string>
|
||||||
<string name="routing_engine_vehicle_type_bike">دوچرخه</string>
|
<string name="routing_engine_vehicle_type_bike">دوچرخه</string>
|
||||||
<string name="routing_engine_vehicle_type_car">خودرو</string>
|
<string name="routing_engine_vehicle_type_car">خودرو</string>
|
||||||
<string name="message_error_recheck_parameters">خطا، پارامترها را بازبینی کنید</string>
|
|
||||||
</resources>
|
</resources>
|
|
@ -3947,7 +3947,6 @@
|
||||||
<string name="routing_engine_vehicle_type_foot">A pieds</string>
|
<string name="routing_engine_vehicle_type_foot">A pieds</string>
|
||||||
<string name="routing_engine_vehicle_type_bike">Vélo</string>
|
<string name="routing_engine_vehicle_type_bike">Vélo</string>
|
||||||
<string name="routing_engine_vehicle_type_car">Automobile</string>
|
<string name="routing_engine_vehicle_type_car">Automobile</string>
|
||||||
<string name="message_error_recheck_parameters">Erreur, vérifiez les paramètres</string>
|
|
||||||
<string name="add_online_routing_engine">Ajouter un moteur de routage en ligne</string>
|
<string name="add_online_routing_engine">Ajouter un moteur de routage en ligne</string>
|
||||||
<string name="edit_online_routing_engine">Modifier le moteur de routage en ligne</string>
|
<string name="edit_online_routing_engine">Modifier le moteur de routage en ligne</string>
|
||||||
<string name="online_routing_example_hint">L\'URL avec tous les paramètres sera de la forme :</string>
|
<string name="online_routing_example_hint">L\'URL avec tous les paramètres sera de la forme :</string>
|
||||||
|
|
|
@ -3968,7 +3968,6 @@ Lon %2$s</string>
|
||||||
<string name="routing_engine_vehicle_type_foot">Pé</string>
|
<string name="routing_engine_vehicle_type_foot">Pé</string>
|
||||||
<string name="routing_engine_vehicle_type_bike">Bicicleta</string>
|
<string name="routing_engine_vehicle_type_bike">Bicicleta</string>
|
||||||
<string name="routing_engine_vehicle_type_car">Coche</string>
|
<string name="routing_engine_vehicle_type_car">Coche</string>
|
||||||
<string name="message_error_recheck_parameters">Erro, verifica novamente os parámetros</string>
|
|
||||||
<string name="copy_address">Copiar enderezo</string>
|
<string name="copy_address">Copiar enderezo</string>
|
||||||
<string name="voice_prompts_timetable">Horarios dos avisos por voz</string>
|
<string name="voice_prompts_timetable">Horarios dos avisos por voz</string>
|
||||||
<string name="online_routing_engine">Motor de navegación en liña</string>
|
<string name="online_routing_engine">Motor de navegación en liña</string>
|
||||||
|
|
|
@ -3954,7 +3954,6 @@
|
||||||
<string name="keep_it_empty_if_not">Hagyja üresen, ha nem</string>
|
<string name="keep_it_empty_if_not">Hagyja üresen, ha nem</string>
|
||||||
<string name="online_routing_example_hint">Az összes paraméterrel rendelkező URL így néz ki:</string>
|
<string name="online_routing_example_hint">Az összes paraméterrel rendelkező URL így néz ki:</string>
|
||||||
<string name="test_route_calculation">Útvonaltervezés kipróbálása</string>
|
<string name="test_route_calculation">Útvonaltervezés kipróbálása</string>
|
||||||
<string name="message_error_recheck_parameters">Hiba, ellenőrizze újra a paramétereket</string>
|
|
||||||
<string name="copy_address">Cím másolása</string>
|
<string name="copy_address">Cím másolása</string>
|
||||||
<string name="online_routing_engine">Online útvonaltervező</string>
|
<string name="online_routing_engine">Online útvonaltervező</string>
|
||||||
<string name="online_routing_engines">Online útvonaltervezők</string>
|
<string name="online_routing_engines">Online útvonaltervezők</string>
|
||||||
|
|
|
@ -3965,6 +3965,5 @@
|
||||||
<string name="routing_engine_vehicle_type_foot">Gangandi</string>
|
<string name="routing_engine_vehicle_type_foot">Gangandi</string>
|
||||||
<string name="routing_engine_vehicle_type_bike">Hjólandi</string>
|
<string name="routing_engine_vehicle_type_bike">Hjólandi</string>
|
||||||
<string name="routing_engine_vehicle_type_car">Bíll</string>
|
<string name="routing_engine_vehicle_type_car">Bíll</string>
|
||||||
<string name="message_error_recheck_parameters">Villa, yfirfarðu breytur</string>
|
|
||||||
<string name="copy_address">Afrita heimilisfang</string>
|
<string name="copy_address">Afrita heimilisfang</string>
|
||||||
</resources>
|
</resources>
|
|
@ -3963,7 +3963,6 @@
|
||||||
<string name="routing_engine_vehicle_type_foot">ברגל</string>
|
<string name="routing_engine_vehicle_type_foot">ברגל</string>
|
||||||
<string name="routing_engine_vehicle_type_bike">אופנוע</string>
|
<string name="routing_engine_vehicle_type_bike">אופנוע</string>
|
||||||
<string name="routing_engine_vehicle_type_car">מכונית</string>
|
<string name="routing_engine_vehicle_type_car">מכונית</string>
|
||||||
<string name="message_error_recheck_parameters">שגיאה, נא לבדוק את המשתנים מחדש</string>
|
|
||||||
<string name="copy_address">העתקת כתובת</string>
|
<string name="copy_address">העתקת כתובת</string>
|
||||||
<string name="online_routing_engine">מנוע ניווט מקוון</string>
|
<string name="online_routing_engine">מנוע ניווט מקוון</string>
|
||||||
<string name="online_routing_engines">מנועי ניווט מקוונים</string>
|
<string name="online_routing_engines">מנועי ניווט מקוונים</string>
|
||||||
|
|
|
@ -2449,7 +2449,6 @@
|
||||||
<string name="subscription_paused_title">OsmAndის გამოწერა დაპაუზებულია</string>
|
<string name="subscription_paused_title">OsmAndის გამოწერა დაპაუზებულია</string>
|
||||||
<string name="subscription_on_hold_title">OsmAndის გამოწერა შეჩერებულია</string>
|
<string name="subscription_on_hold_title">OsmAndის გამოწერა შეჩერებულია</string>
|
||||||
<string name="online_routing_example_hint">URL ყველა პარამეტრით აი ასეთი იქნება:</string>
|
<string name="online_routing_example_hint">URL ყველა პარამეტრით აი ასეთი იქნება:</string>
|
||||||
<string name="message_error_recheck_parameters">შეცდომა, გადაამოწმეთ პარამეტრები</string>
|
|
||||||
<string name="mapillary_image">Mapillary-ის გამოსახულება</string>
|
<string name="mapillary_image">Mapillary-ის გამოსახულება</string>
|
||||||
<string name="mapillary_widget">Mapillary-ის ღილაკი</string>
|
<string name="mapillary_widget">Mapillary-ის ღილაკი</string>
|
||||||
<string name="srtm_color_scheme">ფერთა გამა</string>
|
<string name="srtm_color_scheme">ფერთა გამა</string>
|
||||||
|
|
|
@ -2770,7 +2770,6 @@ Tai yra puikus būdas paremti OsmAnd ir OSM, jei jie jums patinka.</string>
|
||||||
<string name="test_route_calculation">Patikrinti maršruto apskaičiavimą</string>
|
<string name="test_route_calculation">Patikrinti maršruto apskaičiavimą</string>
|
||||||
<string name="routing_engine_vehicle_type_bike">Dviratis</string>
|
<string name="routing_engine_vehicle_type_bike">Dviratis</string>
|
||||||
<string name="routing_engine_vehicle_type_car">Automobilis</string>
|
<string name="routing_engine_vehicle_type_car">Automobilis</string>
|
||||||
<string name="message_error_recheck_parameters">Įvyko klaida, patikrinkite paametrus</string>
|
|
||||||
<string name="copy_address">Kopijuoti adresą</string>
|
<string name="copy_address">Kopijuoti adresą</string>
|
||||||
<string name="shared_string_folders">Folderiai</string>
|
<string name="shared_string_folders">Folderiai</string>
|
||||||
<string name="select_folder">Pasirinkite folderį</string>
|
<string name="select_folder">Pasirinkite folderį</string>
|
||||||
|
|
|
@ -3916,7 +3916,6 @@
|
||||||
<string name="routing_engine_vehicle_type_foot">Te voet</string>
|
<string name="routing_engine_vehicle_type_foot">Te voet</string>
|
||||||
<string name="routing_engine_vehicle_type_bike">Fiets</string>
|
<string name="routing_engine_vehicle_type_bike">Fiets</string>
|
||||||
<string name="routing_engine_vehicle_type_car">Auto</string>
|
<string name="routing_engine_vehicle_type_car">Auto</string>
|
||||||
<string name="message_error_recheck_parameters">Fout, controleer parameters opnieuw</string>
|
|
||||||
<string name="copy_address">Kopieer adres</string>
|
<string name="copy_address">Kopieer adres</string>
|
||||||
<string name="online_routing_engine">Online routeplanningssysteem</string>
|
<string name="online_routing_engine">Online routeplanningssysteem</string>
|
||||||
<string name="online_routing_engines">Online routeplanningssystemen</string>
|
<string name="online_routing_engines">Online routeplanningssystemen</string>
|
||||||
|
|
|
@ -3956,7 +3956,6 @@
|
||||||
<string name="test_route_calculation">Obliczanie trasy testowej</string>
|
<string name="test_route_calculation">Obliczanie trasy testowej</string>
|
||||||
<string name="routing_engine_vehicle_type_bike">Rower</string>
|
<string name="routing_engine_vehicle_type_bike">Rower</string>
|
||||||
<string name="routing_engine_vehicle_type_car">Samochód</string>
|
<string name="routing_engine_vehicle_type_car">Samochód</string>
|
||||||
<string name="message_error_recheck_parameters">Błąd, ponownie sprawdź parametry</string>
|
|
||||||
<string name="copy_address">Skopiuj adres</string>
|
<string name="copy_address">Skopiuj adres</string>
|
||||||
<string name="routing_engine_vehicle_type_driving">Jazda</string>
|
<string name="routing_engine_vehicle_type_driving">Jazda</string>
|
||||||
<string name="routing_engine_vehicle_type_foot">Stopa</string>
|
<string name="routing_engine_vehicle_type_foot">Stopa</string>
|
||||||
|
|
|
@ -3955,7 +3955,6 @@
|
||||||
<string name="routing_engine_vehicle_type_foot">Pé</string>
|
<string name="routing_engine_vehicle_type_foot">Pé</string>
|
||||||
<string name="routing_engine_vehicle_type_bike">Bicicleta</string>
|
<string name="routing_engine_vehicle_type_bike">Bicicleta</string>
|
||||||
<string name="routing_engine_vehicle_type_car">Carro</string>
|
<string name="routing_engine_vehicle_type_car">Carro</string>
|
||||||
<string name="message_error_recheck_parameters">Erro, verifique novamente os parâmetros</string>
|
|
||||||
<string name="copy_address">Copiar endereço</string>
|
<string name="copy_address">Copiar endereço</string>
|
||||||
<string name="online_routing_engine">Motor de encaminhamento online</string>
|
<string name="online_routing_engine">Motor de encaminhamento online</string>
|
||||||
<string name="online_routing_engines">Mecanismos de roteamento online</string>
|
<string name="online_routing_engines">Mecanismos de roteamento online</string>
|
||||||
|
|
|
@ -3957,7 +3957,6 @@
|
||||||
<string name="routing_engine_vehicle_type_foot">A pee</string>
|
<string name="routing_engine_vehicle_type_foot">A pee</string>
|
||||||
<string name="routing_engine_vehicle_type_bike">Bitzicleta</string>
|
<string name="routing_engine_vehicle_type_bike">Bitzicleta</string>
|
||||||
<string name="routing_engine_vehicle_type_car">Màchina</string>
|
<string name="routing_engine_vehicle_type_car">Màchina</string>
|
||||||
<string name="message_error_recheck_parameters">Errore, torra a verificare sos paràmetros</string>
|
|
||||||
<string name="copy_address">Còpia s\'indiritzu</string>
|
<string name="copy_address">Còpia s\'indiritzu</string>
|
||||||
<string name="online_routing_engine">Motore de càrculu in lìnia</string>
|
<string name="online_routing_engine">Motore de càrculu in lìnia</string>
|
||||||
<string name="online_routing_engines">Motores de càrculu in lìnia</string>
|
<string name="online_routing_engines">Motores de càrculu in lìnia</string>
|
||||||
|
|
|
@ -3955,7 +3955,6 @@
|
||||||
<string name="routing_engine_vehicle_type_foot">Chôdza</string>
|
<string name="routing_engine_vehicle_type_foot">Chôdza</string>
|
||||||
<string name="routing_engine_vehicle_type_bike">Bicykel</string>
|
<string name="routing_engine_vehicle_type_bike">Bicykel</string>
|
||||||
<string name="routing_engine_vehicle_type_car">Auto</string>
|
<string name="routing_engine_vehicle_type_car">Auto</string>
|
||||||
<string name="message_error_recheck_parameters">Chyba, skontrolujte parametre</string>
|
|
||||||
<string name="copy_address">Kopírovať adresu</string>
|
<string name="copy_address">Kopírovať adresu</string>
|
||||||
<string name="online_routing_engine">Online navigačná služba</string>
|
<string name="online_routing_engine">Online navigačná služba</string>
|
||||||
<string name="online_routing_engines">Online navigačné služby</string>
|
<string name="online_routing_engines">Online navigačné služby</string>
|
||||||
|
|
|
@ -3961,7 +3961,6 @@
|
||||||
<string name="routing_engine_vehicle_type_foot">Yürüme</string>
|
<string name="routing_engine_vehicle_type_foot">Yürüme</string>
|
||||||
<string name="routing_engine_vehicle_type_bike">Bisiklet</string>
|
<string name="routing_engine_vehicle_type_bike">Bisiklet</string>
|
||||||
<string name="routing_engine_vehicle_type_car">Araba</string>
|
<string name="routing_engine_vehicle_type_car">Araba</string>
|
||||||
<string name="message_error_recheck_parameters">Hata, parametreleri tekrar gözden geçirin</string>
|
|
||||||
<string name="copy_address">Adresi kopyala</string>
|
<string name="copy_address">Adresi kopyala</string>
|
||||||
<string name="online_routing_engine">Çevrim içi yönlendirme motoru</string>
|
<string name="online_routing_engine">Çevrim içi yönlendirme motoru</string>
|
||||||
<string name="online_routing_engines">Çevrim içi yönlendirme motorları</string>
|
<string name="online_routing_engines">Çevrim içi yönlendirme motorları</string>
|
||||||
|
|
|
@ -3959,7 +3959,6 @@
|
||||||
<string name="routing_engine_vehicle_type_foot">Пішки</string>
|
<string name="routing_engine_vehicle_type_foot">Пішки</string>
|
||||||
<string name="routing_engine_vehicle_type_bike">Велосипед</string>
|
<string name="routing_engine_vehicle_type_bike">Велосипед</string>
|
||||||
<string name="routing_engine_vehicle_type_car">Автомобіль</string>
|
<string name="routing_engine_vehicle_type_car">Автомобіль</string>
|
||||||
<string name="message_error_recheck_parameters">Помилка, повторно перевірте параметри</string>
|
|
||||||
<string name="copy_address">Копіювати адресу</string>
|
<string name="copy_address">Копіювати адресу</string>
|
||||||
<string name="online_routing_engine">Мережний рушій маршрутизації</string>
|
<string name="online_routing_engine">Мережний рушій маршрутизації</string>
|
||||||
<string name="online_routing_engines">Мережні рушії маршрутизації</string>
|
<string name="online_routing_engines">Мережні рушії маршрутизації</string>
|
||||||
|
|
|
@ -3953,7 +3953,6 @@
|
||||||
<string name="routing_engine_vehicle_type_foot">步行</string>
|
<string name="routing_engine_vehicle_type_foot">步行</string>
|
||||||
<string name="routing_engine_vehicle_type_bike">自行車</string>
|
<string name="routing_engine_vehicle_type_bike">自行車</string>
|
||||||
<string name="routing_engine_vehicle_type_car">汽車</string>
|
<string name="routing_engine_vehicle_type_car">汽車</string>
|
||||||
<string name="message_error_recheck_parameters">錯誤,重新檢查參數</string>
|
|
||||||
<string name="copy_address">複製地址</string>
|
<string name="copy_address">複製地址</string>
|
||||||
<string name="online_routing_engine">線上路線計算引擎</string>
|
<string name="online_routing_engine">線上路線計算引擎</string>
|
||||||
<string name="online_routing_engines">線上路線計算引擎</string>
|
<string name="online_routing_engines">線上路線計算引擎</string>
|
||||||
|
|
|
@ -12,6 +12,23 @@
|
||||||
|
|
||||||
-->
|
-->
|
||||||
|
|
||||||
|
<string name="message_name_is_already_exists">The name is already exists</string>
|
||||||
|
<string name="message_server_error">Server error: %1$s</string>
|
||||||
|
<string name="routing_engine_vehicle_type_mtb">MTB</string>
|
||||||
|
<string name="routing_engine_vehicle_type_racingbike">Racing bike</string>
|
||||||
|
<string name="routing_engine_vehicle_type_scooter">Scooter</string>
|
||||||
|
<string name="routing_engine_vehicle_type_truck">Truck</string>
|
||||||
|
<string name="routing_engine_vehicle_type_small_truck">Small truck</string>
|
||||||
|
<string name="routing_engine_vehicle_type_hgv">HGV</string>
|
||||||
|
<string name="routing_engine_vehicle_type_cycling_regular">Regular cycling</string>
|
||||||
|
<string name="routing_engine_vehicle_type_cycling_road">Road cycling</string>
|
||||||
|
<string name="routing_engine_vehicle_type_cycling_mountain">Mountain cycling</string>
|
||||||
|
<string name="routing_engine_vehicle_type_cycling_electric">Electric cycling</string>
|
||||||
|
<string name="routing_engine_vehicle_type_walking">Walking</string>
|
||||||
|
<string name="routing_engine_vehicle_type_hiking">Hiking</string>
|
||||||
|
<string name="routing_engine_vehicle_type_wheelchair">Wheelchair</string>
|
||||||
|
<string name="show_track_on_map">Show track on map</string>
|
||||||
|
<string name="start_recording">Start recording</string>
|
||||||
<string name="announcement_time_title">Announcement time</string>
|
<string name="announcement_time_title">Announcement time</string>
|
||||||
<string name="announcement_time_descr">Announcement time of different voice prompts depends on prompt type, current navigation speed and default navigation speed.</string>
|
<string name="announcement_time_descr">Announcement time of different voice prompts depends on prompt type, current navigation speed and default navigation speed.</string>
|
||||||
<string name="announcement_time_intervals">Time and distance intervals</string>
|
<string name="announcement_time_intervals">Time and distance intervals</string>
|
||||||
|
@ -35,7 +52,6 @@
|
||||||
<string name="online_routing_engines">Online routing engines</string>
|
<string name="online_routing_engines">Online routing engines</string>
|
||||||
<string name="online_routing_engine">Online routing engine</string>
|
<string name="online_routing_engine">Online routing engine</string>
|
||||||
<string name="copy_address">Copy address</string>
|
<string name="copy_address">Copy address</string>
|
||||||
<string name="message_error_recheck_parameters">Error, recheck parameters</string>
|
|
||||||
<string name="routing_engine_vehicle_type_car">Car</string>
|
<string name="routing_engine_vehicle_type_car">Car</string>
|
||||||
<string name="routing_engine_vehicle_type_bike">Bike</string>
|
<string name="routing_engine_vehicle_type_bike">Bike</string>
|
||||||
<string name="routing_engine_vehicle_type_foot">Foot</string>
|
<string name="routing_engine_vehicle_type_foot">Foot</string>
|
||||||
|
|
158
OsmAnd/src-gms/net/osmand/plus/LocationServiceHelperImpl.java
Normal file
158
OsmAnd/src-gms/net/osmand/plus/LocationServiceHelperImpl.java
Normal file
|
@ -0,0 +1,158 @@
|
||||||
|
package net.osmand.plus;
|
||||||
|
|
||||||
|
import android.location.Location;
|
||||||
|
import android.os.Looper;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.google.android.gms.location.FusedLocationProviderClient;
|
||||||
|
import com.google.android.gms.location.LocationAvailability;
|
||||||
|
import com.google.android.gms.location.LocationRequest;
|
||||||
|
import com.google.android.gms.location.LocationResult;
|
||||||
|
import com.google.android.gms.location.LocationServices;
|
||||||
|
import com.google.android.gms.tasks.OnSuccessListener;
|
||||||
|
import com.google.android.gms.tasks.Task;
|
||||||
|
import com.google.android.gms.tasks.Tasks;
|
||||||
|
|
||||||
|
import net.osmand.PlatformUtil;
|
||||||
|
import net.osmand.plus.helpers.DayNightHelper;
|
||||||
|
import net.osmand.plus.helpers.LocationServiceHelper;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.TimeoutException;
|
||||||
|
|
||||||
|
public class LocationServiceHelperImpl extends LocationServiceHelper {
|
||||||
|
|
||||||
|
private static final Log LOG = PlatformUtil.getLog(DayNightHelper.class);
|
||||||
|
|
||||||
|
private final OsmandApplication app;
|
||||||
|
|
||||||
|
// FusedLocationProviderClient - Main class for receiving location updates.
|
||||||
|
private final FusedLocationProviderClient fusedLocationProviderClient;
|
||||||
|
|
||||||
|
// LocationRequest - Requirements for the location updates, i.e., how often you should receive
|
||||||
|
// updates, the priority, etc.
|
||||||
|
private final LocationRequest fusedLocationRequest;
|
||||||
|
|
||||||
|
// LocationCallback - Called when FusedLocationProviderClient has a new Location.
|
||||||
|
private final com.google.android.gms.location.LocationCallback fusedLocationCallback;
|
||||||
|
|
||||||
|
private LocationCallback locationCallback;
|
||||||
|
|
||||||
|
public LocationServiceHelperImpl(@NonNull OsmandApplication app) {
|
||||||
|
this.app = app;
|
||||||
|
|
||||||
|
fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(app);
|
||||||
|
|
||||||
|
fusedLocationRequest = new LocationRequest()
|
||||||
|
// Sets the desired interval for active location updates. This interval is inexact. You
|
||||||
|
// may not receive updates at all if no location sources are available, or you may
|
||||||
|
// receive them less frequently than requested. You may also receive updates more
|
||||||
|
// frequently than requested if other applications are requesting location at a more
|
||||||
|
// frequent interval.
|
||||||
|
//
|
||||||
|
// IMPORTANT NOTE: Apps running on Android 8.0 and higher devices (regardless of
|
||||||
|
// targetSdkVersion) may receive updates less frequently than this interval when the app
|
||||||
|
// is no longer in the foreground.
|
||||||
|
.setInterval(100)
|
||||||
|
|
||||||
|
// Sets the fastest rate for active location updates. This interval is exact, and your
|
||||||
|
// application will never receive updates more frequently than this value.
|
||||||
|
.setFastestInterval(50)
|
||||||
|
|
||||||
|
// Sets the maximum time when batched location updates are delivered. Updates may be
|
||||||
|
// delivered sooner than this interval.
|
||||||
|
.setMaxWaitTime(200)
|
||||||
|
|
||||||
|
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
|
||||||
|
|
||||||
|
fusedLocationCallback = new com.google.android.gms.location.LocationCallback() {
|
||||||
|
@Override
|
||||||
|
public void onLocationResult(LocationResult locationResult) {
|
||||||
|
LocationCallback locationCallback = LocationServiceHelperImpl.this.locationCallback;
|
||||||
|
if (locationCallback != null) {
|
||||||
|
Location location = locationResult != null ? locationResult.getLastLocation() : null;
|
||||||
|
net.osmand.Location l = convertLocation(location);
|
||||||
|
locationCallback.onLocationResult(l == null
|
||||||
|
? Collections.<net.osmand.Location>emptyList() : Collections.singletonList(l));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLocationAvailability(LocationAvailability locationAvailability) {
|
||||||
|
LocationCallback locationCallback = LocationServiceHelperImpl.this.locationCallback;
|
||||||
|
if (locationAvailability != null && locationCallback != null) {
|
||||||
|
locationCallback.onLocationAvailability(locationAvailability.isLocationAvailable());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void requestLocationUpdates(@NonNull LocationCallback locationCallback) {
|
||||||
|
this.locationCallback = locationCallback;
|
||||||
|
// request location updates
|
||||||
|
try {
|
||||||
|
fusedLocationProviderClient.requestLocationUpdates(
|
||||||
|
fusedLocationRequest, fusedLocationCallback, Looper.myLooper());
|
||||||
|
} catch (SecurityException e) {
|
||||||
|
LOG.debug("Location service permission not granted");
|
||||||
|
throw e;
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
LOG.debug("GPS location provider not available");
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isNetworkLocationUpdatesSupported() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void requestNetworkLocationUpdates(@NonNull LocationCallback locationCallback) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeLocationUpdates() {
|
||||||
|
// remove location updates
|
||||||
|
try {
|
||||||
|
fusedLocationProviderClient.removeLocationUpdates(fusedLocationCallback);
|
||||||
|
} catch (SecurityException e) {
|
||||||
|
LOG.debug("Location service permission not granted", e);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public net.osmand.Location getFirstTimeRunDefaultLocation() {
|
||||||
|
final net.osmand.Location[] location = {null};
|
||||||
|
/*
|
||||||
|
try {
|
||||||
|
Task<Location> lastLocation = fusedLocationProviderClient.getLastLocation();
|
||||||
|
lastLocation.addOnSuccessListener(new OnSuccessListener<Location>() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(Location loc) {
|
||||||
|
location[0] = convertLocation(loc);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (SecurityException e) {
|
||||||
|
LOG.debug("Location service permission not granted");
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
LOG.debug("GPS location provider not available");
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
return location[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private net.osmand.Location convertLocation(@Nullable Location location) {
|
||||||
|
return location == null ? null : OsmAndLocationProvider.convertLocation(location, app);
|
||||||
|
}
|
||||||
|
}
|
188
OsmAnd/src-nogms/net/osmand/plus/LocationServiceHelperImpl.java
Normal file
188
OsmAnd/src-nogms/net/osmand/plus/LocationServiceHelperImpl.java
Normal file
|
@ -0,0 +1,188 @@
|
||||||
|
package net.osmand.plus;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.location.Location;
|
||||||
|
import android.location.LocationListener;
|
||||||
|
import android.location.LocationManager;
|
||||||
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import net.osmand.PlatformUtil;
|
||||||
|
import net.osmand.plus.helpers.DayNightHelper;
|
||||||
|
import net.osmand.plus.helpers.LocationServiceHelper;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static android.content.Context.LOCATION_SERVICE;
|
||||||
|
|
||||||
|
public class LocationServiceHelperImpl extends LocationServiceHelper implements LocationListener {
|
||||||
|
|
||||||
|
private static final Log LOG = PlatformUtil.getLog(DayNightHelper.class);
|
||||||
|
|
||||||
|
private final OsmandApplication app;
|
||||||
|
|
||||||
|
private LocationCallback locationCallback;
|
||||||
|
private LocationCallback networkLocationCallback;
|
||||||
|
private final LinkedList<LocationListener> networkListeners = new LinkedList<>();
|
||||||
|
|
||||||
|
// Working with location checkListeners
|
||||||
|
private class NetworkListener implements LocationListener {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLocationChanged(Location location) {
|
||||||
|
LocationCallback locationCallback = LocationServiceHelperImpl.this.networkLocationCallback;
|
||||||
|
if (locationCallback != null) {
|
||||||
|
net.osmand.Location l = convertLocation(location);
|
||||||
|
locationCallback.onLocationResult(l == null
|
||||||
|
? Collections.<net.osmand.Location>emptyList() : Collections.singletonList(l));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onProviderDisabled(String provider) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onProviderEnabled(String provider) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStatusChanged(String provider, int status, Bundle extras) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocationServiceHelperImpl(@NonNull OsmandApplication app) {
|
||||||
|
this.app = app;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void requestLocationUpdates(@NonNull LocationCallback locationCallback) {
|
||||||
|
this.locationCallback = locationCallback;
|
||||||
|
// request location updates
|
||||||
|
LocationManager locationManager = (LocationManager) app.getSystemService(LOCATION_SERVICE);
|
||||||
|
try {
|
||||||
|
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
|
||||||
|
} catch (SecurityException e) {
|
||||||
|
LOG.debug("Location service permission not granted");
|
||||||
|
throw e;
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
LOG.debug("GPS location provider not available");
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isNetworkLocationUpdatesSupported() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void requestNetworkLocationUpdates(@NonNull LocationCallback locationCallback) {
|
||||||
|
this.networkLocationCallback = locationCallback;
|
||||||
|
// request location updates
|
||||||
|
LocationManager locationManager = (LocationManager) app.getSystemService(LOCATION_SERVICE);
|
||||||
|
List<String> providers = locationManager.getProviders(true);
|
||||||
|
for (String provider : providers) {
|
||||||
|
if (provider == null || provider.equals(LocationManager.GPS_PROVIDER)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
NetworkListener networkListener = new NetworkListener();
|
||||||
|
locationManager.requestLocationUpdates(provider, 0, 0, networkListener);
|
||||||
|
networkListeners.add(networkListener);
|
||||||
|
} catch (SecurityException e) {
|
||||||
|
LOG.debug(provider + " location service permission not granted");
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
LOG.debug(provider + " location provider not available");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeLocationUpdates() {
|
||||||
|
// remove location updates
|
||||||
|
LocationManager locationManager = (LocationManager) app.getSystemService(LOCATION_SERVICE);
|
||||||
|
try {
|
||||||
|
locationManager.removeUpdates(this);
|
||||||
|
} catch (SecurityException e) {
|
||||||
|
LOG.debug("Location service permission not granted", e);
|
||||||
|
throw e;
|
||||||
|
} finally {
|
||||||
|
while (!networkListeners.isEmpty()) {
|
||||||
|
LocationListener listener = networkListeners.poll();
|
||||||
|
if (listener != null) {
|
||||||
|
locationManager.removeUpdates(listener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public net.osmand.Location getFirstTimeRunDefaultLocation() {
|
||||||
|
LocationManager locationManager = (LocationManager) app.getSystemService(Context.LOCATION_SERVICE);
|
||||||
|
List<String> providers = new ArrayList<>(locationManager.getProviders(true));
|
||||||
|
// note, passive provider is from API_LEVEL 8 but it is a constant, we can check for it.
|
||||||
|
// constant should not be changed in future
|
||||||
|
int passiveFirst = providers.indexOf(LocationManager.PASSIVE_PROVIDER);
|
||||||
|
// put passive provider to first place
|
||||||
|
if (passiveFirst > -1) {
|
||||||
|
providers.add(0, providers.remove(passiveFirst));
|
||||||
|
}
|
||||||
|
// find location
|
||||||
|
for (String provider : providers) {
|
||||||
|
try {
|
||||||
|
net.osmand.Location location = convertLocation(locationManager.getLastKnownLocation(provider));
|
||||||
|
if (location != null) {
|
||||||
|
return location;
|
||||||
|
}
|
||||||
|
} catch (SecurityException e) {
|
||||||
|
// location service permission not granted
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// location provider not available
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private net.osmand.Location convertLocation(@Nullable Location location) {
|
||||||
|
return location == null ? null : OsmAndLocationProvider.convertLocation(location, app);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLocationChanged(Location location) {
|
||||||
|
LocationCallback locationCallback = this.locationCallback;
|
||||||
|
if (locationCallback != null) {
|
||||||
|
net.osmand.Location l = convertLocation(location);
|
||||||
|
locationCallback.onLocationResult(l == null
|
||||||
|
? Collections.<net.osmand.Location>emptyList() : Collections.singletonList(l));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStatusChanged(String provider, int status, Bundle extras) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onProviderEnabled(String provider) {
|
||||||
|
LocationCallback locationCallback = this.locationCallback;
|
||||||
|
if (locationCallback != null) {
|
||||||
|
locationCallback.onLocationAvailability(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onProviderDisabled(String provider) {
|
||||||
|
LocationCallback locationCallback = this.locationCallback;
|
||||||
|
if (locationCallback != null) {
|
||||||
|
locationCallback.onLocationAvailability(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,20 +4,24 @@ import android.app.Notification;
|
||||||
import android.app.Service;
|
import android.app.Service;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.location.Location;
|
|
||||||
import android.location.LocationListener;
|
|
||||||
import android.location.LocationManager;
|
import android.location.LocationManager;
|
||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
import android.os.Bundle;
|
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
import net.osmand.Location;
|
||||||
import net.osmand.PlatformUtil;
|
import net.osmand.PlatformUtil;
|
||||||
|
import net.osmand.plus.helpers.LocationServiceHelper;
|
||||||
|
import net.osmand.plus.helpers.LocationServiceHelper.LocationCallback;
|
||||||
import net.osmand.plus.notifications.OsmandNotification;
|
import net.osmand.plus.notifications.OsmandNotification;
|
||||||
import net.osmand.plus.settings.backend.OsmandSettings;
|
import net.osmand.plus.settings.backend.OsmandSettings;
|
||||||
|
|
||||||
public class NavigationService extends Service implements LocationListener {
|
import java.util.List;
|
||||||
|
|
||||||
|
public class NavigationService extends Service {
|
||||||
|
|
||||||
public static class NavigationServiceBinder extends Binder {
|
public static class NavigationServiceBinder extends Binder {
|
||||||
}
|
}
|
||||||
|
@ -29,11 +33,11 @@ public class NavigationService extends Service implements LocationListener {
|
||||||
|
|
||||||
private final NavigationServiceBinder binder = new NavigationServiceBinder();
|
private final NavigationServiceBinder binder = new NavigationServiceBinder();
|
||||||
|
|
||||||
private String serviceOffProvider;
|
|
||||||
private OsmandSettings settings;
|
private OsmandSettings settings;
|
||||||
|
|
||||||
protected int usedBy = 0;
|
protected int usedBy = 0;
|
||||||
private OsmAndLocationProvider locationProvider;
|
private OsmAndLocationProvider locationProvider;
|
||||||
|
private LocationServiceHelper locationServiceHelper;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IBinder onBind(Intent intent) {
|
public IBinder onBind(Intent intent) {
|
||||||
|
@ -72,21 +76,37 @@ public class NavigationService extends Service implements LocationListener {
|
||||||
settings = app.getSettings();
|
settings = app.getSettings();
|
||||||
usedBy = intent.getIntExtra(USAGE_INTENT, 0);
|
usedBy = intent.getIntExtra(USAGE_INTENT, 0);
|
||||||
|
|
||||||
// use only gps provider
|
|
||||||
serviceOffProvider = LocationManager.GPS_PROVIDER;
|
|
||||||
locationProvider = app.getLocationProvider();
|
locationProvider = app.getLocationProvider();
|
||||||
|
locationServiceHelper = app.createLocationServiceHelper();
|
||||||
app.setNavigationService(this);
|
app.setNavigationService(this);
|
||||||
|
|
||||||
// request location updates
|
// request location updates
|
||||||
LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
|
|
||||||
try {
|
try {
|
||||||
locationManager.requestLocationUpdates(serviceOffProvider, 0, 0, NavigationService.this);
|
locationServiceHelper.requestLocationUpdates(new LocationCallback() {
|
||||||
|
@Override
|
||||||
|
public void onLocationResult(@NonNull List<net.osmand.Location> locations) {
|
||||||
|
if (!locations.isEmpty()) {
|
||||||
|
Location location = locations.get(locations.size() - 1);
|
||||||
|
if (!settings.MAP_ACTIVITY_ENABLED.get()) {
|
||||||
|
locationProvider.setLocationFromService(location);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLocationAvailability(boolean locationAvailable) {
|
||||||
|
if (!locationAvailable) {
|
||||||
|
OsmandApplication app = (OsmandApplication) getApplication();
|
||||||
|
if (app != null) {
|
||||||
|
app.showToastMessage(getString(R.string.off_router_service_no_gps_available));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
} catch (SecurityException e) {
|
} catch (SecurityException e) {
|
||||||
Toast.makeText(this, R.string.no_location_permission, Toast.LENGTH_LONG).show();
|
Toast.makeText(this, R.string.no_location_permission, Toast.LENGTH_LONG).show();
|
||||||
Log.d(PlatformUtil.TAG, "Location service permission not granted"); //$NON-NLS-1$
|
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
Toast.makeText(this, R.string.gps_not_available, Toast.LENGTH_LONG).show();
|
Toast.makeText(this, R.string.gps_not_available, Toast.LENGTH_LONG).show();
|
||||||
Log.d(PlatformUtil.TAG, "GPS location provider not available"); //$NON-NLS-1$
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// registering icon at top level
|
// registering icon at top level
|
||||||
|
@ -117,11 +137,10 @@ public class NavigationService extends Service implements LocationListener {
|
||||||
app.setNavigationService(null);
|
app.setNavigationService(null);
|
||||||
usedBy = 0;
|
usedBy = 0;
|
||||||
// remove updates
|
// remove updates
|
||||||
LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
|
|
||||||
try {
|
try {
|
||||||
locationManager.removeUpdates(this);
|
locationServiceHelper.removeLocationUpdates();
|
||||||
} catch (SecurityException e) {
|
} catch (SecurityException e) {
|
||||||
Log.d(PlatformUtil.TAG, "Location service permission not granted"); //$NON-NLS-1$
|
// Location service permission not granted
|
||||||
}
|
}
|
||||||
// remove notification
|
// remove notification
|
||||||
stopForeground(Boolean.TRUE);
|
stopForeground(Boolean.TRUE);
|
||||||
|
@ -134,29 +153,6 @@ public class NavigationService extends Service implements LocationListener {
|
||||||
}, 500);
|
}, 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onLocationChanged(Location l) {
|
|
||||||
if (l != null && !settings.MAP_ACTIVITY_ENABLED.get()) {
|
|
||||||
net.osmand.Location location = OsmAndLocationProvider.convertLocation(l, (OsmandApplication) getApplication());
|
|
||||||
locationProvider.setLocationFromService(location);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onProviderDisabled(String provider) {
|
|
||||||
Toast.makeText(this, getString(R.string.off_router_service_no_gps_available), Toast.LENGTH_LONG).show();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onProviderEnabled(String provider) {
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onStatusChanged(String provider, int status, Bundle extras) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTaskRemoved(Intent rootIntent) {
|
public void onTaskRemoved(Intent rootIntent) {
|
||||||
OsmandApplication app = ((OsmandApplication) getApplication());
|
OsmandApplication app = ((OsmandApplication) getApplication());
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package net.osmand.plus;
|
package net.osmand.plus;
|
||||||
|
|
||||||
import android.Manifest;
|
import android.Manifest;
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
|
@ -16,7 +17,6 @@ import android.location.GpsSatellite;
|
||||||
import android.location.GpsStatus;
|
import android.location.GpsStatus;
|
||||||
import android.location.GpsStatus.Listener;
|
import android.location.GpsStatus.Listener;
|
||||||
import android.location.Location;
|
import android.location.Location;
|
||||||
import android.location.LocationListener;
|
|
||||||
import android.location.LocationManager;
|
import android.location.LocationManager;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Build.VERSION;
|
import android.os.Build.VERSION;
|
||||||
|
@ -25,6 +25,7 @@ import android.os.Bundle;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.appcompat.app.AlertDialog;
|
import androidx.appcompat.app.AlertDialog;
|
||||||
import androidx.core.app.ActivityCompat;
|
import androidx.core.app.ActivityCompat;
|
||||||
|
@ -38,8 +39,9 @@ import net.osmand.binary.RouteDataObject;
|
||||||
import net.osmand.data.LatLon;
|
import net.osmand.data.LatLon;
|
||||||
import net.osmand.data.QuadPoint;
|
import net.osmand.data.QuadPoint;
|
||||||
import net.osmand.plus.TargetPointsHelper.TargetPoint;
|
import net.osmand.plus.TargetPointsHelper.TargetPoint;
|
||||||
import net.osmand.plus.routing.RoutingHelper;
|
import net.osmand.plus.helpers.LocationServiceHelper;
|
||||||
import net.osmand.plus.routing.RouteSegmentSearchResult;
|
import net.osmand.plus.routing.RouteSegmentSearchResult;
|
||||||
|
import net.osmand.plus.routing.RoutingHelper;
|
||||||
import net.osmand.plus.settings.backend.ApplicationMode;
|
import net.osmand.plus.settings.backend.ApplicationMode;
|
||||||
import net.osmand.plus.settings.backend.OsmandSettings;
|
import net.osmand.plus.settings.backend.OsmandSettings;
|
||||||
import net.osmand.router.RouteSegmentResult;
|
import net.osmand.router.RouteSegmentResult;
|
||||||
|
@ -47,8 +49,6 @@ import net.osmand.util.MapUtils;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
@ -75,8 +75,6 @@ public class OsmAndLocationProvider implements SensorEventListener {
|
||||||
|
|
||||||
private static final float ACCURACY_FOR_GPX_AND_ROUTING = 50;
|
private static final float ACCURACY_FOR_GPX_AND_ROUTING = 50;
|
||||||
|
|
||||||
private static final int GPS_TIMEOUT_REQUEST = 0;
|
|
||||||
private static final int GPS_DIST_REQUEST = 0;
|
|
||||||
private static final int NOT_SWITCH_TO_NETWORK_WHEN_GPS_LOST_MS = 12000;
|
private static final int NOT_SWITCH_TO_NETWORK_WHEN_GPS_LOST_MS = 12000;
|
||||||
|
|
||||||
private static final long LOCATION_TIMEOUT_TO_BE_STALE = 1000 * 60 * 2; // 2 minutes
|
private static final long LOCATION_TIMEOUT_TO_BE_STALE = 1000 * 60 * 2; // 2 minutes
|
||||||
|
@ -85,9 +83,8 @@ public class OsmAndLocationProvider implements SensorEventListener {
|
||||||
private static final long AGPS_TO_REDOWNLOAD = 16 * 60 * 60 * 1000; // 16 hours
|
private static final long AGPS_TO_REDOWNLOAD = 16 * 60 * 60 * 1000; // 16 hours
|
||||||
|
|
||||||
private static final int REQUESTS_BEFORE_CHECK_LOCATION = 100;
|
private static final int REQUESTS_BEFORE_CHECK_LOCATION = 100;
|
||||||
private AtomicInteger locationRequestsCounter = new AtomicInteger();
|
private final AtomicInteger locationRequestsCounter = new AtomicInteger();
|
||||||
private AtomicInteger staleLocationRequestsCounter = new AtomicInteger();
|
private final AtomicInteger staleLocationRequestsCounter = new AtomicInteger();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private long lastTimeGPSLocationFixed = 0;
|
private long lastTimeGPSLocationFixed = 0;
|
||||||
|
@ -121,23 +118,23 @@ public class OsmAndLocationProvider implements SensorEventListener {
|
||||||
// Current screen orientation
|
// Current screen orientation
|
||||||
private int currentScreenOrientation;
|
private int currentScreenOrientation;
|
||||||
|
|
||||||
private OsmandApplication app;
|
private final OsmandApplication app;
|
||||||
|
|
||||||
private NavigationInfo navigationInfo;
|
private final NavigationInfo navigationInfo;
|
||||||
private CurrentPositionHelper currentPositionHelper;
|
private final CurrentPositionHelper currentPositionHelper;
|
||||||
private OsmAndLocationSimulation locationSimulation;
|
private final OsmAndLocationSimulation locationSimulation;
|
||||||
|
private final LocationServiceHelper locationServiceHelper;
|
||||||
|
|
||||||
private net.osmand.Location location = null;
|
private net.osmand.Location location = null;
|
||||||
|
|
||||||
private GPSInfo gpsInfo = new GPSInfo();
|
private GPSInfo gpsInfo = new GPSInfo();
|
||||||
|
|
||||||
private List<OsmAndLocationListener> locationListeners = new ArrayList<OsmAndLocationProvider.OsmAndLocationListener>();
|
private List<OsmAndLocationListener> locationListeners = new ArrayList<>();
|
||||||
private List<OsmAndCompassListener> compassListeners = new ArrayList<OsmAndLocationProvider.OsmAndCompassListener>();
|
private List<OsmAndCompassListener> compassListeners = new ArrayList<>();
|
||||||
private Object gpsStatusListener;
|
private Object gpsStatusListener;
|
||||||
private float[] mRotationM = new float[9];
|
private float[] mRotationM = new float[9];
|
||||||
|
|
||||||
|
public static class SimulationProvider {
|
||||||
public class SimulationProvider {
|
|
||||||
private int currentRoad;
|
private int currentRoad;
|
||||||
private int currentSegment;
|
private int currentSegment;
|
||||||
private QuadPoint currentPoint;
|
private QuadPoint currentPoint;
|
||||||
|
@ -227,6 +224,7 @@ public class OsmAndLocationProvider implements SensorEventListener {
|
||||||
navigationInfo = new NavigationInfo(app);
|
navigationInfo = new NavigationInfo(app);
|
||||||
currentPositionHelper = new CurrentPositionHelper(app);
|
currentPositionHelper = new CurrentPositionHelper(app);
|
||||||
locationSimulation = new OsmAndLocationSimulation(app, this);
|
locationSimulation = new OsmAndLocationSimulation(app, this);
|
||||||
|
locationServiceHelper = app.createLocationServiceHelper();
|
||||||
addLocationListener(navigationInfo);
|
addLocationListener(navigationInfo);
|
||||||
addCompassListener(navigationInfo);
|
addCompassListener(navigationInfo);
|
||||||
}
|
}
|
||||||
|
@ -235,7 +233,7 @@ public class OsmAndLocationProvider implements SensorEventListener {
|
||||||
final LocationManager service = (LocationManager) app.getSystemService(Context.LOCATION_SERVICE);
|
final LocationManager service = (LocationManager) app.getSystemService(Context.LOCATION_SERVICE);
|
||||||
if (app.getSettings().isInternetConnectionAvailable()) {
|
if (app.getSettings().isInternetConnectionAvailable()) {
|
||||||
if (System.currentTimeMillis() - app.getSettings().AGPS_DATA_LAST_TIME_DOWNLOADED.get() > AGPS_TO_REDOWNLOAD) {
|
if (System.currentTimeMillis() - app.getSettings().AGPS_DATA_LAST_TIME_DOWNLOADED.get() > AGPS_TO_REDOWNLOAD) {
|
||||||
//force an updated check for internet connectivity here before destroying A-GPS-data
|
// force an updated check for internet connectivity here before destroying A-GPS-data
|
||||||
if (app.getSettings().isInternetConnectionAvailable(true)) {
|
if (app.getSettings().isInternetConnectionAvailable(true)) {
|
||||||
redownloadAGPS();
|
redownloadAGPS();
|
||||||
}
|
}
|
||||||
|
@ -244,27 +242,34 @@ public class OsmAndLocationProvider implements SensorEventListener {
|
||||||
if (isLocationPermissionAvailable(app)) {
|
if (isLocationPermissionAvailable(app)) {
|
||||||
registerGpsStatusListener(service);
|
registerGpsStatusListener(service);
|
||||||
try {
|
try {
|
||||||
service.requestLocationUpdates(LocationManager.GPS_PROVIDER, GPS_TIMEOUT_REQUEST, GPS_DIST_REQUEST, gpsListener);
|
locationServiceHelper.requestLocationUpdates(new LocationServiceHelper.LocationCallback() {
|
||||||
|
@Override
|
||||||
|
public void onLocationResult(@NonNull List<net.osmand.Location> locations) {
|
||||||
|
net.osmand.Location location = null;
|
||||||
|
if (!locations.isEmpty()) {
|
||||||
|
location = locations.get(locations.size() - 1);
|
||||||
|
lastTimeGPSLocationFixed = System.currentTimeMillis();
|
||||||
|
}
|
||||||
|
if (!locationSimulation.isRouteAnimating()) {
|
||||||
|
setLocation(location);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (SecurityException e) {
|
||||||
|
// Location service permission not granted
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
Log.d(PlatformUtil.TAG, "GPS location provider not available"); //$NON-NLS-1$
|
// GPS location provider not available
|
||||||
}
|
}
|
||||||
// try to always ask for network provide : it is faster way to find location
|
// try to always ask for network provide : it is faster way to find location
|
||||||
|
if (locationServiceHelper.isNetworkLocationUpdatesSupported()) {
|
||||||
List<String> providers = service.getProviders(true);
|
locationServiceHelper.requestNetworkLocationUpdates(new LocationServiceHelper.LocationCallback() {
|
||||||
if (providers == null) {
|
@Override
|
||||||
return;
|
public void onLocationResult(@NonNull List<net.osmand.Location> locations) {
|
||||||
}
|
if (!locations.isEmpty() && !useOnlyGPS() && !locationSimulation.isRouteAnimating()) {
|
||||||
for (String provider : providers) {
|
setLocation(locations.get(locations.size() - 1));
|
||||||
if (provider == null || provider.equals(LocationManager.GPS_PROVIDER)) {
|
}
|
||||||
continue;
|
}
|
||||||
}
|
});
|
||||||
try {
|
|
||||||
NetworkListener networkListener = new NetworkListener();
|
|
||||||
service.requestLocationUpdates(provider, GPS_TIMEOUT_REQUEST, GPS_DIST_REQUEST, networkListener);
|
|
||||||
networkListeners.add(networkListener);
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
Log.d(PlatformUtil.TAG, provider + " location provider not available"); //$NON-NLS-1$
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -284,8 +289,9 @@ public class OsmAndLocationProvider implements SensorEventListener {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void registerGpsStatusListener(final LocationManager service) {
|
@SuppressLint("MissingPermission")
|
||||||
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
private void registerGpsStatusListener(@NonNull final LocationManager service) {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||||
gpsStatusListener = new GnssStatus.Callback() {
|
gpsStatusListener = new GnssStatus.Callback() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -320,7 +326,7 @@ public class OsmAndLocationProvider implements SensorEventListener {
|
||||||
updateLocation(location);
|
updateLocation(location);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
service.registerGnssStatusCallback((GnssStatus.Callback) gpsStatusListener);
|
service.registerGnssStatusCallback((GnssStatus.Callback) gpsStatusListener, null);
|
||||||
} else {
|
} else {
|
||||||
gpsStatusListener = new Listener() {
|
gpsStatusListener = new Listener() {
|
||||||
private GpsStatus gpsStatus;
|
private GpsStatus gpsStatus;
|
||||||
|
@ -335,14 +341,12 @@ public class OsmAndLocationProvider implements SensorEventListener {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateGPSInfo(GpsStatus s) {
|
private void updateGPSInfo(@Nullable GpsStatus s) {
|
||||||
boolean fixed = false;
|
boolean fixed = false;
|
||||||
int n = 0;
|
int n = 0;
|
||||||
int u = 0;
|
int u = 0;
|
||||||
if (s != null) {
|
if (s != null) {
|
||||||
Iterator<GpsSatellite> iterator = s.getSatellites().iterator();
|
for (GpsSatellite g : s.getSatellites()) {
|
||||||
while (iterator.hasNext()) {
|
|
||||||
GpsSatellite g = iterator.next();
|
|
||||||
n++;
|
n++;
|
||||||
if (g.usedInFix()) {
|
if (g.usedInFix()) {
|
||||||
u++;
|
u++;
|
||||||
|
@ -354,7 +358,8 @@ public class OsmAndLocationProvider implements SensorEventListener {
|
||||||
gpsInfo.foundSatellites = n;
|
gpsInfo.foundSatellites = n;
|
||||||
gpsInfo.usedSatellites = u;
|
gpsInfo.usedSatellites = u;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
public GPSInfo getGPSInfo(){
|
public GPSInfo getGPSInfo(){
|
||||||
return gpsInfo;
|
return gpsInfo;
|
||||||
}
|
}
|
||||||
|
@ -363,51 +368,29 @@ public class OsmAndLocationProvider implements SensorEventListener {
|
||||||
currentScreenOrientation = orientation;
|
currentScreenOrientation = orientation;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addLocationListener(OsmAndLocationListener listener){
|
public void addLocationListener(@NonNull OsmAndLocationListener listener) {
|
||||||
if(!locationListeners.contains(listener)) {
|
if (!locationListeners.contains(listener)) {
|
||||||
locationListeners.add(listener);
|
locationListeners.add(listener);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeLocationListener(OsmAndLocationListener listener){
|
public void removeLocationListener(@NonNull OsmAndLocationListener listener) {
|
||||||
locationListeners.remove(listener);
|
locationListeners.remove(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addCompassListener(OsmAndCompassListener listener){
|
public void addCompassListener(@NonNull OsmAndCompassListener listener) {
|
||||||
if(!compassListeners.contains(listener)) {
|
if (!compassListeners.contains(listener)) {
|
||||||
compassListeners.add(listener);
|
compassListeners.add(listener);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeCompassListener(OsmAndCompassListener listener){
|
public void removeCompassListener(@NonNull OsmAndCompassListener listener) {
|
||||||
compassListeners.remove(listener);
|
compassListeners.remove(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
public net.osmand.Location getFirstTimeRunDefaultLocation() {
|
public net.osmand.Location getFirstTimeRunDefaultLocation() {
|
||||||
if (!isLocationPermissionAvailable(app)) {
|
return isLocationPermissionAvailable(app) ? locationServiceHelper.getFirstTimeRunDefaultLocation() : null;
|
||||||
return null;
|
|
||||||
}
|
|
||||||
LocationManager service = (LocationManager) app.getSystemService(Context.LOCATION_SERVICE);
|
|
||||||
List<String> ps = service.getProviders(true);
|
|
||||||
if(ps == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
List<String> providers = new ArrayList<String>(ps);
|
|
||||||
// note, passive provider is from API_LEVEL 8 but it is a constant, we can check for it.
|
|
||||||
// constant should not be changed in future
|
|
||||||
int passiveFirst = providers.indexOf("passive"); // LocationManager.PASSIVE_PROVIDER
|
|
||||||
// put passive provider to first place
|
|
||||||
if (passiveFirst > -1) {
|
|
||||||
providers.add(0, providers.remove(passiveFirst));
|
|
||||||
}
|
|
||||||
// find location
|
|
||||||
for (String provider : providers) {
|
|
||||||
net.osmand.Location location = convertLocation(service.getLastKnownLocation(provider), app);
|
|
||||||
if (location != null) {
|
|
||||||
return location;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void registerOrUnregisterCompassListener(boolean register) {
|
public synchronized void registerOrUnregisterCompassListener(boolean register) {
|
||||||
|
@ -466,10 +449,7 @@ public class OsmAndLocationProvider implements SensorEventListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isRunningOnEmulator() {
|
private boolean isRunningOnEmulator() {
|
||||||
if (Build.DEVICE.equals("generic")) { //$NON-NLS-1$
|
return Build.DEVICE.equals("generic");
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -599,78 +579,25 @@ public class OsmAndLocationProvider implements SensorEventListener {
|
||||||
return MapUtils.unifyRotationTo360((float) (Math.atan2(sinA, cosA) * 180 / Math.PI));
|
return MapUtils.unifyRotationTo360((float) (Math.atan2(sinA, cosA) * 180 / Math.PI));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void updateLocation(net.osmand.Location loc) {
|
private void updateLocation(net.osmand.Location loc) {
|
||||||
for (OsmAndLocationListener l : locationListeners) {
|
for (OsmAndLocationListener l : locationListeners) {
|
||||||
l.updateLocation(loc);
|
l.updateLocation(loc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private LocationListener gpsListener = new LocationListener() {
|
|
||||||
@Override
|
|
||||||
public void onLocationChanged(Location location) {
|
|
||||||
if (location != null) {
|
|
||||||
// lastTimeGPSLocationFixed = location.getTime();
|
|
||||||
lastTimeGPSLocationFixed = System.currentTimeMillis();
|
|
||||||
}
|
|
||||||
if(!locationSimulation.isRouteAnimating()) {
|
|
||||||
setLocation(convertLocation(location, app));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onProviderDisabled(String provider) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onProviderEnabled(String provider) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onStatusChanged(String provider, int status, Bundle extras) {
|
|
||||||
}
|
|
||||||
};
|
|
||||||
private LinkedList<LocationListener> networkListeners = new LinkedList<LocationListener>();
|
|
||||||
|
|
||||||
private boolean useOnlyGPS() {
|
private boolean useOnlyGPS() {
|
||||||
if(app.getRoutingHelper().isFollowingMode()) {
|
if (app.getRoutingHelper().isFollowingMode()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if((System.currentTimeMillis() - lastTimeGPSLocationFixed) < NOT_SWITCH_TO_NETWORK_WHEN_GPS_LOST_MS) {
|
if ((System.currentTimeMillis() - lastTimeGPSLocationFixed) < NOT_SWITCH_TO_NETWORK_WHEN_GPS_LOST_MS) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if(isRunningOnEmulator()) {
|
if (isRunningOnEmulator()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Working with location checkListeners
|
|
||||||
private class NetworkListener implements LocationListener {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onLocationChanged(Location location) {
|
|
||||||
if (!useOnlyGPS() && !locationSimulation.isRouteAnimating()) {
|
|
||||||
setLocation(convertLocation(location, app));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onProviderDisabled(String provider) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onProviderEnabled(String provider) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onStatusChanged(String provider, int status, Bundle extras) {
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
private void stopLocationRequests() {
|
private void stopLocationRequests() {
|
||||||
LocationManager service = (LocationManager) app.getSystemService(Context.LOCATION_SERVICE);
|
LocationManager service = (LocationManager) app.getSystemService(Context.LOCATION_SERVICE);
|
||||||
if (gpsStatusListener != null) {
|
if (gpsStatusListener != null) {
|
||||||
|
@ -680,9 +607,10 @@ public class OsmAndLocationProvider implements SensorEventListener {
|
||||||
service.removeGpsStatusListener((Listener) gpsStatusListener);
|
service.removeGpsStatusListener((Listener) gpsStatusListener);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
service.removeUpdates(gpsListener);
|
try {
|
||||||
while (!networkListeners.isEmpty()) {
|
locationServiceHelper.removeLocationUpdates();
|
||||||
service.removeUpdates(networkListeners.poll());
|
} catch (SecurityException e) {
|
||||||
|
// Location service permission not granted
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -963,7 +891,7 @@ public class OsmAndLocationProvider implements SensorEventListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isNotSimulatedLocation(net.osmand.Location l) {
|
public static boolean isNotSimulatedLocation(net.osmand.Location l) {
|
||||||
if(l != null) {
|
if (l != null) {
|
||||||
return !SIMULATED_PROVIDER.equals(l.getProvider());
|
return !SIMULATED_PROVIDER.equals(l.getProvider());
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -984,7 +912,7 @@ public class OsmAndLocationProvider implements SensorEventListener {
|
||||||
networkenabled = lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
|
networkenabled = lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
|
||||||
} catch(Exception ex) {}
|
} catch(Exception ex) {}
|
||||||
|
|
||||||
if(!gpsenabled && !networkenabled) {
|
if (!gpsenabled && !networkenabled) {
|
||||||
// notify user
|
// notify user
|
||||||
AlertDialog.Builder dialog = new AlertDialog.Builder(context);
|
AlertDialog.Builder dialog = new AlertDialog.Builder(context);
|
||||||
dialog.setMessage(context.getResources().getString(R.string.gps_network_not_enabled));
|
dialog.setMessage(context.getResources().getString(R.string.gps_network_not_enabled));
|
||||||
|
@ -1003,11 +931,8 @@ public class OsmAndLocationProvider implements SensorEventListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isLocationPermissionAvailable(Context context) {
|
public static boolean isLocationPermissionAvailable(Context context) {
|
||||||
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION)
|
return ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION)
|
||||||
!= PackageManager.PERMISSION_GRANTED) {
|
== PackageManager.PERMISSION_GRANTED;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void requestFineLocationPermissionIfNeeded(Activity activity) {
|
public static void requestFineLocationPermissionIfNeeded(Activity activity) {
|
||||||
|
|
|
@ -57,6 +57,7 @@ import net.osmand.plus.download.DownloadService;
|
||||||
import net.osmand.plus.download.IndexItem;
|
import net.osmand.plus.download.IndexItem;
|
||||||
import net.osmand.plus.helpers.AvoidSpecificRoads;
|
import net.osmand.plus.helpers.AvoidSpecificRoads;
|
||||||
import net.osmand.plus.helpers.DayNightHelper;
|
import net.osmand.plus.helpers.DayNightHelper;
|
||||||
|
import net.osmand.plus.helpers.LocationServiceHelper;
|
||||||
import net.osmand.plus.helpers.LockHelper;
|
import net.osmand.plus.helpers.LockHelper;
|
||||||
import net.osmand.plus.helpers.WaypointHelper;
|
import net.osmand.plus.helpers.WaypointHelper;
|
||||||
import net.osmand.plus.helpers.enums.DrivingRegion;
|
import net.osmand.plus.helpers.enums.DrivingRegion;
|
||||||
|
@ -300,7 +301,11 @@ public class OsmandApplication extends MultiDexApplication {
|
||||||
public QuickActionRegistry getQuickActionRegistry() {
|
public QuickActionRegistry getQuickActionRegistry() {
|
||||||
return quickActionRegistry;
|
return quickActionRegistry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public LocationServiceHelper createLocationServiceHelper() {
|
||||||
|
return new LocationServiceHelperImpl(this);
|
||||||
|
}
|
||||||
|
|
||||||
public void setAppCustomization(OsmAndAppCustomization appCustomization) {
|
public void setAppCustomization(OsmAndAppCustomization appCustomization) {
|
||||||
this.appCustomization = appCustomization;
|
this.appCustomization = appCustomization;
|
||||||
this.appCustomization.setup(this);
|
this.appCustomization.setup(this);
|
||||||
|
|
|
@ -445,7 +445,7 @@ public class TargetPointsHelper {
|
||||||
Location lastKnownLocation = ctx.getLocationProvider().getLastKnownLocation();
|
Location lastKnownLocation = ctx.getLocationProvider().getLastKnownLocation();
|
||||||
LatLon latLon = lastKnownLocation != null ?
|
LatLon latLon = lastKnownLocation != null ?
|
||||||
new LatLon(lastKnownLocation.getLatitude(), lastKnownLocation.getLongitude()) : null;
|
new LatLon(lastKnownLocation.getLatitude(), lastKnownLocation.getLongitude()) : null;
|
||||||
RoutingHelperUtils.checkAndUpdateStartLocation(ctx, latLon);
|
RoutingHelperUtils.checkAndUpdateStartLocation(ctx, latLon, false);
|
||||||
setMyLocationPoint(latLon, false, null);
|
setMyLocationPoint(latLon, false, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -118,6 +118,7 @@ import net.osmand.plus.measurementtool.LoginBottomSheetFragment;
|
||||||
import net.osmand.plus.measurementtool.MeasurementEditingContext;
|
import net.osmand.plus.measurementtool.MeasurementEditingContext;
|
||||||
import net.osmand.plus.measurementtool.MeasurementToolFragment;
|
import net.osmand.plus.measurementtool.MeasurementToolFragment;
|
||||||
import net.osmand.plus.measurementtool.SnapTrackWarningFragment;
|
import net.osmand.plus.measurementtool.SnapTrackWarningFragment;
|
||||||
|
import net.osmand.plus.monitoring.TripRecordingBottomSheet;
|
||||||
import net.osmand.plus.render.RendererRegistry;
|
import net.osmand.plus.render.RendererRegistry;
|
||||||
import net.osmand.plus.resources.ResourceManager;
|
import net.osmand.plus.resources.ResourceManager;
|
||||||
import net.osmand.plus.routepreparationmenu.ChooseRouteFragment;
|
import net.osmand.plus.routepreparationmenu.ChooseRouteFragment;
|
||||||
|
@ -1408,6 +1409,7 @@ public class MapActivity extends OsmandActionBarActivity implements DownloadEven
|
||||||
updateMapSettings();
|
updateMapSettings();
|
||||||
app.getPoiFilters().loadSelectedPoiFilters();
|
app.getPoiFilters().loadSelectedPoiFilters();
|
||||||
mapViewTrackingUtilities.updateSettings();
|
mapViewTrackingUtilities.updateSettings();
|
||||||
|
mapViewTrackingUtilities.resetDrivingRegionUpdate();
|
||||||
//app.getRoutingHelper().setAppMode(settings.getApplicationMode());
|
//app.getRoutingHelper().setAppMode(settings.getApplicationMode());
|
||||||
if (mapLayers.getMapInfoLayer() != null) {
|
if (mapLayers.getMapInfoLayer() != null) {
|
||||||
mapLayers.getMapInfoLayer().recreateControls();
|
mapLayers.getMapInfoLayer().recreateControls();
|
||||||
|
@ -2204,6 +2206,10 @@ public class MapActivity extends OsmandActionBarActivity implements DownloadEven
|
||||||
return getFragment(MeasurementToolFragment.TAG);
|
return getFragment(MeasurementToolFragment.TAG);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TripRecordingBottomSheet getTripRecordingBottomSheet() {
|
||||||
|
return getFragment(TripRecordingBottomSheet.TAG);
|
||||||
|
}
|
||||||
|
|
||||||
public ChooseRouteFragment getChooseRouteFragment() {
|
public ChooseRouteFragment getChooseRouteFragment() {
|
||||||
return getFragment(ChooseRouteFragment.TAG);
|
return getFragment(ChooseRouteFragment.TAG);
|
||||||
}
|
}
|
||||||
|
@ -2220,7 +2226,6 @@ public class MapActivity extends OsmandActionBarActivity implements DownloadEven
|
||||||
return getFragment(SnapTrackWarningFragment.TAG);
|
return getFragment(SnapTrackWarningFragment.TAG);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
|
||||||
public TrackMenuFragment getTrackMenuFragment() {
|
public TrackMenuFragment getTrackMenuFragment() {
|
||||||
return getFragment(TrackMenuFragment.TAG);
|
return getFragment(TrackMenuFragment.TAG);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,8 +13,6 @@ import net.osmand.data.LatLon;
|
||||||
import net.osmand.data.RotatedTileBox;
|
import net.osmand.data.RotatedTileBox;
|
||||||
import net.osmand.map.IMapLocationListener;
|
import net.osmand.map.IMapLocationListener;
|
||||||
import net.osmand.map.WorldRegion;
|
import net.osmand.map.WorldRegion;
|
||||||
import net.osmand.plus.mapmarkers.MapMarker;
|
|
||||||
import net.osmand.plus.mapmarkers.MapMarkersHelper.MapMarkerChangedListener;
|
|
||||||
import net.osmand.plus.OsmAndConstants;
|
import net.osmand.plus.OsmAndConstants;
|
||||||
import net.osmand.plus.OsmAndLocationProvider;
|
import net.osmand.plus.OsmAndLocationProvider;
|
||||||
import net.osmand.plus.OsmAndLocationProvider.OsmAndCompassListener;
|
import net.osmand.plus.OsmAndLocationProvider.OsmAndCompassListener;
|
||||||
|
@ -22,10 +20,14 @@ import net.osmand.plus.OsmAndLocationProvider.OsmAndLocationListener;
|
||||||
import net.osmand.plus.OsmandApplication;
|
import net.osmand.plus.OsmandApplication;
|
||||||
import net.osmand.plus.R;
|
import net.osmand.plus.R;
|
||||||
import net.osmand.plus.dashboard.DashboardOnMap;
|
import net.osmand.plus.dashboard.DashboardOnMap;
|
||||||
|
import net.osmand.plus.helpers.enums.DrivingRegion;
|
||||||
import net.osmand.plus.mapcontextmenu.MapContextMenu;
|
import net.osmand.plus.mapcontextmenu.MapContextMenu;
|
||||||
import net.osmand.plus.mapcontextmenu.other.TrackDetailsMenu;
|
import net.osmand.plus.mapcontextmenu.other.TrackDetailsMenu;
|
||||||
|
import net.osmand.plus.mapmarkers.MapMarker;
|
||||||
|
import net.osmand.plus.mapmarkers.MapMarkersHelper.MapMarkerChangedListener;
|
||||||
import net.osmand.plus.routing.RoutingHelper;
|
import net.osmand.plus.routing.RoutingHelper;
|
||||||
import net.osmand.plus.routing.RoutingHelperUtils;
|
import net.osmand.plus.routing.RoutingHelperUtils;
|
||||||
|
import net.osmand.plus.settings.backend.ApplicationMode;
|
||||||
import net.osmand.plus.settings.backend.OsmandSettings;
|
import net.osmand.plus.settings.backend.OsmandSettings;
|
||||||
import net.osmand.plus.views.AnimateDraggingMapThread;
|
import net.osmand.plus.views.AnimateDraggingMapThread;
|
||||||
import net.osmand.plus.views.OsmandMapTileView;
|
import net.osmand.plus.views.OsmandMapTileView;
|
||||||
|
@ -176,7 +178,7 @@ public class MapViewTrackingUtilities implements OsmAndLocationListener, IMapLoc
|
||||||
locationProvider = location.getProvider();
|
locationProvider = location.getProvider();
|
||||||
if (settings.DRIVING_REGION_AUTOMATIC.get() && !drivingRegionUpdated && !app.isApplicationInitializing()) {
|
if (settings.DRIVING_REGION_AUTOMATIC.get() && !drivingRegionUpdated && !app.isApplicationInitializing()) {
|
||||||
drivingRegionUpdated = true;
|
drivingRegionUpdated = true;
|
||||||
RoutingHelperUtils.checkAndUpdateStartLocation(app, location);
|
RoutingHelperUtils.checkAndUpdateStartLocation(app, location, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (mapView != null) {
|
if (mapView != null) {
|
||||||
|
@ -489,7 +491,15 @@ public class MapViewTrackingUtilities implements OsmAndLocationListener, IMapLoc
|
||||||
@Override
|
@Override
|
||||||
protected void onPostExecute(WorldRegion worldRegion) {
|
protected void onPostExecute(WorldRegion worldRegion) {
|
||||||
if (worldRegion != null) {
|
if (worldRegion != null) {
|
||||||
|
DrivingRegion oldRegion = app.getSettings().DRIVING_REGION.get();
|
||||||
|
|
||||||
app.setupDrivingRegion(worldRegion);
|
app.setupDrivingRegion(worldRegion);
|
||||||
|
|
||||||
|
DrivingRegion currentRegion = app.getSettings().DRIVING_REGION.get();
|
||||||
|
if (oldRegion.leftHandDriving != currentRegion.leftHandDriving) {
|
||||||
|
ApplicationMode mode = app.getRoutingHelper().getAppMode();
|
||||||
|
app.getRoutingHelper().onSettingsChanged(mode, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,10 +43,10 @@ public class DayNightHelper implements SensorEventListener {
|
||||||
|
|
||||||
private static final Log log = PlatformUtil.getLog(DayNightHelper.class);
|
private static final Log log = PlatformUtil.getLog(DayNightHelper.class);
|
||||||
|
|
||||||
private final OsmandApplication osmandApplication;
|
private final OsmandApplication app;
|
||||||
|
|
||||||
public DayNightHelper(OsmandApplication osmandApplication) {
|
public DayNightHelper(OsmandApplication app) {
|
||||||
this.osmandApplication = osmandApplication;
|
this.app = app;
|
||||||
}
|
}
|
||||||
|
|
||||||
private DayNightHelper listener;
|
private DayNightHelper listener;
|
||||||
|
@ -56,11 +56,11 @@ public class DayNightHelper implements SensorEventListener {
|
||||||
private StateChangedListener<Boolean> sensorStateListener;
|
private StateChangedListener<Boolean> sensorStateListener;
|
||||||
|
|
||||||
public boolean isNightModeForMapControls() {
|
public boolean isNightModeForMapControls() {
|
||||||
return isNightModeForMapControlsForProfile(osmandApplication.getSettings().APPLICATION_MODE.get());
|
return isNightModeForMapControlsForProfile(app.getSettings().APPLICATION_MODE.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isNightModeForMapControlsForProfile(ApplicationMode mode) {
|
public boolean isNightModeForMapControlsForProfile(ApplicationMode mode) {
|
||||||
if (osmandApplication.getSettings().isLightContentForMode(mode)) {
|
if (app.getSettings().isLightContentForMode(mode)) {
|
||||||
return isNightModeForProfile(mode);
|
return isNightModeForProfile(mode);
|
||||||
} else {
|
} else {
|
||||||
return true;
|
return true;
|
||||||
|
@ -72,11 +72,11 @@ public class DayNightHelper implements SensorEventListener {
|
||||||
* @return true if day is supposed to be
|
* @return true if day is supposed to be
|
||||||
*/
|
*/
|
||||||
public boolean isNightMode() {
|
public boolean isNightMode() {
|
||||||
return isNightModeForProfile(osmandApplication.getSettings().APPLICATION_MODE.get());
|
return isNightModeForProfile(app.getSettings().APPLICATION_MODE.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isNightModeForProfile(ApplicationMode mode) {
|
public boolean isNightModeForProfile(ApplicationMode mode) {
|
||||||
DayNightMode dayNightMode = osmandApplication.getSettings().DAYNIGHT_MODE.getModeValue(mode);
|
DayNightMode dayNightMode = app.getSettings().DAYNIGHT_MODE.getModeValue(mode);
|
||||||
if (dayNightMode.isDay()) {
|
if (dayNightMode.isDay()) {
|
||||||
return false;
|
return false;
|
||||||
} else if (dayNightMode.isNight()) {
|
} else if (dayNightMode.isNight()) {
|
||||||
|
@ -108,24 +108,23 @@ public class DayNightHelper implements SensorEventListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
public SunriseSunset getSunriseSunset() {
|
public SunriseSunset getSunriseSunset() {
|
||||||
Location lastKnownLocation = osmandApplication.getLocationProvider().getLastKnownLocation();
|
Location lastKnownLocation = app.getLocationProvider().getLastKnownLocation();
|
||||||
if(lastKnownLocation == null) {
|
if (lastKnownLocation == null) {
|
||||||
lastKnownLocation = osmandApplication.getLocationProvider().getFirstTimeRunDefaultLocation();
|
lastKnownLocation = app.getLocationProvider().getFirstTimeRunDefaultLocation();
|
||||||
}
|
}
|
||||||
if (lastKnownLocation == null) {
|
if (lastKnownLocation == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
double longitude = lastKnownLocation.getLongitude();
|
double longitude = lastKnownLocation.getLongitude();
|
||||||
Date actualTime = new Date();
|
Date actualTime = new Date();
|
||||||
SunriseSunset daynightSwitch = new SunriseSunset(lastKnownLocation.getLatitude(),
|
return new SunriseSunset(lastKnownLocation.getLatitude(),
|
||||||
longitude < 0 ? 360 + longitude : longitude,
|
longitude < 0 ? 360 + longitude : longitude,
|
||||||
actualTime, TimeZone.getDefault());
|
actualTime, TimeZone.getDefault());
|
||||||
return daynightSwitch;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void stopSensorIfNeeded() {
|
public void stopSensorIfNeeded() {
|
||||||
if (listener != null) {
|
if (listener != null) {
|
||||||
SensorManager mSensorManager = (SensorManager) osmandApplication
|
SensorManager mSensorManager = (SensorManager) app
|
||||||
.getSystemService(Context.SENSOR_SERVICE);
|
.getSystemService(Context.SENSOR_SERVICE);
|
||||||
Sensor mLight = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
|
Sensor mLight = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
|
||||||
mSensorManager.unregisterListener(listener, mLight);
|
mSensorManager.unregisterListener(listener, mLight);
|
||||||
|
@ -135,9 +134,9 @@ public class DayNightHelper implements SensorEventListener {
|
||||||
|
|
||||||
public void startSensorIfNeeded(StateChangedListener<Boolean> sensorStateListener) {
|
public void startSensorIfNeeded(StateChangedListener<Boolean> sensorStateListener) {
|
||||||
this.sensorStateListener = sensorStateListener;
|
this.sensorStateListener = sensorStateListener;
|
||||||
DayNightMode dayNightMode = osmandApplication.getSettings().DAYNIGHT_MODE.get();
|
DayNightMode dayNightMode = app.getSettings().DAYNIGHT_MODE.get();
|
||||||
if (listener == null && dayNightMode.isSensor()) {
|
if (listener == null && dayNightMode.isSensor()) {
|
||||||
SensorManager mSensorManager = (SensorManager) osmandApplication.getSystemService(Context.SENSOR_SERVICE);
|
SensorManager mSensorManager = (SensorManager) app.getSystemService(Context.SENSOR_SERVICE);
|
||||||
Sensor mLight = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
|
Sensor mLight = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
|
||||||
List<Sensor> list = mSensorManager.getSensorList(Sensor.TYPE_LIGHT);
|
List<Sensor> list = mSensorManager.getSensorList(Sensor.TYPE_LIGHT);
|
||||||
log.info("Light sensors:" + list.size()); //$NON-NLS-1$
|
log.info("Light sensors:" + list.size()); //$NON-NLS-1$
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
package net.osmand.plus.helpers;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
import net.osmand.Location;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public abstract class LocationServiceHelper {
|
||||||
|
|
||||||
|
public static abstract class LocationCallback {
|
||||||
|
|
||||||
|
public void onLocationResult(@NonNull List<Location> locations) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onLocationAvailability(boolean locationAvailable) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void requestLocationUpdates(@NonNull LocationCallback locationCallback);
|
||||||
|
|
||||||
|
public abstract boolean isNetworkLocationUpdatesSupported();
|
||||||
|
|
||||||
|
public abstract void requestNetworkLocationUpdates(@NonNull LocationCallback locationCallback);
|
||||||
|
|
||||||
|
public abstract void removeLocationUpdates();
|
||||||
|
|
||||||
|
public abstract Location getFirstTimeRunDefaultLocation();
|
||||||
|
}
|
|
@ -100,12 +100,12 @@ public class OsmandMonitoringPlugin extends OsmandPlugin {
|
||||||
public void updateLocation(Location location) {
|
public void updateLocation(Location location) {
|
||||||
liveMonitoringHelper.updateLocation(location);
|
liveMonitoringHelper.updateLocation(location);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getLogoResourceId() {
|
public int getLogoResourceId() {
|
||||||
return R.drawable.ic_action_gps_info;
|
return R.drawable.ic_action_gps_info;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Drawable getAssetResourceImage() {
|
public Drawable getAssetResourceImage() {
|
||||||
return app.getUIUtilities().getIcon(R.drawable.trip_recording);
|
return app.getUIUtilities().getIcon(R.drawable.trip_recording);
|
||||||
|
@ -140,7 +140,7 @@ public class OsmandMonitoringPlugin extends OsmandPlugin {
|
||||||
private void registerWidget(MapActivity activity) {
|
private void registerWidget(MapActivity activity) {
|
||||||
MapInfoLayer layer = activity.getMapLayers().getMapInfoLayer();
|
MapInfoLayer layer = activity.getMapLayers().getMapInfoLayer();
|
||||||
monitoringControl = createMonitoringControl(activity);
|
monitoringControl = createMonitoringControl(activity);
|
||||||
|
|
||||||
layer.registerSideWidget(monitoringControl,
|
layer.registerSideWidget(monitoringControl,
|
||||||
R.drawable.ic_action_play_dark, R.string.map_widget_monitoring, "monitoring", false, 30);
|
R.drawable.ic_action_play_dark, R.string.map_widget_monitoring, "monitoring", false, 30);
|
||||||
layer.recreateControls();
|
layer.recreateControls();
|
||||||
|
@ -161,7 +161,7 @@ public class OsmandMonitoringPlugin extends OsmandPlugin {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final int[] SECONDS = new int[] {0, 1, 2, 3, 5, 10, 15, 20, 30, 60, 90};
|
public static final int[] SECONDS = new int[] {0, 1, 2, 3, 5, 10, 15, 20, 30, 60, 90};
|
||||||
public static final int[] MINUTES = new int[] {2, 3, 5};
|
public static final int[] MINUTES = new int[] {2, 3, 5};
|
||||||
public static final int[] MAX_INTERVAL_TO_SEND_MINUTES = new int[] {1, 2, 5, 10, 15, 20, 30, 60, 90, 2 * 60, 3 * 60, 4 * 60, 6 * 60, 12 * 60, 24 * 60};
|
public static final int[] MAX_INTERVAL_TO_SEND_MINUTES = new int[] {1, 2, 5, 10, 15, 20, 30, 60, 90, 2 * 60, 3 * 60, 4 * 60, 6 * 60, 12 * 60, 24 * 60};
|
||||||
|
@ -287,7 +287,7 @@ public class OsmandMonitoringPlugin extends OsmandPlugin {
|
||||||
controlDialog(map, true);
|
controlDialog(map, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
return monitoringControl;
|
return monitoringControl;
|
||||||
}
|
}
|
||||||
|
@ -422,7 +422,7 @@ public class OsmandMonitoringPlugin extends OsmandPlugin {
|
||||||
public void saveCurrentTrack() {
|
public void saveCurrentTrack() {
|
||||||
saveCurrentTrack(null, null);
|
saveCurrentTrack(null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void saveCurrentTrack(@Nullable final Runnable onComplete) {
|
public void saveCurrentTrack(@Nullable final Runnable onComplete) {
|
||||||
saveCurrentTrack(onComplete, null);
|
saveCurrentTrack(onComplete, null);
|
||||||
}
|
}
|
||||||
|
@ -464,7 +464,7 @@ public class OsmandMonitoringPlugin extends OsmandPlugin {
|
||||||
SaveGPXBottomSheetFragment.showInstance(((FragmentActivity) a).getSupportFragmentManager(), result.getFilenames());
|
SaveGPXBottomSheetFragment.showInstance(((FragmentActivity) a).getSupportFragmentManager(), result.getFilenames());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (onComplete != null) {
|
if (onComplete != null) {
|
||||||
onComplete.run();
|
onComplete.run();
|
||||||
}
|
}
|
||||||
|
@ -505,15 +505,9 @@ public class OsmandMonitoringPlugin extends OsmandPlugin {
|
||||||
};
|
};
|
||||||
if (choice.value || map == null) {
|
if (choice.value || map == null) {
|
||||||
runnable.run();
|
runnable.run();
|
||||||
} else {
|
} else if (map instanceof FragmentActivity) {
|
||||||
showIntervalChooseDialog(map, app.getString(R.string.save_track_interval_globally) + " : %s",
|
FragmentActivity activity = (FragmentActivity) map;
|
||||||
app.getString(R.string.save_track_to_gpx_globally), SECONDS, MINUTES, choice, vs, showTrackSelection,
|
TripRecordingBottomSheet.showInstance(activity.getSupportFragmentManager());
|
||||||
new OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
|
||||||
runnable.run();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -588,7 +582,7 @@ public class OsmandMonitoringPlugin extends OsmandPlugin {
|
||||||
tv.setText(String.format(patternMsg, s));
|
tv.setText(String.format(patternMsg, s));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
for (int i = 0; i < secondsLength + minutesLength - 1; i++) {
|
for (int i = 0; i < secondsLength + minutesLength - 1; i++) {
|
||||||
if (i < secondsLength) {
|
if (i < secondsLength) {
|
||||||
if (v.value <= seconds[i] * 1000) {
|
if (v.value <= seconds[i] * 1000) {
|
||||||
|
|
|
@ -0,0 +1,273 @@
|
||||||
|
package net.osmand.plus.monitoring;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.app.Dialog;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.Typeface;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.text.SpannableString;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.CompoundButton;
|
||||||
|
import android.widget.CompoundButton.OnCheckedChangeListener;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.appcompat.widget.SwitchCompat;
|
||||||
|
import androidx.fragment.app.FragmentManager;
|
||||||
|
|
||||||
|
import com.google.android.material.slider.RangeSlider;
|
||||||
|
|
||||||
|
import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile;
|
||||||
|
import net.osmand.plus.NavigationService;
|
||||||
|
import net.osmand.plus.OsmandApplication;
|
||||||
|
import net.osmand.plus.R;
|
||||||
|
import net.osmand.plus.UiUtilities;
|
||||||
|
import net.osmand.plus.UiUtilities.DialogButtonType;
|
||||||
|
import net.osmand.plus.activities.MapActivity;
|
||||||
|
import net.osmand.plus.base.MenuBottomSheetDialogFragment;
|
||||||
|
import net.osmand.plus.base.bottomsheetmenu.BottomSheetItemWithDescription;
|
||||||
|
import net.osmand.plus.base.bottomsheetmenu.simpleitems.DividerSpaceItem;
|
||||||
|
import net.osmand.plus.helpers.AndroidUiHelper;
|
||||||
|
import net.osmand.plus.helpers.FontCache;
|
||||||
|
import net.osmand.plus.settings.backend.OsmandSettings;
|
||||||
|
import net.osmand.plus.track.TrackAppearanceFragment;
|
||||||
|
|
||||||
|
import static net.osmand.plus.UiUtilities.CompoundButtonType.PROFILE_DEPENDENT;
|
||||||
|
import static net.osmand.plus.monitoring.OsmandMonitoringPlugin.MINUTES;
|
||||||
|
import static net.osmand.plus.monitoring.OsmandMonitoringPlugin.SECONDS;
|
||||||
|
|
||||||
|
public class TripRecordingBottomSheet extends MenuBottomSheetDialogFragment {
|
||||||
|
|
||||||
|
public static final String TAG = TripRecordingBottomSheet.class.getSimpleName();
|
||||||
|
|
||||||
|
private OsmandApplication app;
|
||||||
|
private OsmandSettings settings;
|
||||||
|
|
||||||
|
private ImageView upDownBtn;
|
||||||
|
private SwitchCompat confirmEveryRun;
|
||||||
|
private TextView intervalValueView;
|
||||||
|
|
||||||
|
private boolean infoExpanded;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void createMenuItems(Bundle savedInstanceState) {
|
||||||
|
app = requiredMyApplication();
|
||||||
|
settings = app.getSettings();
|
||||||
|
Context context = requireContext();
|
||||||
|
|
||||||
|
LayoutInflater inflater = UiUtilities.getInflater(context, nightMode);
|
||||||
|
View itemView = inflater.inflate(R.layout.trip_recording_fragment, null, false);
|
||||||
|
items.add(new BottomSheetItemWithDescription.Builder()
|
||||||
|
.setCustomView(itemView)
|
||||||
|
.create());
|
||||||
|
|
||||||
|
int padding = getResources().getDimensionPixelSize(R.dimen.content_padding_small);
|
||||||
|
final int paddingSmall = getResources().getDimensionPixelSize(R.dimen.content_padding_small);
|
||||||
|
|
||||||
|
items.add(new DividerSpaceItem(context, padding));
|
||||||
|
|
||||||
|
LinearLayout showTrackOnMapView = itemView.findViewById(R.id.show_track_on_map);
|
||||||
|
TextView showTrackOnMapTitle = showTrackOnMapView.findViewById(R.id.title);
|
||||||
|
showTrackOnMapTitle.setText(R.string.show_track_on_map);
|
||||||
|
|
||||||
|
ImageView trackAppearanceIcon = showTrackOnMapView.findViewById(R.id.icon_after_divider);
|
||||||
|
|
||||||
|
int color = settings.CURRENT_TRACK_COLOR.get();
|
||||||
|
String width = settings.CURRENT_TRACK_WIDTH.get();
|
||||||
|
boolean showArrows = settings.CURRENT_TRACK_SHOW_ARROWS.get();
|
||||||
|
Drawable drawable = TrackAppearanceFragment.getTrackIcon(app, width, showArrows, color);
|
||||||
|
|
||||||
|
trackAppearanceIcon.setImageDrawable(drawable);
|
||||||
|
trackAppearanceIcon.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
MapActivity mapActivity = getMapActivity();
|
||||||
|
if (mapActivity != null) {
|
||||||
|
hide();
|
||||||
|
SelectedGpxFile selectedGpxFile = app.getSavingTrackHelper().getCurrentTrack();
|
||||||
|
TrackAppearanceFragment.showInstance(mapActivity, selectedGpxFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
upDownBtn = itemView.findViewById(R.id.up_down_button);
|
||||||
|
upDownBtn.setOnClickListener(new View.OnClickListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
toggleInfoView();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
final int secondsLength = SECONDS.length;
|
||||||
|
final int minutesLength = MINUTES.length;
|
||||||
|
|
||||||
|
intervalValueView = itemView.findViewById(R.id.interval_value);
|
||||||
|
updateIntervalLegend();
|
||||||
|
|
||||||
|
RangeSlider intervalSlider = itemView.findViewById(R.id.interval_slider);
|
||||||
|
intervalSlider.setValueTo(secondsLength + minutesLength - 1);
|
||||||
|
intervalSlider.addOnChangeListener(new RangeSlider.OnChangeListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onValueChange(@NonNull RangeSlider slider, float value, boolean fromUser) {
|
||||||
|
int progress = (int) value;
|
||||||
|
if (progress == 0) {
|
||||||
|
settings.SAVE_GLOBAL_TRACK_INTERVAL.set(0);
|
||||||
|
} else if (progress < secondsLength) {
|
||||||
|
settings.SAVE_GLOBAL_TRACK_INTERVAL.set(SECONDS[progress] * 1000);
|
||||||
|
} else {
|
||||||
|
settings.SAVE_GLOBAL_TRACK_INTERVAL.set(MINUTES[progress - secondsLength] * 60 * 1000);
|
||||||
|
}
|
||||||
|
updateIntervalLegend();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
for (int i = 0; i < secondsLength + minutesLength; i++) {
|
||||||
|
if (i < secondsLength) {
|
||||||
|
if (settings.SAVE_GLOBAL_TRACK_INTERVAL.get() <= SECONDS[i] * 1000) {
|
||||||
|
intervalSlider.setValues((float) i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (settings.SAVE_GLOBAL_TRACK_INTERVAL.get() <= MINUTES[i - secondsLength] * 1000 * 60) {
|
||||||
|
intervalSlider.setValues((float) i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
boolean checked = !settings.SAVE_GLOBAL_TRACK_REMEMBER.get();
|
||||||
|
confirmEveryRun = itemView.findViewById(R.id.confirm_every_run);
|
||||||
|
confirmEveryRun.setChecked(checked);
|
||||||
|
setBackgroundAndPadding(checked, paddingSmall);
|
||||||
|
confirmEveryRun.setOnCheckedChangeListener(new OnCheckedChangeListener() {
|
||||||
|
@Override
|
||||||
|
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||||
|
setBackgroundAndPadding(isChecked, paddingSmall);
|
||||||
|
settings.SAVE_GLOBAL_TRACK_REMEMBER.set(!isChecked);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
SwitchCompat showTrackOnMapButton = showTrackOnMapView.findViewById(R.id.switch_button);
|
||||||
|
showTrackOnMapButton.setChecked(app.getSelectedGpxHelper().getSelectedCurrentRecordingTrack() != null);
|
||||||
|
showTrackOnMapButton.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||||
|
app.getSelectedGpxHelper().selectGpxFile(app.getSavingTrackHelper().getCurrentGpx(), isChecked, false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
UiUtilities.setupCompoundButton(showTrackOnMapButton, nightMode, PROFILE_DEPENDENT);
|
||||||
|
|
||||||
|
updateUpDownBtn();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateIntervalLegend() {
|
||||||
|
String text = getString(R.string.save_track_interval_globally);
|
||||||
|
String textValue;
|
||||||
|
int interval = settings.SAVE_GLOBAL_TRACK_INTERVAL.get();
|
||||||
|
if (interval == 0) {
|
||||||
|
textValue = getString(R.string.int_continuosly);
|
||||||
|
} else {
|
||||||
|
int seconds = interval / 1000;
|
||||||
|
if (seconds <= SECONDS[SECONDS.length - 1]) {
|
||||||
|
textValue = seconds + " " + getString(R.string.int_seconds);
|
||||||
|
} else {
|
||||||
|
textValue = (seconds / 60) + " " + getString(R.string.int_min);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String textAll = getString(R.string.ltr_or_rtl_combine_via_colon, text, textValue);
|
||||||
|
Typeface typeface = FontCache.getRobotoMedium(app);
|
||||||
|
SpannableString spannableString = UiUtilities.createCustomFontSpannable(typeface, textAll, textValue);
|
||||||
|
intervalValueView.setText(spannableString);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void show() {
|
||||||
|
Dialog dialog = getDialog();
|
||||||
|
if (dialog != null) {
|
||||||
|
dialog.show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void hide() {
|
||||||
|
Dialog dialog = getDialog();
|
||||||
|
if (dialog != null) {
|
||||||
|
dialog.hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setBackgroundAndPadding(boolean isChecked, int paddingSmall) {
|
||||||
|
if (nightMode) {
|
||||||
|
confirmEveryRun.setBackgroundResource(
|
||||||
|
isChecked ? R.drawable.layout_bg_dark_solid : R.drawable.layout_bg_dark);
|
||||||
|
} else {
|
||||||
|
confirmEveryRun.setBackgroundResource(
|
||||||
|
isChecked ? R.drawable.layout_bg_solid : R.drawable.layout_bg);
|
||||||
|
}
|
||||||
|
confirmEveryRun.setPadding(paddingSmall, 0, paddingSmall, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateUpDownBtn() {
|
||||||
|
int iconId = infoExpanded ? R.drawable.ic_action_arrow_down : R.drawable.ic_action_arrow_up;
|
||||||
|
upDownBtn.setImageDrawable(getContentIcon(iconId));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void toggleInfoView() {
|
||||||
|
infoExpanded = !infoExpanded;
|
||||||
|
AndroidUiHelper.updateVisibility(confirmEveryRun, infoExpanded);
|
||||||
|
updateUpDownBtn();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean useVerticalButtons() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getRightBottomButtonTextId() {
|
||||||
|
return R.string.start_recording;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getDismissButtonTextId() {
|
||||||
|
return R.string.shared_string_cancel;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected DialogButtonType getRightBottomButtonType() {
|
||||||
|
return DialogButtonType.PRIMARY;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getSecondDividerHeight() {
|
||||||
|
return getResources().getDimensionPixelSize(R.dimen.bottom_sheet_icon_margin);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onRightBottomButtonClick() {
|
||||||
|
app.getSavingTrackHelper().startNewSegment();
|
||||||
|
settings.SAVE_GLOBAL_TRACK_TO_GPX.set(true);
|
||||||
|
app.startNavigationService(NavigationService.USED_BY_GPX);
|
||||||
|
dismiss();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public MapActivity getMapActivity() {
|
||||||
|
Activity activity = getActivity();
|
||||||
|
if (activity instanceof MapActivity) {
|
||||||
|
return (MapActivity) activity;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void showInstance(@NonNull FragmentManager fragmentManager) {
|
||||||
|
if (!fragmentManager.isStateSaved()) {
|
||||||
|
TripRecordingBottomSheet fragment = new TripRecordingBottomSheet();
|
||||||
|
fragment.show(fragmentManager, TAG);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
package net.osmand.plus.onlinerouting;
|
||||||
|
|
||||||
|
public enum EngineParameter {
|
||||||
|
KEY,
|
||||||
|
VEHICLE_KEY,
|
||||||
|
CUSTOM_NAME,
|
||||||
|
NAME_INDEX,
|
||||||
|
CUSTOM_URL,
|
||||||
|
API_KEY
|
||||||
|
}
|
|
@ -1,24 +0,0 @@
|
||||||
package net.osmand.plus.onlinerouting;
|
|
||||||
|
|
||||||
public enum EngineType {
|
|
||||||
|
|
||||||
GRAPHHOPPER("Graphhopper", "https://graphhopper.com/api/1/route"),
|
|
||||||
OSRM("OSRM", "https://router.project-osrm.org/route/v1/"),
|
|
||||||
ORS("Openroute Service", "https://api.openrouteservice.org/v2/directions/");
|
|
||||||
|
|
||||||
private String title;
|
|
||||||
private String standardUrl;
|
|
||||||
|
|
||||||
EngineType(String title, String standardUrl) {
|
|
||||||
this.title = title;
|
|
||||||
this.standardUrl = standardUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getTitle() {
|
|
||||||
return title;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getStandardUrl() {
|
|
||||||
return standardUrl;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,109 +0,0 @@
|
||||||
package net.osmand.plus.onlinerouting;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
|
|
||||||
import net.osmand.plus.R;
|
|
||||||
import net.osmand.util.Algorithms;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class OnlineRoutingEngine {
|
|
||||||
|
|
||||||
public final static String ONLINE_ROUTING_ENGINE_PREFIX = "online_routing_engine_";
|
|
||||||
|
|
||||||
public enum EngineParameter {
|
|
||||||
CUSTOM_NAME,
|
|
||||||
CUSTOM_URL,
|
|
||||||
API_KEY
|
|
||||||
}
|
|
||||||
|
|
||||||
private String stringKey;
|
|
||||||
private EngineType type;
|
|
||||||
private String vehicleKey;
|
|
||||||
private Map<String, String> params = new HashMap<>();
|
|
||||||
|
|
||||||
public OnlineRoutingEngine(@NonNull String stringKey,
|
|
||||||
@NonNull EngineType type,
|
|
||||||
@NonNull String vehicleKey,
|
|
||||||
@Nullable Map<String, String> params) {
|
|
||||||
this(stringKey, type, vehicleKey);
|
|
||||||
if (!Algorithms.isEmpty(params)) {
|
|
||||||
this.params.putAll(params);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public OnlineRoutingEngine(@NonNull String stringKey,
|
|
||||||
@NonNull EngineType type,
|
|
||||||
@NonNull String vehicleKey) {
|
|
||||||
this.stringKey = stringKey;
|
|
||||||
this.type = type;
|
|
||||||
this.vehicleKey = vehicleKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getStringKey() {
|
|
||||||
return stringKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
public EngineType getType() {
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getBaseUrl() {
|
|
||||||
String customUrl = getParameter(EngineParameter.CUSTOM_URL);
|
|
||||||
if (Algorithms.isEmpty(customUrl)) {
|
|
||||||
return type.getStandardUrl();
|
|
||||||
}
|
|
||||||
return customUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getVehicleKey() {
|
|
||||||
return vehicleKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<String, String> getParams() {
|
|
||||||
return params;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getParameter(EngineParameter paramKey) {
|
|
||||||
return params.get(paramKey.name());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void putParameter(EngineParameter paramKey, String paramValue) {
|
|
||||||
params.put(paramKey.name(), paramValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getName(@NonNull Context ctx) {
|
|
||||||
String customName = getParameter(EngineParameter.CUSTOM_NAME);
|
|
||||||
if (customName != null) {
|
|
||||||
return customName;
|
|
||||||
} else {
|
|
||||||
return getStandardName(ctx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getStandardName(@NonNull Context ctx) {
|
|
||||||
return getStandardName(ctx, type, vehicleKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getStandardName(@NonNull Context ctx,
|
|
||||||
@NonNull EngineType type,
|
|
||||||
@NonNull String vehicleKey) {
|
|
||||||
String vehicleTitle = VehicleType.toHumanString(ctx, vehicleKey);
|
|
||||||
String pattern = ctx.getString(R.string.ltr_or_rtl_combine_via_dash);
|
|
||||||
return String.format(pattern, type.getTitle(), vehicleTitle);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static OnlineRoutingEngine createNewEngine(@NonNull EngineType type,
|
|
||||||
@NonNull String vehicleKey,
|
|
||||||
@Nullable Map<String, String> params) {
|
|
||||||
return new OnlineRoutingEngine(generateKey(), type, vehicleKey, params);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String generateKey() {
|
|
||||||
return ONLINE_ROUTING_ENGINE_PREFIX + System.currentTimeMillis();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,609 +0,0 @@
|
||||||
package net.osmand.plus.onlinerouting;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.os.Build;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.View.OnClickListener;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.FrameLayout;
|
|
||||||
import android.widget.ImageView;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.appcompat.widget.Toolbar;
|
|
||||||
import androidx.fragment.app.FragmentActivity;
|
|
||||||
import androidx.fragment.app.FragmentManager;
|
|
||||||
|
|
||||||
import net.osmand.AndroidNetworkUtils;
|
|
||||||
import net.osmand.AndroidNetworkUtils.OnRequestResultListener;
|
|
||||||
import net.osmand.AndroidUtils;
|
|
||||||
import net.osmand.CallbackWithObject;
|
|
||||||
import net.osmand.data.LatLon;
|
|
||||||
import net.osmand.plus.OsmandApplication;
|
|
||||||
import net.osmand.plus.R;
|
|
||||||
import net.osmand.plus.UiUtilities;
|
|
||||||
import net.osmand.plus.UiUtilities.DialogButtonType;
|
|
||||||
import net.osmand.plus.activities.MapActivity;
|
|
||||||
import net.osmand.plus.base.BaseOsmAndFragment;
|
|
||||||
import net.osmand.plus.mapcontextmenu.other.HorizontalSelectionAdapter.HorizontalSelectionItem;
|
|
||||||
import net.osmand.plus.onlinerouting.OnlineRoutingCard.OnTextChangedListener;
|
|
||||||
import net.osmand.plus.onlinerouting.OnlineRoutingEngine.EngineParameter;
|
|
||||||
import net.osmand.plus.routepreparationmenu.cards.BaseCard;
|
|
||||||
import net.osmand.plus.settings.backend.ApplicationMode;
|
|
||||||
import net.osmand.util.Algorithms;
|
|
||||||
|
|
||||||
import org.json.JSONException;
|
|
||||||
import org.json.JSONObject;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class OnlineRoutingEngineFragment extends BaseOsmAndFragment {
|
|
||||||
|
|
||||||
public static final String TAG = OnlineRoutingEngineFragment.class.getSimpleName();
|
|
||||||
|
|
||||||
private static final String ENGINE_NAME_KEY = "engine_name";
|
|
||||||
private static final String ENGINE_SERVER_KEY = "engine_server";
|
|
||||||
private static final String ENGINE_SERVER_URL_KEY = "engine_server_url";
|
|
||||||
private static final String ENGINE_VEHICLE_TYPE_KEY = "engine_vehicle_type";
|
|
||||||
private static final String ENGINE_CUSTOM_VEHICLE_KEY = "engine_custom_vehicle";
|
|
||||||
private static final String ENGINE_API_KEY_KEY = "engine_api_key";
|
|
||||||
private static final String EXAMPLE_LOCATION_KEY = "example_location";
|
|
||||||
private static final String APP_MODE_KEY = "app_mode";
|
|
||||||
private static final String EDITED_ENGINE_KEY = "edited_engine_key";
|
|
||||||
|
|
||||||
private OsmandApplication app;
|
|
||||||
private MapActivity mapActivity;
|
|
||||||
private OnlineRoutingHelper helper;
|
|
||||||
|
|
||||||
private View view;
|
|
||||||
private ViewGroup segmentsContainer;
|
|
||||||
private OnlineRoutingCard nameCard;
|
|
||||||
private OnlineRoutingCard typeCard;
|
|
||||||
private OnlineRoutingCard vehicleCard;
|
|
||||||
private OnlineRoutingCard apiKeyCard;
|
|
||||||
private OnlineRoutingCard exampleCard;
|
|
||||||
private View testResultsContainer;
|
|
||||||
|
|
||||||
private ApplicationMode appMode;
|
|
||||||
|
|
||||||
private OnlineRoutingEngineObject engine;
|
|
||||||
private ExampleLocation selectedLocation;
|
|
||||||
private String editedEngineKey;
|
|
||||||
|
|
||||||
private enum ExampleLocation {
|
|
||||||
|
|
||||||
AMSTERDAM("Amsterdam",
|
|
||||||
new LatLon(52.379189, 4.899431),
|
|
||||||
new LatLon(52.308056, 4.764167)),
|
|
||||||
|
|
||||||
BERLIN("Berlin",
|
|
||||||
new LatLon(52.520008, 13.404954),
|
|
||||||
new LatLon(52.3666652, 13.501997992)),
|
|
||||||
|
|
||||||
NEW_YORK("New York",
|
|
||||||
new LatLon(43.000000, -75.000000),
|
|
||||||
new LatLon(40.641766, -73.780968)),
|
|
||||||
|
|
||||||
PARIS("Paris",
|
|
||||||
new LatLon(48.864716, 2.349014),
|
|
||||||
new LatLon(48.948437, 2.434931));
|
|
||||||
|
|
||||||
ExampleLocation(String name, LatLon cityCenterLatLon, LatLon cityAirportLatLon) {
|
|
||||||
this.name = name;
|
|
||||||
this.cityCenterLatLon = cityCenterLatLon;
|
|
||||||
this.cityAirportLatLon = cityAirportLatLon;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String name;
|
|
||||||
private LatLon cityCenterLatLon;
|
|
||||||
private LatLon cityAirportLatLon;
|
|
||||||
|
|
||||||
public String getName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public LatLon getCityCenterLatLon() {
|
|
||||||
return cityCenterLatLon;
|
|
||||||
}
|
|
||||||
|
|
||||||
public LatLon getCityAirportLatLon() {
|
|
||||||
return cityAirportLatLon;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
app = requireMyApplication();
|
|
||||||
mapActivity = getMapActivity();
|
|
||||||
helper = app.getOnlineRoutingHelper();
|
|
||||||
engine = new OnlineRoutingEngineObject();
|
|
||||||
if (savedInstanceState != null) {
|
|
||||||
restoreState(savedInstanceState);
|
|
||||||
} else {
|
|
||||||
initState();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public View onCreateView(@NonNull LayoutInflater inflater,
|
|
||||||
@Nullable ViewGroup container,
|
|
||||||
@Nullable Bundle savedInstanceState) {
|
|
||||||
view = getInflater().inflate(
|
|
||||||
R.layout.online_routing_engine_fragment, container, false);
|
|
||||||
segmentsContainer = (ViewGroup) view.findViewById(R.id.segments_container);
|
|
||||||
if (Build.VERSION.SDK_INT >= 21) {
|
|
||||||
AndroidUtils.addStatusBarPadding21v(getContext(), view);
|
|
||||||
}
|
|
||||||
setupToolbar((Toolbar) view.findViewById(R.id.toolbar));
|
|
||||||
|
|
||||||
setupNameCard();
|
|
||||||
setupTypeCard();
|
|
||||||
setupVehicleCard();
|
|
||||||
setupApiKeyCard();
|
|
||||||
setupExampleCard();
|
|
||||||
setupResultsContainer();
|
|
||||||
addSpaceSegment();
|
|
||||||
|
|
||||||
setupButtons();
|
|
||||||
|
|
||||||
updateCardViews(nameCard, typeCard, vehicleCard, exampleCard);
|
|
||||||
return view;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setupNameCard() {
|
|
||||||
nameCard = new OnlineRoutingCard(mapActivity, isNightMode());
|
|
||||||
nameCard.build(mapActivity);
|
|
||||||
nameCard.setDescription(getString(R.string.select_nav_profile_dialog_message));
|
|
||||||
nameCard.setEditedText(engine.getName(app));
|
|
||||||
nameCard.setFieldBoxLabelText(getString(R.string.shared_string_name));
|
|
||||||
nameCard.setOnTextChangedListener(new OnTextChangedListener() {
|
|
||||||
@Override
|
|
||||||
public void onTextChanged(boolean changedByUser, String text) {
|
|
||||||
if (changedByUser) {
|
|
||||||
engine.customName = text;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
nameCard.showDivider();
|
|
||||||
segmentsContainer.addView(nameCard.getView());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setupTypeCard() {
|
|
||||||
typeCard = new OnlineRoutingCard(mapActivity, isNightMode());
|
|
||||||
typeCard.build(mapActivity);
|
|
||||||
typeCard.setHeaderTitle(getString(R.string.shared_string_type));
|
|
||||||
List<HorizontalSelectionItem> serverItems = new ArrayList<>();
|
|
||||||
for (EngineType server : EngineType.values()) {
|
|
||||||
serverItems.add(new HorizontalSelectionItem(server.getTitle(), server));
|
|
||||||
}
|
|
||||||
typeCard.setSelectionMenu(serverItems, engine.type.getTitle(),
|
|
||||||
new CallbackWithObject<HorizontalSelectionItem>() {
|
|
||||||
@Override
|
|
||||||
public boolean processResult(HorizontalSelectionItem result) {
|
|
||||||
EngineType type = (EngineType) result.getObject();
|
|
||||||
if (engine.type != type) {
|
|
||||||
engine.type = type;
|
|
||||||
updateCardViews(nameCard, typeCard, exampleCard);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
typeCard.setOnTextChangedListener(new OnTextChangedListener() {
|
|
||||||
@Override
|
|
||||||
public void onTextChanged(boolean editedByUser, String text) {
|
|
||||||
if (editedByUser) {
|
|
||||||
engine.customServerUrl = text;
|
|
||||||
updateCardViews(exampleCard);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
typeCard.setFieldBoxLabelText(getString(R.string.shared_string_server_url));
|
|
||||||
typeCard.showDivider();
|
|
||||||
segmentsContainer.addView(typeCard.getView());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setupVehicleCard() {
|
|
||||||
vehicleCard = new OnlineRoutingCard(mapActivity, isNightMode());
|
|
||||||
vehicleCard.build(mapActivity);
|
|
||||||
vehicleCard.setHeaderTitle(getString(R.string.shared_string_vehicle));
|
|
||||||
List<HorizontalSelectionItem> vehicleItems = new ArrayList<>();
|
|
||||||
for (VehicleType vehicle : VehicleType.values()) {
|
|
||||||
vehicleItems.add(new HorizontalSelectionItem(vehicle.getTitle(app), vehicle));
|
|
||||||
}
|
|
||||||
vehicleCard.setSelectionMenu(vehicleItems, engine.vehicleType.getTitle(app),
|
|
||||||
new CallbackWithObject<HorizontalSelectionItem>() {
|
|
||||||
@Override
|
|
||||||
public boolean processResult(HorizontalSelectionItem result) {
|
|
||||||
VehicleType vehicle = (VehicleType) result.getObject();
|
|
||||||
if (engine.vehicleType != vehicle) {
|
|
||||||
engine.vehicleType = vehicle;
|
|
||||||
updateCardViews(nameCard, vehicleCard, exampleCard);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
vehicleCard.setFieldBoxLabelText(getString(R.string.shared_string_custom));
|
|
||||||
vehicleCard.setOnTextChangedListener(new OnTextChangedListener() {
|
|
||||||
@Override
|
|
||||||
public void onTextChanged(boolean editedByUser, String text) {
|
|
||||||
if (editedByUser) {
|
|
||||||
engine.customVehicleKey = text;
|
|
||||||
updateCardViews(nameCard, exampleCard);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
vehicleCard.setEditedText(engine.customVehicleKey);
|
|
||||||
vehicleCard.setFieldBoxHelperText(getString(R.string.shared_string_enter_param));
|
|
||||||
vehicleCard.showDivider();
|
|
||||||
segmentsContainer.addView(vehicleCard.getView());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setupApiKeyCard() {
|
|
||||||
apiKeyCard = new OnlineRoutingCard(mapActivity, isNightMode());
|
|
||||||
apiKeyCard.build(mapActivity);
|
|
||||||
apiKeyCard.setHeaderTitle(getString(R.string.shared_string_api_key));
|
|
||||||
apiKeyCard.setFieldBoxLabelText(getString(R.string.keep_it_empty_if_not));
|
|
||||||
apiKeyCard.setEditedText(engine.apiKey);
|
|
||||||
apiKeyCard.showDivider();
|
|
||||||
apiKeyCard.setOnTextChangedListener(new OnTextChangedListener() {
|
|
||||||
@Override
|
|
||||||
public void onTextChanged(boolean editedByUser, String text) {
|
|
||||||
engine.apiKey = text;
|
|
||||||
updateCardViews(exampleCard);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
segmentsContainer.addView(apiKeyCard.getView());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setupExampleCard() {
|
|
||||||
exampleCard = new OnlineRoutingCard(mapActivity, isNightMode());
|
|
||||||
exampleCard.build(mapActivity);
|
|
||||||
exampleCard.setHeaderTitle(getString(R.string.shared_string_example));
|
|
||||||
List<HorizontalSelectionItem> locationItems = new ArrayList<>();
|
|
||||||
for (ExampleLocation location : ExampleLocation.values()) {
|
|
||||||
locationItems.add(new HorizontalSelectionItem(location.getName(), location));
|
|
||||||
}
|
|
||||||
exampleCard.setSelectionMenu(locationItems, selectedLocation.getName(),
|
|
||||||
new CallbackWithObject<HorizontalSelectionItem>() {
|
|
||||||
@Override
|
|
||||||
public boolean processResult(HorizontalSelectionItem result) {
|
|
||||||
ExampleLocation location = (ExampleLocation) result.getObject();
|
|
||||||
if (selectedLocation != location) {
|
|
||||||
selectedLocation = location;
|
|
||||||
updateCardViews(exampleCard);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
exampleCard.setFieldBoxHelperText(getString(R.string.online_routing_example_hint));
|
|
||||||
exampleCard.setButton(getString(R.string.test_route_calculation), new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
testEngineWork();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
segmentsContainer.addView(exampleCard.getView());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setupResultsContainer() {
|
|
||||||
testResultsContainer = getInflater().inflate(
|
|
||||||
R.layout.bottom_sheet_item_with_descr_64dp, segmentsContainer, false);
|
|
||||||
testResultsContainer.setVisibility(View.GONE);
|
|
||||||
segmentsContainer.addView(testResultsContainer);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addSpaceSegment() {
|
|
||||||
int space = (int) getResources().getDimension(R.dimen.empty_state_text_button_padding_top);
|
|
||||||
View bottomSpaceView = new View(app);
|
|
||||||
bottomSpaceView.setLayoutParams(
|
|
||||||
new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, space));
|
|
||||||
segmentsContainer.addView(bottomSpaceView);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setupToolbar(Toolbar toolbar) {
|
|
||||||
ImageView navigationIcon = toolbar.findViewById(R.id.close_button);
|
|
||||||
navigationIcon.setImageResource(R.drawable.ic_action_close);
|
|
||||||
navigationIcon.setOnClickListener(new OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
dismiss();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
TextView title = toolbar.findViewById(R.id.toolbar_title);
|
|
||||||
toolbar.findViewById(R.id.toolbar_subtitle).setVisibility(View.GONE);
|
|
||||||
View actionBtn = toolbar.findViewById(R.id.action_button);
|
|
||||||
if (isEditingMode()) {
|
|
||||||
title.setText(getString(R.string.edit_online_routing_engine));
|
|
||||||
ImageView ivBtn = toolbar.findViewById(R.id.action_button_icon);
|
|
||||||
ivBtn.setImageDrawable(
|
|
||||||
getIcon(R.drawable.ic_action_delete_dark, R.color.color_osm_edit_delete));
|
|
||||||
actionBtn.setOnClickListener(new OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
deleteEngine();
|
|
||||||
dismiss();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
title.setText(getString(R.string.add_online_routing_engine));
|
|
||||||
actionBtn.setVisibility(View.GONE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateCardViews(BaseCard... cardsToUpdate) {
|
|
||||||
for (BaseCard card : cardsToUpdate) {
|
|
||||||
if (nameCard.equals(card)) {
|
|
||||||
if (Algorithms.isEmpty(engine.customName)) {
|
|
||||||
String name;
|
|
||||||
if (Algorithms.isEmpty(engine.getVehicleKey())) {
|
|
||||||
name = engine.type.getTitle();
|
|
||||||
} else {
|
|
||||||
name = OnlineRoutingEngine.getStandardName(app, engine.type, engine.getVehicleKey());
|
|
||||||
}
|
|
||||||
nameCard.setEditedText(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (typeCard.equals(card)) {
|
|
||||||
typeCard.setHeaderSubtitle(engine.type.getTitle());
|
|
||||||
typeCard.setEditedText(engine.getBaseUrl());
|
|
||||||
if (engine.type == EngineType.GRAPHHOPPER || engine.type == EngineType.ORS) {
|
|
||||||
apiKeyCard.show();
|
|
||||||
} else {
|
|
||||||
apiKeyCard.hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (vehicleCard.equals(card)) {
|
|
||||||
VehicleType vt = VehicleType.getVehicleByKey(engine.getVehicleKey());
|
|
||||||
vehicleCard.setHeaderSubtitle(vt.getTitle(app));
|
|
||||||
if (vt == VehicleType.CUSTOM) {
|
|
||||||
vehicleCard.showFieldBox();
|
|
||||||
vehicleCard.setEditedText(engine.getVehicleKey());
|
|
||||||
} else {
|
|
||||||
vehicleCard.hideFieldBox();
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (exampleCard.equals(card)) {
|
|
||||||
exampleCard.setEditedText(getTestUrl());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setupButtons() {
|
|
||||||
boolean nightMode = isNightMode();
|
|
||||||
View cancelButton = view.findViewById(R.id.dismiss_button);
|
|
||||||
UiUtilities.setupDialogButton(nightMode, cancelButton,
|
|
||||||
DialogButtonType.SECONDARY, R.string.shared_string_cancel);
|
|
||||||
cancelButton.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
dismiss();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
view.findViewById(R.id.buttons_divider).setVisibility(View.VISIBLE);
|
|
||||||
|
|
||||||
View saveButton = view.findViewById(R.id.right_bottom_button);
|
|
||||||
UiUtilities.setupDialogButton(nightMode, saveButton,
|
|
||||||
UiUtilities.DialogButtonType.PRIMARY, R.string.shared_string_save);
|
|
||||||
saveButton.setVisibility(View.VISIBLE);
|
|
||||||
saveButton.setOnClickListener(new OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
saveChanges();
|
|
||||||
dismiss();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void saveChanges() {
|
|
||||||
OnlineRoutingEngine engineToSave;
|
|
||||||
if (isEditingMode()) {
|
|
||||||
engineToSave = new OnlineRoutingEngine(editedEngineKey, engine.type, engine.getVehicleKey());
|
|
||||||
} else {
|
|
||||||
engineToSave = OnlineRoutingEngine.createNewEngine(engine.type, engine.getVehicleKey(), null);
|
|
||||||
}
|
|
||||||
|
|
||||||
engineToSave.putParameter(EngineParameter.CUSTOM_NAME, engine.customName);
|
|
||||||
engineToSave.putParameter(EngineParameter.CUSTOM_URL, engine.customServerUrl);
|
|
||||||
if (engine.type == EngineType.GRAPHHOPPER || engine.type == EngineType.ORS) {
|
|
||||||
engineToSave.putParameter(EngineParameter.API_KEY, engine.apiKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
helper.saveEngine(engineToSave);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void deleteEngine() {
|
|
||||||
helper.deleteEngine(editedEngineKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getTestUrl() {
|
|
||||||
List<LatLon> path = new ArrayList<>();
|
|
||||||
path.add(selectedLocation.getCityCenterLatLon());
|
|
||||||
path.add(selectedLocation.getCityAirportLatLon());
|
|
||||||
OnlineRoutingEngine tmpEngine =
|
|
||||||
OnlineRoutingEngine.createNewEngine(engine.type, engine.getVehicleKey(), null);
|
|
||||||
tmpEngine.putParameter(EngineParameter.CUSTOM_URL, engine.customServerUrl);
|
|
||||||
tmpEngine.putParameter(EngineParameter.API_KEY, engine.apiKey);
|
|
||||||
return helper.createFullUrl(tmpEngine, path);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void testEngineWork() {
|
|
||||||
final EngineType type = engine.type;
|
|
||||||
final ExampleLocation location = selectedLocation;
|
|
||||||
AndroidNetworkUtils.sendRequestAsync(app, exampleCard.getEditedText(), null,
|
|
||||||
null, false, false, new OnRequestResultListener() {
|
|
||||||
@Override
|
|
||||||
public void onResult(String response) {
|
|
||||||
boolean resultOk = false;
|
|
||||||
if (response != null) {
|
|
||||||
try {
|
|
||||||
JSONObject obj = new JSONObject(response);
|
|
||||||
|
|
||||||
if (type == EngineType.GRAPHHOPPER) {
|
|
||||||
resultOk = obj.has("paths");
|
|
||||||
} else if (type == EngineType.OSRM) {
|
|
||||||
resultOk = obj.has("routes");
|
|
||||||
} else if (type == EngineType.ORS) {
|
|
||||||
resultOk = obj.has("features");
|
|
||||||
}
|
|
||||||
} catch (JSONException e) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
showTestResults(resultOk, location);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void showTestResults(boolean resultOk, ExampleLocation location) {
|
|
||||||
testResultsContainer.setVisibility(View.VISIBLE);
|
|
||||||
ImageView ivImage = testResultsContainer.findViewById(R.id.icon);
|
|
||||||
TextView tvTitle = testResultsContainer.findViewById(R.id.title);
|
|
||||||
TextView tvDescription = testResultsContainer.findViewById(R.id.description);
|
|
||||||
if (resultOk) {
|
|
||||||
ivImage.setImageDrawable(getContentIcon(R.drawable.ic_action_gdirections_dark));
|
|
||||||
tvTitle.setText(getString(R.string.shared_string_ok));
|
|
||||||
} else {
|
|
||||||
ivImage.setImageDrawable(getContentIcon(R.drawable.ic_action_alert));
|
|
||||||
tvTitle.setText(getString(R.string.message_error_recheck_parameters));
|
|
||||||
}
|
|
||||||
tvDescription.setText(location.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isEditingMode() {
|
|
||||||
return editedEngineKey != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onSaveInstanceState(@NonNull Bundle outState) {
|
|
||||||
super.onSaveInstanceState(outState);
|
|
||||||
saveState(outState);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void saveState(Bundle outState) {
|
|
||||||
outState.putString(ENGINE_NAME_KEY, engine.customName);
|
|
||||||
outState.putString(ENGINE_SERVER_KEY, engine.type.name());
|
|
||||||
outState.putString(ENGINE_SERVER_URL_KEY, engine.customServerUrl);
|
|
||||||
outState.putString(ENGINE_VEHICLE_TYPE_KEY, engine.vehicleType.name());
|
|
||||||
outState.putString(ENGINE_CUSTOM_VEHICLE_KEY, engine.customVehicleKey);
|
|
||||||
outState.putString(ENGINE_API_KEY_KEY, engine.apiKey);
|
|
||||||
outState.putString(EXAMPLE_LOCATION_KEY, selectedLocation.name());
|
|
||||||
if (appMode != null) {
|
|
||||||
outState.putString(APP_MODE_KEY, appMode.getStringKey());
|
|
||||||
}
|
|
||||||
outState.putString(EDITED_ENGINE_KEY, editedEngineKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void restoreState(Bundle savedState) {
|
|
||||||
engine.customName = savedState.getString(ENGINE_NAME_KEY);
|
|
||||||
engine.type = EngineType.valueOf(savedState.getString(ENGINE_SERVER_KEY));
|
|
||||||
engine.customServerUrl = savedState.getString(ENGINE_SERVER_URL_KEY);
|
|
||||||
engine.vehicleType = VehicleType.valueOf(savedState.getString(ENGINE_VEHICLE_TYPE_KEY));
|
|
||||||
engine.customVehicleKey = savedState.getString(ENGINE_CUSTOM_VEHICLE_KEY);
|
|
||||||
engine.apiKey = savedState.getString(ENGINE_API_KEY_KEY);
|
|
||||||
selectedLocation = ExampleLocation.valueOf(savedState.getString(EXAMPLE_LOCATION_KEY));
|
|
||||||
appMode = ApplicationMode.valueOfStringKey(savedState.getString(APP_MODE_KEY), null);
|
|
||||||
editedEngineKey = savedState.getString(EDITED_ENGINE_KEY);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initState() {
|
|
||||||
engine.type = EngineType.values()[0];
|
|
||||||
engine.vehicleType = VehicleType.values()[0];
|
|
||||||
selectedLocation = ExampleLocation.values()[0];
|
|
||||||
|
|
||||||
if (isEditingMode()) {
|
|
||||||
OnlineRoutingEngine editedEngine = helper.getEngineByKey(editedEngineKey);
|
|
||||||
if (editedEngine != null) {
|
|
||||||
engine.customName = editedEngine.getParameter(EngineParameter.CUSTOM_NAME);
|
|
||||||
engine.type = editedEngine.getType();
|
|
||||||
String vehicleKey = editedEngine.getVehicleKey();
|
|
||||||
if (vehicleKey != null) {
|
|
||||||
VehicleType vehicleType = VehicleType.getVehicleByKey(vehicleKey);
|
|
||||||
if (vehicleType == VehicleType.CUSTOM) {
|
|
||||||
engine.customVehicleKey = vehicleKey;
|
|
||||||
}
|
|
||||||
engine.vehicleType = vehicleType;
|
|
||||||
}
|
|
||||||
engine.apiKey = editedEngine.getParameter(EngineParameter.API_KEY);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void dismiss() {
|
|
||||||
FragmentActivity activity = getActivity();
|
|
||||||
if (activity != null) {
|
|
||||||
activity.onBackPressed();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isNightMode() {
|
|
||||||
return !app.getSettings().isLightContentForMode(appMode);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
private MapActivity getMapActivity() {
|
|
||||||
FragmentActivity activity = getActivity();
|
|
||||||
if (activity instanceof MapActivity) {
|
|
||||||
return (MapActivity) activity;
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private LayoutInflater getInflater() {
|
|
||||||
return UiUtilities.getInflater(mapActivity, isNightMode());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void showInstance(@NonNull FragmentActivity activity,
|
|
||||||
@NonNull ApplicationMode appMode,
|
|
||||||
String editedEngineKey) {
|
|
||||||
FragmentManager fm = activity.getSupportFragmentManager();
|
|
||||||
if (!fm.isStateSaved() && fm.findFragmentByTag(OnlineRoutingEngineFragment.TAG) == null) {
|
|
||||||
OnlineRoutingEngineFragment fragment = new OnlineRoutingEngineFragment();
|
|
||||||
fragment.appMode = appMode;
|
|
||||||
fragment.editedEngineKey = editedEngineKey;
|
|
||||||
fm.beginTransaction()
|
|
||||||
.add(R.id.fragmentContainer, fragment, TAG)
|
|
||||||
.addToBackStack(TAG).commitAllowingStateLoss();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class OnlineRoutingEngineObject {
|
|
||||||
private String customName;
|
|
||||||
private EngineType type;
|
|
||||||
private String customServerUrl;
|
|
||||||
private VehicleType vehicleType;
|
|
||||||
private String customVehicleKey;
|
|
||||||
private String apiKey;
|
|
||||||
|
|
||||||
public String getVehicleKey() {
|
|
||||||
if (vehicleType == VehicleType.CUSTOM) {
|
|
||||||
return customVehicleKey;
|
|
||||||
}
|
|
||||||
return vehicleType.getKey();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getName(Context ctx) {
|
|
||||||
if (customName != null) {
|
|
||||||
return customName;
|
|
||||||
}
|
|
||||||
return OnlineRoutingEngine.getStandardName(ctx, type, getVehicleKey());
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getBaseUrl() {
|
|
||||||
if (Algorithms.isEmpty(customServerUrl)) {
|
|
||||||
return type.getStandardUrl();
|
|
||||||
}
|
|
||||||
return customServerUrl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
package net.osmand.plus.onlinerouting;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import net.osmand.plus.onlinerouting.engine.EngineType;
|
||||||
|
import net.osmand.plus.onlinerouting.engine.GraphhopperEngine;
|
||||||
|
import net.osmand.plus.onlinerouting.engine.OnlineRoutingEngine;
|
||||||
|
import net.osmand.plus.onlinerouting.engine.OrsEngine;
|
||||||
|
import net.osmand.plus.onlinerouting.engine.OsrmEngine;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class OnlineRoutingFactory {
|
||||||
|
|
||||||
|
public static OnlineRoutingEngine createEngine(@NonNull EngineType type) {
|
||||||
|
return createEngine(type, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public static OnlineRoutingEngine createEngine(@NonNull EngineType type,
|
||||||
|
@Nullable Map<String, String> params) {
|
||||||
|
switch (type) {
|
||||||
|
case GRAPHHOPPER:
|
||||||
|
return new GraphhopperEngine(params);
|
||||||
|
case OSRM:
|
||||||
|
return new OsrmEngine(params);
|
||||||
|
case ORS:
|
||||||
|
return new OrsEngine(params);
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Online routing type {" + type.name() + "} not supported");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
package net.osmand.plus.onlinerouting;
|
package net.osmand.plus.onlinerouting;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.reflect.TypeToken;
|
import com.google.gson.reflect.TypeToken;
|
||||||
|
@ -10,10 +11,10 @@ import net.osmand.data.LatLon;
|
||||||
import net.osmand.osm.io.NetworkUtils;
|
import net.osmand.osm.io.NetworkUtils;
|
||||||
import net.osmand.plus.OsmandApplication;
|
import net.osmand.plus.OsmandApplication;
|
||||||
import net.osmand.plus.Version;
|
import net.osmand.plus.Version;
|
||||||
import net.osmand.plus.onlinerouting.OnlineRoutingEngine.EngineParameter;
|
import net.osmand.plus.onlinerouting.engine.EngineType;
|
||||||
|
import net.osmand.plus.onlinerouting.engine.OnlineRoutingEngine;
|
||||||
import net.osmand.plus.settings.backend.OsmandSettings;
|
import net.osmand.plus.settings.backend.OsmandSettings;
|
||||||
import net.osmand.util.Algorithms;
|
import net.osmand.util.Algorithms;
|
||||||
import net.osmand.util.GeoPolylineParserUtil;
|
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
|
@ -24,7 +25,7 @@ import java.io.BufferedReader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.net.URLConnection;
|
import java.net.HttpURLConnection;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
|
@ -35,14 +36,18 @@ public class OnlineRoutingHelper {
|
||||||
|
|
||||||
private static final Log LOG = PlatformUtil.getLog(OnlineRoutingHelper.class);
|
private static final Log LOG = PlatformUtil.getLog(OnlineRoutingHelper.class);
|
||||||
|
|
||||||
|
private static final String ITEMS = "items";
|
||||||
|
private static final String TYPE = "type";
|
||||||
|
private static final String PARAMS = "params";
|
||||||
|
|
||||||
private OsmandApplication app;
|
private OsmandApplication app;
|
||||||
private OsmandSettings settings;
|
private OsmandSettings settings;
|
||||||
private Map<String, OnlineRoutingEngine> cachedEngines;
|
private Map<String, OnlineRoutingEngine> cachedEngines;
|
||||||
|
|
||||||
public OnlineRoutingHelper(OsmandApplication app) {
|
public OnlineRoutingHelper(@NonNull OsmandApplication app) {
|
||||||
this.app = app;
|
this.app = app;
|
||||||
this.settings = app.getSettings();
|
this.settings = app.getSettings();
|
||||||
loadFromSettings();
|
this.cachedEngines = loadSavedEngines();
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
|
@ -50,104 +55,42 @@ public class OnlineRoutingHelper {
|
||||||
return new ArrayList<>(cachedEngines.values());
|
return new ArrayList<>(cachedEngines.values());
|
||||||
}
|
}
|
||||||
|
|
||||||
public OnlineRoutingEngine getEngineByKey(String stringKey) {
|
@NonNull
|
||||||
|
public List<OnlineRoutingEngine> getEnginesExceptMentioned(@Nullable String ... excludeKeys) {
|
||||||
|
List<OnlineRoutingEngine> engines = getEngines();
|
||||||
|
if (excludeKeys != null) {
|
||||||
|
for (String key : excludeKeys) {
|
||||||
|
OnlineRoutingEngine engine = getEngineByKey(key);
|
||||||
|
engines.remove(engine);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return engines;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public OnlineRoutingEngine getEngineByKey(@Nullable String stringKey) {
|
||||||
return cachedEngines.get(stringKey);
|
return cachedEngines.get(stringKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
public List<LatLon> calculateRouteOnline(@NonNull OnlineRoutingEngine engine,
|
public List<LatLon> calculateRouteOnline(@NonNull OnlineRoutingEngine engine,
|
||||||
@NonNull List<LatLon> path) throws IOException, JSONException {
|
@NonNull List<LatLon> path) throws IOException, JSONException {
|
||||||
String fullUrl = createFullUrl(engine, path);
|
String url = engine.getFullUrl(path);
|
||||||
String content = makeRequest(fullUrl);
|
String content = makeRequest(url);
|
||||||
return parseResponse(engine, content);
|
return engine.parseServerResponse(content);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String createFullUrl(OnlineRoutingEngine engine, List<LatLon> path) {
|
@NonNull
|
||||||
StringBuilder sb = new StringBuilder(engine.getBaseUrl());
|
public String makeRequest(@NonNull String url) throws IOException {
|
||||||
String vehicle = engine.getVehicleKey();
|
HttpURLConnection connection = NetworkUtils.getHttpURLConnection(url);
|
||||||
String apiKey = engine.getParameter(EngineParameter.API_KEY);
|
|
||||||
switch (engine.getType()) {
|
|
||||||
|
|
||||||
case GRAPHHOPPER:
|
|
||||||
sb.append("?");
|
|
||||||
for (LatLon point : path) {
|
|
||||||
sb.append("point=")
|
|
||||||
.append(point.getLatitude())
|
|
||||||
.append(',')
|
|
||||||
.append(point.getLongitude())
|
|
||||||
.append('&');
|
|
||||||
}
|
|
||||||
sb.append("vehicle=").append(vehicle);
|
|
||||||
|
|
||||||
if (!Algorithms.isEmpty(apiKey)) {
|
|
||||||
sb.append('&').append("key=").append(apiKey);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case OSRM:
|
|
||||||
sb.append(vehicle).append('/');
|
|
||||||
for (int i = 0; i < path.size(); i++) {
|
|
||||||
LatLon point = path.get(i);
|
|
||||||
sb.append(point.getLongitude()).append(',').append(point.getLatitude());
|
|
||||||
if (i < path.size() - 1) {
|
|
||||||
sb.append(';');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ORS:
|
|
||||||
if (path.size() > 1) {
|
|
||||||
sb.append("driving-car").append('?'); // todo only for testing
|
|
||||||
if (!Algorithms.isEmpty(apiKey)) {
|
|
||||||
sb.append("api_key=").append(apiKey);
|
|
||||||
}
|
|
||||||
LatLon start = path.get(0);
|
|
||||||
LatLon end = path.get(path.size() - 1);
|
|
||||||
sb.append('&').append("start=")
|
|
||||||
.append(start.getLatitude()).append(',').append(start.getLongitude());
|
|
||||||
sb.append('&').append("end=")
|
|
||||||
.append(end.getLatitude()).append(',').append(end.getLongitude());
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
}
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<LatLon> parseResponse(OnlineRoutingEngine engine, String content) throws JSONException {
|
|
||||||
JSONObject obj = new JSONObject(content);
|
|
||||||
|
|
||||||
switch (engine.getType()) {
|
|
||||||
|
|
||||||
case GRAPHHOPPER:
|
|
||||||
return GeoPolylineParserUtil.parse(
|
|
||||||
obj.getJSONArray("paths").getJSONObject(0).getString("points"),
|
|
||||||
GeoPolylineParserUtil.PRECISION_5);
|
|
||||||
|
|
||||||
case OSRM:
|
|
||||||
return GeoPolylineParserUtil.parse(
|
|
||||||
obj.getJSONArray("routes").getJSONObject(0).getString("geometry"),
|
|
||||||
GeoPolylineParserUtil.PRECISION_5);
|
|
||||||
|
|
||||||
case ORS:
|
|
||||||
JSONArray array = obj.getJSONArray("features").getJSONObject(0)
|
|
||||||
.getJSONObject("geometry").getJSONArray("coordinates");
|
|
||||||
List<LatLon> track = new ArrayList<>();
|
|
||||||
for (int i = 0; i < array.length(); i++) {
|
|
||||||
JSONArray point = array.getJSONArray(i);
|
|
||||||
double lat = Double.parseDouble(point.getString(0));
|
|
||||||
double lon = Double.parseDouble(point.getString(1));
|
|
||||||
track.add(new LatLon(lat, lon));
|
|
||||||
}
|
|
||||||
return track;
|
|
||||||
}
|
|
||||||
return new ArrayList<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
private String makeRequest(String url) throws IOException {
|
|
||||||
URLConnection connection = NetworkUtils.getHttpURLConnection(url);
|
|
||||||
connection.setRequestProperty("User-Agent", Version.getFullVersion(app));
|
connection.setRequestProperty("User-Agent", Version.getFullVersion(app));
|
||||||
StringBuilder content = new StringBuilder();
|
StringBuilder content = new StringBuilder();
|
||||||
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
|
BufferedReader reader;
|
||||||
|
if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
|
||||||
|
reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
|
||||||
|
} else {
|
||||||
|
reader = new BufferedReader(new InputStreamReader(connection.getErrorStream()));
|
||||||
|
}
|
||||||
String s;
|
String s;
|
||||||
while ((s = reader.readLine()) != null) {
|
while ((s = reader.readLine()) != null) {
|
||||||
content.append(s);
|
content.append(s);
|
||||||
|
@ -160,32 +103,49 @@ public class OnlineRoutingHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void saveEngine(@NonNull OnlineRoutingEngine engine) {
|
public void saveEngine(@NonNull OnlineRoutingEngine engine) {
|
||||||
String stringKey = engine.getStringKey();
|
deleteInaccessibleParameters(engine);
|
||||||
cachedEngines.put(stringKey, engine);
|
String key = createEngineKeyIfNeeded(engine);
|
||||||
saveToSettings();
|
cachedEngines.put(key, engine);
|
||||||
}
|
saveCacheToSettings();
|
||||||
|
|
||||||
public void deleteEngine(@NonNull String stringKey) {
|
|
||||||
OnlineRoutingEngine engine = getEngineByKey(stringKey);
|
|
||||||
if (engine != null) {
|
|
||||||
deleteEngine(engine);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void deleteEngine(@NonNull OnlineRoutingEngine engine) {
|
public void deleteEngine(@NonNull OnlineRoutingEngine engine) {
|
||||||
String stringKey = engine.getStringKey();
|
String stringKey = engine.getStringKey();
|
||||||
if (cachedEngines.containsKey(stringKey)) {
|
deleteEngine(stringKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void deleteEngine(@Nullable String stringKey) {
|
||||||
|
if (stringKey != null) {
|
||||||
cachedEngines.remove(stringKey);
|
cachedEngines.remove(stringKey);
|
||||||
saveToSettings();
|
saveCacheToSettings();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadFromSettings() {
|
private void deleteInaccessibleParameters(@NonNull OnlineRoutingEngine engine) {
|
||||||
|
for (EngineParameter key : EngineParameter.values()) {
|
||||||
|
if (!engine.isParameterAllowed(key)) {
|
||||||
|
engine.remove(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
private String createEngineKeyIfNeeded(@NonNull OnlineRoutingEngine engine) {
|
||||||
|
String key = engine.get(EngineParameter.KEY);
|
||||||
|
if (Algorithms.isEmpty(key)) {
|
||||||
|
key = OnlineRoutingEngine.generateKey();
|
||||||
|
engine.put(EngineParameter.KEY, key);
|
||||||
|
}
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
private Map<String, OnlineRoutingEngine> loadSavedEngines() {
|
||||||
Map<String, OnlineRoutingEngine> cachedEngines = new LinkedHashMap<>();
|
Map<String, OnlineRoutingEngine> cachedEngines = new LinkedHashMap<>();
|
||||||
for (OnlineRoutingEngine engine : readFromSettings()) {
|
for (OnlineRoutingEngine engine : readFromSettings()) {
|
||||||
cachedEngines.put(engine.getStringKey(), engine);
|
cachedEngines.put(engine.getStringKey(), engine);
|
||||||
}
|
}
|
||||||
this.cachedEngines = cachedEngines;
|
return cachedEngines;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
|
@ -196,14 +156,14 @@ public class OnlineRoutingHelper {
|
||||||
try {
|
try {
|
||||||
JSONObject json = new JSONObject(jsonString);
|
JSONObject json = new JSONObject(jsonString);
|
||||||
readFromJson(json, engines);
|
readFromJson(json, engines);
|
||||||
} catch (JSONException e) {
|
} catch (JSONException | IllegalArgumentException e) {
|
||||||
LOG.debug("Error when reading engines from JSON ", e);
|
LOG.debug("Error when reading engines from JSON ", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return engines;
|
return engines;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void saveToSettings() {
|
private void saveCacheToSettings() {
|
||||||
if (!Algorithms.isEmpty(cachedEngines)) {
|
if (!Algorithms.isEmpty(cachedEngines)) {
|
||||||
try {
|
try {
|
||||||
JSONObject json = new JSONObject();
|
JSONObject json = new JSONObject();
|
||||||
|
@ -217,38 +177,44 @@ public class OnlineRoutingHelper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void readFromJson(JSONObject json, List<OnlineRoutingEngine> engines) throws JSONException {
|
public static void readFromJson(@NonNull JSONObject json,
|
||||||
|
@NonNull List<OnlineRoutingEngine> engines) throws JSONException {
|
||||||
if (!json.has("items")) {
|
if (!json.has("items")) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Gson gson = new Gson();
|
Gson gson = new Gson();
|
||||||
Type type = new TypeToken<HashMap<String, String>>() {
|
Type typeToken = new TypeToken<HashMap<String, String>>() {
|
||||||
}.getType();
|
}.getType();
|
||||||
JSONArray itemsJson = json.getJSONArray("items");
|
JSONArray itemsJson = json.getJSONArray(ITEMS);
|
||||||
for (int i = 0; i < itemsJson.length(); i++) {
|
for (int i = 0; i < itemsJson.length(); i++) {
|
||||||
JSONObject object = itemsJson.getJSONObject(i);
|
JSONObject object = itemsJson.getJSONObject(i);
|
||||||
String key = object.getString("key");
|
if (object.has(TYPE) && object.has(PARAMS)) {
|
||||||
String vehicleKey = object.getString("vehicle");
|
EngineType type = EngineType.getTypeByName(object.getString(TYPE));
|
||||||
EngineType engineType = EngineType.valueOf(object.getString("type"));
|
String paramsString = object.getString(PARAMS);
|
||||||
String paramsString = object.getString("params");
|
HashMap<String, String> params = gson.fromJson(paramsString, typeToken);
|
||||||
HashMap<String, String> params = gson.fromJson(paramsString, type);
|
OnlineRoutingEngine engine = OnlineRoutingFactory.createEngine(type, params);
|
||||||
engines.add(new OnlineRoutingEngine(key, engineType, vehicleKey, params));
|
if (!Algorithms.isEmpty(engine.getStringKey())) {
|
||||||
|
engines.add(engine);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void writeToJson(JSONObject json, List<OnlineRoutingEngine> engines) throws JSONException {
|
public static void writeToJson(@NonNull JSONObject json,
|
||||||
|
@NonNull List<OnlineRoutingEngine> engines) throws JSONException {
|
||||||
JSONArray jsonArray = new JSONArray();
|
JSONArray jsonArray = new JSONArray();
|
||||||
Gson gson = new Gson();
|
Gson gson = new Gson();
|
||||||
Type type = new TypeToken<HashMap<String, String>>() {
|
Type type = new TypeToken<HashMap<String, String>>() {
|
||||||
}.getType();
|
}.getType();
|
||||||
for (OnlineRoutingEngine engine : engines) {
|
for (OnlineRoutingEngine engine : engines) {
|
||||||
|
if (Algorithms.isEmpty(engine.getStringKey())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
JSONObject jsonObject = new JSONObject();
|
JSONObject jsonObject = new JSONObject();
|
||||||
jsonObject.put("key", engine.getStringKey());
|
jsonObject.put(TYPE, engine.getType().name());
|
||||||
jsonObject.put("type", engine.getType().name());
|
jsonObject.put(PARAMS, gson.toJson(engine.getParams(), type));
|
||||||
jsonObject.put("vehicle", engine.getVehicleKey());
|
|
||||||
jsonObject.put("params", gson.toJson(engine.getParams(), type));
|
|
||||||
jsonArray.put(jsonObject);
|
jsonArray.put(jsonObject);
|
||||||
}
|
}
|
||||||
json.put("items", jsonArray);
|
json.put(ITEMS, jsonArray);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,48 +3,26 @@ package net.osmand.plus.onlinerouting;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.StringRes;
|
||||||
|
|
||||||
import net.osmand.plus.R;
|
public class VehicleType {
|
||||||
import net.osmand.util.Algorithms;
|
private final String key;
|
||||||
|
@StringRes
|
||||||
|
private final int titleId;
|
||||||
|
|
||||||
public enum VehicleType {
|
public VehicleType(@NonNull String key,
|
||||||
CAR("car", R.string.routing_engine_vehicle_type_car),
|
@StringRes int titleId) {
|
||||||
BIKE("bike", R.string.routing_engine_vehicle_type_bike),
|
|
||||||
FOOT("foot", R.string.routing_engine_vehicle_type_foot),
|
|
||||||
DRIVING("driving", R.string.routing_engine_vehicle_type_driving),
|
|
||||||
CUSTOM("", R.string.shared_string_custom);
|
|
||||||
|
|
||||||
VehicleType(String key, int titleId) {
|
|
||||||
this.key = key;
|
this.key = key;
|
||||||
this.titleId = titleId;
|
this.titleId = titleId;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String key;
|
@NonNull
|
||||||
private int titleId;
|
|
||||||
|
|
||||||
public String getKey() {
|
public String getKey() {
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getTitle(Context ctx) {
|
@NonNull
|
||||||
|
public String getTitle(@NonNull Context ctx) {
|
||||||
return ctx.getString(titleId);
|
return ctx.getString(titleId);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
public static String toHumanString(@NonNull Context ctx,
|
|
||||||
@NonNull String key) {
|
|
||||||
VehicleType vehicleType = getVehicleByKey(key);
|
|
||||||
if (vehicleType == CUSTOM) {
|
|
||||||
return Algorithms.capitalizeFirstLetter(key);
|
|
||||||
}
|
|
||||||
return vehicleType.getTitle(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static VehicleType getVehicleByKey(String key) {
|
|
||||||
for (VehicleType v : values()) {
|
|
||||||
if (Algorithms.objectEquals(v.getKey(), key)) {
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return CUSTOM;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
package net.osmand.plus.onlinerouting.engine;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import net.osmand.util.Algorithms;
|
||||||
|
|
||||||
|
public enum EngineType {
|
||||||
|
GRAPHHOPPER("Graphhopper"),
|
||||||
|
OSRM("OSRM"),
|
||||||
|
ORS("Openroute Service");
|
||||||
|
|
||||||
|
private final String title;
|
||||||
|
|
||||||
|
EngineType(String title) {
|
||||||
|
this.title = title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTitle() {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public static EngineType getTypeByName(@Nullable String name) {
|
||||||
|
if (!Algorithms.isEmpty(name)) {
|
||||||
|
for (EngineType type : values()) {
|
||||||
|
if (type.name().equals(name)) {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return values()[0];
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,95 @@
|
||||||
|
package net.osmand.plus.onlinerouting.engine;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import net.osmand.data.LatLon;
|
||||||
|
import net.osmand.plus.R;
|
||||||
|
import net.osmand.plus.onlinerouting.EngineParameter;
|
||||||
|
import net.osmand.plus.onlinerouting.VehicleType;
|
||||||
|
import net.osmand.util.GeoPolylineParserUtil;
|
||||||
|
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static net.osmand.util.Algorithms.isEmpty;
|
||||||
|
|
||||||
|
public class GraphhopperEngine extends OnlineRoutingEngine {
|
||||||
|
|
||||||
|
public GraphhopperEngine(@Nullable Map<String, String> params) {
|
||||||
|
super(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NonNull EngineType getType() {
|
||||||
|
return EngineType.GRAPHHOPPER;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public String getStandardUrl() {
|
||||||
|
return "https://graphhopper.com/api/1/route";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void collectAllowedParameters() {
|
||||||
|
allowParameters(EngineParameter.API_KEY);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void collectAllowedVehicles(@NonNull List<VehicleType> vehicles) {
|
||||||
|
vehicles.add(new VehicleType("car", R.string.routing_engine_vehicle_type_car));
|
||||||
|
vehicles.add(new VehicleType("bike", R.string.routing_engine_vehicle_type_bike));
|
||||||
|
vehicles.add(new VehicleType("foot", R.string.routing_engine_vehicle_type_foot));
|
||||||
|
vehicles.add(new VehicleType("hike", R.string.routing_engine_vehicle_type_hiking));
|
||||||
|
vehicles.add(new VehicleType("mtb", R.string.routing_engine_vehicle_type_mtb));
|
||||||
|
vehicles.add(new VehicleType("racingbike", R.string.routing_engine_vehicle_type_racingbike));
|
||||||
|
vehicles.add(new VehicleType("scooter", R.string.routing_engine_vehicle_type_scooter));
|
||||||
|
vehicles.add(new VehicleType("truck", R.string.routing_engine_vehicle_type_truck));
|
||||||
|
vehicles.add(new VehicleType("small_truck", R.string.routing_engine_vehicle_type_small_truck));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void makeFullUrl(@NonNull StringBuilder sb,
|
||||||
|
@NonNull List<LatLon> path) {
|
||||||
|
sb.append("?");
|
||||||
|
for (LatLon point : path) {
|
||||||
|
sb.append("point=")
|
||||||
|
.append(point.getLatitude())
|
||||||
|
.append(',')
|
||||||
|
.append(point.getLongitude())
|
||||||
|
.append('&');
|
||||||
|
}
|
||||||
|
String vehicle = get(EngineParameter.VEHICLE_KEY);
|
||||||
|
if (isEmpty(vehicle)) {
|
||||||
|
sb.append("vehicle=").append(vehicle);
|
||||||
|
}
|
||||||
|
String apiKey = get(EngineParameter.API_KEY);
|
||||||
|
if (isEmpty(apiKey)) {
|
||||||
|
sb.append('&').append("key=").append(apiKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public List<LatLon> parseServerResponse(@NonNull String content) throws JSONException {
|
||||||
|
JSONObject obj = new JSONObject(content);
|
||||||
|
return GeoPolylineParserUtil.parse(
|
||||||
|
obj.getJSONArray("paths").getJSONObject(0).getString("points"),
|
||||||
|
GeoPolylineParserUtil.PRECISION_5);
|
||||||
|
}
|
||||||
|
|
||||||
|
@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);
|
||||||
|
}
|
||||||
|
return obj.has("paths");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,205 @@
|
||||||
|
package net.osmand.plus.onlinerouting.engine;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import net.osmand.data.LatLon;
|
||||||
|
import net.osmand.plus.R;
|
||||||
|
import net.osmand.plus.onlinerouting.EngineParameter;
|
||||||
|
import net.osmand.plus.onlinerouting.OnlineRoutingFactory;
|
||||||
|
import net.osmand.plus.onlinerouting.VehicleType;
|
||||||
|
import net.osmand.util.Algorithms;
|
||||||
|
|
||||||
|
import org.json.JSONException;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import static net.osmand.util.Algorithms.isEmpty;
|
||||||
|
|
||||||
|
public abstract class OnlineRoutingEngine implements Cloneable {
|
||||||
|
|
||||||
|
public final static String ONLINE_ROUTING_ENGINE_PREFIX = "online_routing_engine_";
|
||||||
|
public static final VehicleType CUSTOM_VEHICLE = new VehicleType("", R.string.shared_string_custom);
|
||||||
|
|
||||||
|
private final Map<String, String> params = new HashMap<>();
|
||||||
|
private final List<VehicleType> allowedVehicles = new ArrayList<>();
|
||||||
|
private final Set<EngineParameter> allowedParameters = new HashSet<>();
|
||||||
|
|
||||||
|
public OnlineRoutingEngine(@Nullable Map<String, String> params) {
|
||||||
|
if (!isEmpty(params)) {
|
||||||
|
this.params.putAll(params);
|
||||||
|
}
|
||||||
|
collectAllowedVehiclesInternal();
|
||||||
|
collectAllowedParametersInternal();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public abstract EngineType getType();
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public String getStringKey() {
|
||||||
|
return get(EngineParameter.KEY);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public String getName(@NonNull Context ctx) {
|
||||||
|
String customName = get(EngineParameter.CUSTOM_NAME);
|
||||||
|
if (customName != null) {
|
||||||
|
return customName;
|
||||||
|
} else {
|
||||||
|
return getStandardName(ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
private String getStandardName(@NonNull Context ctx) {
|
||||||
|
String base = getBaseName(ctx);
|
||||||
|
String index = get(EngineParameter.NAME_INDEX);
|
||||||
|
return !isEmpty(index) ? base + " " + index : base;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public String getBaseName(@NonNull Context ctx) {
|
||||||
|
String vehicleTitle = getSelectedVehicleName(ctx);
|
||||||
|
if (isEmpty(vehicleTitle)) {
|
||||||
|
return getType().getTitle();
|
||||||
|
} else {
|
||||||
|
String pattern = ctx.getString(R.string.ltr_or_rtl_combine_via_dash);
|
||||||
|
return String.format(pattern, getType().getTitle(), vehicleTitle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public String getBaseUrl() {
|
||||||
|
String customUrl = get(EngineParameter.CUSTOM_URL);
|
||||||
|
if (isEmpty(customUrl)) {
|
||||||
|
return getStandardUrl();
|
||||||
|
}
|
||||||
|
return customUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public String getFullUrl(@NonNull List<LatLon> path) {
|
||||||
|
StringBuilder sb = new StringBuilder(getBaseUrl());
|
||||||
|
makeFullUrl(sb, path);
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void makeFullUrl(@NonNull StringBuilder sb,
|
||||||
|
@NonNull List<LatLon> path);
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public abstract List<LatLon> parseServerResponse(@NonNull String content) throws JSONException;
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public abstract String getStandardUrl();
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public Map<String, String> getParams() {
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public String get(@NonNull EngineParameter key) {
|
||||||
|
return params.get(key.name());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void put(@NonNull EngineParameter key, @NonNull String value) {
|
||||||
|
params.put(key.name(), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remove(@NonNull EngineParameter key) {
|
||||||
|
params.remove(key.name());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void collectAllowedVehiclesInternal() {
|
||||||
|
allowedVehicles.clear();
|
||||||
|
collectAllowedVehicles(allowedVehicles);
|
||||||
|
allowedVehicles.add(CUSTOM_VEHICLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void collectAllowedVehicles(@NonNull List<VehicleType> vehicles);
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public List<VehicleType> getAllowedVehicles() {
|
||||||
|
return Collections.unmodifiableList(allowedVehicles);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void collectAllowedParametersInternal() {
|
||||||
|
allowedParameters.clear();
|
||||||
|
allowParameters(EngineParameter.KEY, EngineParameter.VEHICLE_KEY,
|
||||||
|
EngineParameter.CUSTOM_NAME, EngineParameter.NAME_INDEX, EngineParameter.CUSTOM_URL);
|
||||||
|
collectAllowedParameters();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void collectAllowedParameters();
|
||||||
|
|
||||||
|
public boolean isParameterAllowed(EngineParameter key) {
|
||||||
|
return allowedParameters.contains(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void allowParameters(@NonNull EngineParameter ... allowedParams) {
|
||||||
|
allowedParameters.addAll(Arrays.asList(allowedParams));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private String getSelectedVehicleName(@NonNull Context ctx) {
|
||||||
|
String key = get(EngineParameter.VEHICLE_KEY);
|
||||||
|
VehicleType vt = getVehicleTypeByKey(key);
|
||||||
|
if (!vt.equals(CUSTOM_VEHICLE)) {
|
||||||
|
return vt.getTitle(ctx);
|
||||||
|
}
|
||||||
|
return key != null ? Algorithms.capitalizeFirstLetter(key) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public VehicleType getSelectedVehicleType() {
|
||||||
|
String key = get(EngineParameter.VEHICLE_KEY);
|
||||||
|
return getVehicleTypeByKey(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public VehicleType getVehicleTypeByKey(@Nullable String vehicleKey) {
|
||||||
|
if (!isEmpty(vehicleKey)) {
|
||||||
|
for (VehicleType vt : allowedVehicles) {
|
||||||
|
if (Algorithms.objectEquals(vt.getKey(), vehicleKey)) {
|
||||||
|
return vt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return CUSTOM_VEHICLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract boolean parseServerMessage(@NonNull StringBuilder sb,
|
||||||
|
@NonNull String content) throws JSONException;
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public Object clone() {
|
||||||
|
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;
|
||||||
|
if (!(o instanceof OnlineRoutingEngine)) return false;
|
||||||
|
|
||||||
|
OnlineRoutingEngine engine = (OnlineRoutingEngine) o;
|
||||||
|
if (getType() != engine.getType()) return false;
|
||||||
|
return Algorithms.objectEquals(getParams(), engine.getParams());
|
||||||
|
}
|
||||||
|
}
|
104
OsmAnd/src/net/osmand/plus/onlinerouting/engine/OrsEngine.java
Normal file
104
OsmAnd/src/net/osmand/plus/onlinerouting/engine/OrsEngine.java
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
package net.osmand.plus.onlinerouting.engine;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import net.osmand.data.LatLon;
|
||||||
|
import net.osmand.plus.R;
|
||||||
|
import net.osmand.plus.onlinerouting.EngineParameter;
|
||||||
|
import net.osmand.plus.onlinerouting.VehicleType;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
public class OrsEngine extends OnlineRoutingEngine {
|
||||||
|
|
||||||
|
public OrsEngine(@Nullable Map<String, String> params) {
|
||||||
|
super(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NonNull EngineType getType() {
|
||||||
|
return EngineType.ORS;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public String getStandardUrl() {
|
||||||
|
return "https://api.openrouteservice.org/v2/directions/";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void collectAllowedParameters() {
|
||||||
|
allowParameters(EngineParameter.API_KEY);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void collectAllowedVehicles(@NonNull List<VehicleType> vehicles) {
|
||||||
|
vehicles.add(new VehicleType("driving-car", R.string.routing_engine_vehicle_type_car));
|
||||||
|
vehicles.add(new VehicleType("driving-hgv", R.string.routing_engine_vehicle_type_hgv));
|
||||||
|
vehicles.add(new VehicleType("cycling-regular", R.string.routing_engine_vehicle_type_cycling_regular));
|
||||||
|
vehicles.add(new VehicleType("cycling-road", R.string.routing_engine_vehicle_type_cycling_road));
|
||||||
|
vehicles.add(new VehicleType("cycling-mountain", R.string.routing_engine_vehicle_type_cycling_mountain));
|
||||||
|
vehicles.add(new VehicleType("cycling-electric", R.string.routing_engine_vehicle_type_cycling_electric));
|
||||||
|
vehicles.add(new VehicleType("foot-walking", R.string.routing_engine_vehicle_type_walking));
|
||||||
|
vehicles.add(new VehicleType("foot-hiking", R.string.routing_engine_vehicle_type_hiking));
|
||||||
|
vehicles.add(new VehicleType("wheelchair", R.string.routing_engine_vehicle_type_wheelchair));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void makeFullUrl(@NonNull StringBuilder sb,
|
||||||
|
@NonNull List<LatLon> path) {
|
||||||
|
if (path.size() > 1) {
|
||||||
|
String vehicleKey = get(EngineParameter.VEHICLE_KEY);
|
||||||
|
if (!isEmpty(vehicleKey)) {
|
||||||
|
sb.append(vehicleKey);
|
||||||
|
}
|
||||||
|
sb.append('?');
|
||||||
|
String apiKey = get(EngineParameter.API_KEY);
|
||||||
|
if (!isEmpty(apiKey)) {
|
||||||
|
sb.append("api_key=").append(apiKey);
|
||||||
|
}
|
||||||
|
LatLon start = path.get(0);
|
||||||
|
LatLon end = path.get(path.size() - 1);
|
||||||
|
sb.append('&').append("start=")
|
||||||
|
.append(start.getLongitude()).append(',').append(start.getLatitude());
|
||||||
|
sb.append('&').append("end=")
|
||||||
|
.append(end.getLongitude()).append(',').append(end.getLatitude());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public List<LatLon> parseServerResponse(@NonNull String content) throws JSONException {
|
||||||
|
JSONObject obj = new JSONObject(content);
|
||||||
|
JSONArray array = obj.getJSONArray("features").getJSONObject(0)
|
||||||
|
.getJSONObject("geometry").getJSONArray("coordinates");
|
||||||
|
List<LatLon> track = new ArrayList<>();
|
||||||
|
for (int i = 0; i < array.length(); i++) {
|
||||||
|
JSONArray point = array.getJSONArray(i);
|
||||||
|
double lon = Double.parseDouble(point.getString(0));
|
||||||
|
double lat = Double.parseDouble(point.getString(1));
|
||||||
|
track.add(new LatLon(lat, lon));
|
||||||
|
}
|
||||||
|
return track;
|
||||||
|
}
|
||||||
|
|
||||||
|
@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);
|
||||||
|
}
|
||||||
|
return obj.has("features");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,84 @@
|
||||||
|
package net.osmand.plus.onlinerouting.engine;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import net.osmand.data.LatLon;
|
||||||
|
import net.osmand.plus.R;
|
||||||
|
import net.osmand.plus.onlinerouting.EngineParameter;
|
||||||
|
import net.osmand.plus.onlinerouting.VehicleType;
|
||||||
|
import net.osmand.util.GeoPolylineParserUtil;
|
||||||
|
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static net.osmand.util.Algorithms.isEmpty;
|
||||||
|
|
||||||
|
public class OsrmEngine extends OnlineRoutingEngine {
|
||||||
|
|
||||||
|
public OsrmEngine(@Nullable Map<String, String> params) {
|
||||||
|
super(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NonNull EngineType getType() {
|
||||||
|
return EngineType.OSRM;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public String getStandardUrl() {
|
||||||
|
return "https://router.project-osrm.org/route/v1/";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void collectAllowedParameters() { }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void collectAllowedVehicles(@NonNull List<VehicleType> vehicles) {
|
||||||
|
vehicles.add(new VehicleType("car", R.string.routing_engine_vehicle_type_car));
|
||||||
|
vehicles.add(new VehicleType("bike", R.string.routing_engine_vehicle_type_bike));
|
||||||
|
vehicles.add(new VehicleType("foot", R.string.routing_engine_vehicle_type_foot));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void makeFullUrl(@NonNull StringBuilder sb,
|
||||||
|
@NonNull List<LatLon> path) {
|
||||||
|
String vehicleKey = get(EngineParameter.VEHICLE_KEY);
|
||||||
|
if (!isEmpty(vehicleKey)) {
|
||||||
|
sb.append(vehicleKey).append('/');
|
||||||
|
}
|
||||||
|
for (int i = 0; i < path.size(); i++) {
|
||||||
|
LatLon point = path.get(i);
|
||||||
|
sb.append(point.getLongitude()).append(',').append(point.getLatitude());
|
||||||
|
if (i < path.size() - 1) {
|
||||||
|
sb.append(';');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sb.append('?');
|
||||||
|
sb.append("overview=full");
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public List<LatLon> parseServerResponse(@NonNull String content) throws JSONException {
|
||||||
|
JSONObject obj = new JSONObject(content);
|
||||||
|
return GeoPolylineParserUtil.parse(
|
||||||
|
obj.getJSONArray("routes").getJSONObject(0).getString("geometry"),
|
||||||
|
GeoPolylineParserUtil.PRECISION_5);
|
||||||
|
}
|
||||||
|
|
||||||
|
@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);
|
||||||
|
}
|
||||||
|
return obj.has("routes");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
package net.osmand.plus.onlinerouting.ui;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
import net.osmand.data.LatLon;
|
||||||
|
|
||||||
|
public enum ExampleLocation {
|
||||||
|
|
||||||
|
AMSTERDAM("Amsterdam",
|
||||||
|
new LatLon(52.379189, 4.899431),
|
||||||
|
new LatLon(52.308056, 4.764167)),
|
||||||
|
|
||||||
|
BERLIN("Berlin",
|
||||||
|
new LatLon(52.520008, 13.404954),
|
||||||
|
new LatLon(52.3666652, 13.501997992)),
|
||||||
|
|
||||||
|
NEW_YORK("New York",
|
||||||
|
new LatLon(43.000000, -75.000000),
|
||||||
|
new LatLon(40.641766, -73.780968)),
|
||||||
|
|
||||||
|
PARIS("Paris",
|
||||||
|
new LatLon(48.864716, 2.349014),
|
||||||
|
new LatLon(48.948437, 2.434931));
|
||||||
|
|
||||||
|
ExampleLocation(@NonNull String name,
|
||||||
|
@NonNull LatLon cityCenterLatLon,
|
||||||
|
@NonNull LatLon cityAirportLatLon) {
|
||||||
|
this.name = name;
|
||||||
|
this.cityCenterLatLon = cityCenterLatLon;
|
||||||
|
this.cityAirportLatLon = cityAirportLatLon;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
private LatLon cityCenterLatLon;
|
||||||
|
private LatLon cityAirportLatLon;
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public LatLon getCityCenterLatLon() {
|
||||||
|
return cityCenterLatLon;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public LatLon getCityAirportLatLon() {
|
||||||
|
return cityAirportLatLon;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,14 +1,17 @@
|
||||||
package net.osmand.plus.onlinerouting;
|
package net.osmand.plus.onlinerouting.ui;
|
||||||
|
|
||||||
import android.text.Editable;
|
import android.text.Editable;
|
||||||
import android.text.TextWatcher;
|
import android.text.TextWatcher;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.View.OnClickListener;
|
import android.view.View.OnClickListener;
|
||||||
import android.view.View.OnFocusChangeListener;
|
import android.view.View.OnFocusChangeListener;
|
||||||
|
import android.view.ViewGroup;
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.core.content.ContextCompat;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
@ -22,7 +25,10 @@ import net.osmand.plus.helpers.AndroidUiHelper;
|
||||||
import net.osmand.plus.mapcontextmenu.other.HorizontalSelectionAdapter;
|
import net.osmand.plus.mapcontextmenu.other.HorizontalSelectionAdapter;
|
||||||
import net.osmand.plus.mapcontextmenu.other.HorizontalSelectionAdapter.HorizontalSelectionAdapterListener;
|
import net.osmand.plus.mapcontextmenu.other.HorizontalSelectionAdapter.HorizontalSelectionAdapterListener;
|
||||||
import net.osmand.plus.mapcontextmenu.other.HorizontalSelectionAdapter.HorizontalSelectionItem;
|
import net.osmand.plus.mapcontextmenu.other.HorizontalSelectionAdapter.HorizontalSelectionItem;
|
||||||
|
import net.osmand.plus.onlinerouting.VehicleType;
|
||||||
|
import net.osmand.plus.onlinerouting.engine.OnlineRoutingEngine;
|
||||||
import net.osmand.plus.routepreparationmenu.cards.BaseCard;
|
import net.osmand.plus.routepreparationmenu.cards.BaseCard;
|
||||||
|
import net.osmand.plus.settings.backend.ApplicationMode;
|
||||||
import net.osmand.plus.widgets.OsmandTextFieldBoxes;
|
import net.osmand.plus.widgets.OsmandTextFieldBoxes;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -39,13 +45,18 @@ public class OnlineRoutingCard extends BaseCard {
|
||||||
private OsmandTextFieldBoxes textFieldBoxes;
|
private OsmandTextFieldBoxes textFieldBoxes;
|
||||||
private EditText editText;
|
private EditText editText;
|
||||||
private TextView tvHelperText;
|
private TextView tvHelperText;
|
||||||
|
private TextView tvErrorText;
|
||||||
private View bottomDivider;
|
private View bottomDivider;
|
||||||
private View button;
|
private View button;
|
||||||
private OnTextChangedListener onTextChangedListener;
|
private OnTextChangedListener onTextChangedListener;
|
||||||
|
private boolean fieldBoxHelperTextShowed;
|
||||||
|
|
||||||
public OnlineRoutingCard(@NonNull MapActivity mapActivity, boolean nightMode) {
|
private ApplicationMode appMode;
|
||||||
|
|
||||||
|
public OnlineRoutingCard(@NonNull MapActivity mapActivity, boolean nightMode, ApplicationMode appMode) {
|
||||||
super(mapActivity);
|
super(mapActivity);
|
||||||
this.nightMode = nightMode;
|
this.nightMode = nightMode;
|
||||||
|
this.appMode = appMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -64,9 +75,13 @@ public class OnlineRoutingCard extends BaseCard {
|
||||||
textFieldBoxes = view.findViewById(R.id.field_box);
|
textFieldBoxes = view.findViewById(R.id.field_box);
|
||||||
editText = view.findViewById(R.id.edit_text);
|
editText = view.findViewById(R.id.edit_text);
|
||||||
tvHelperText = view.findViewById(R.id.helper_text);
|
tvHelperText = view.findViewById(R.id.helper_text);
|
||||||
|
tvErrorText = view.findViewById(R.id.error_text);
|
||||||
bottomDivider = view.findViewById(R.id.bottom_divider);
|
bottomDivider = view.findViewById(R.id.bottom_divider);
|
||||||
button = view.findViewById(R.id.button);
|
button = view.findViewById(R.id.button);
|
||||||
|
|
||||||
|
int activeColor = ContextCompat.getColor(app, appMode.getIconColorInfo().getColor(nightMode));
|
||||||
|
textFieldBoxes.setPrimaryColor(activeColor);
|
||||||
|
|
||||||
editText.addTextChangedListener(new TextWatcher() {
|
editText.addTextChangedListener(new TextWatcher() {
|
||||||
@Override
|
@Override
|
||||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||||
|
@ -80,7 +95,7 @@ public class OnlineRoutingCard extends BaseCard {
|
||||||
public void afterTextChanged(Editable s) {
|
public void afterTextChanged(Editable s) {
|
||||||
if (onTextChangedListener != null) {
|
if (onTextChangedListener != null) {
|
||||||
boolean editedByUser = editText.getTag() == null;
|
boolean editedByUser = editText.getTag() == null;
|
||||||
String text = editText.getText().toString();
|
String text = editText.getText().toString().trim();
|
||||||
onTextChangedListener.onTextChanged(editedByUser, text);
|
onTextChangedListener.onTextChanged(editedByUser, text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -107,9 +122,9 @@ public class OnlineRoutingCard extends BaseCard {
|
||||||
tvHeaderSubtitle.setText(subtitle);
|
tvHeaderSubtitle.setText(subtitle);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSelectionMenu(List<HorizontalSelectionItem> items,
|
public void setSelectionMenu(@NonNull List<HorizontalSelectionItem> items,
|
||||||
String selectedItemTitle,
|
@NonNull String selectedItemTitle,
|
||||||
final CallbackWithObject<HorizontalSelectionItem> callback) {
|
@NonNull final CallbackWithObject<HorizontalSelectionItem> callback) {
|
||||||
showElements(rvSelectionMenu);
|
showElements(rvSelectionMenu);
|
||||||
rvSelectionMenu.setLayoutManager(
|
rvSelectionMenu.setLayoutManager(
|
||||||
new LinearLayoutManager(app, RecyclerView.HORIZONTAL, false));
|
new LinearLayoutManager(app, RecyclerView.HORIZONTAL, false));
|
||||||
|
@ -122,11 +137,25 @@ public class OnlineRoutingCard extends BaseCard {
|
||||||
if (callback.processResult(item)) {
|
if (callback.processResult(item)) {
|
||||||
adapter.setSelectedItem(item);
|
adapter.setSelectedItem(item);
|
||||||
}
|
}
|
||||||
|
Object obj = item.getObject();
|
||||||
|
updateBottomMarginSelectionMenu(obj);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
Object item = adapter.getItemByTitle(selectedItemTitle).getObject();
|
||||||
|
updateBottomMarginSelectionMenu(item);
|
||||||
rvSelectionMenu.setAdapter(adapter);
|
rvSelectionMenu.setAdapter(adapter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateBottomMarginSelectionMenu(Object item) {
|
||||||
|
if (item instanceof VehicleType) {
|
||||||
|
VehicleType vt = (VehicleType) item;
|
||||||
|
boolean hasPadding = vt.equals(OnlineRoutingEngine.CUSTOM_VEHICLE);
|
||||||
|
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) rvSelectionMenu.getLayoutParams();
|
||||||
|
int contentPadding = app.getResources().getDimensionPixelSize(R.dimen.content_padding);
|
||||||
|
params.bottomMargin = hasPadding ? contentPadding : 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void setDescription(@NonNull String description) {
|
public void setDescription(@NonNull String description) {
|
||||||
showElements(tvDescription);
|
showElements(tvDescription);
|
||||||
tvDescription.setText(description);
|
tvDescription.setText(description);
|
||||||
|
@ -139,15 +168,31 @@ public class OnlineRoutingCard extends BaseCard {
|
||||||
|
|
||||||
public void setFieldBoxHelperText(@NonNull String helperText) {
|
public void setFieldBoxHelperText(@NonNull String helperText) {
|
||||||
showElements(fieldBoxContainer, tvHelperText);
|
showElements(fieldBoxContainer, tvHelperText);
|
||||||
|
fieldBoxHelperTextShowed = true;
|
||||||
tvHelperText.setText(helperText);
|
tvHelperText.setText(helperText);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void showFieldBoxError(@NonNull String errorText) {
|
||||||
|
showElements(fieldBoxContainer, tvErrorText);
|
||||||
|
hideElements(tvHelperText);
|
||||||
|
tvErrorText.setText(errorText);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void hideFieldBoxError() {
|
||||||
|
hideElements(tvErrorText);
|
||||||
|
if (fieldBoxHelperTextShowed) {
|
||||||
|
showElements(tvHelperText);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void setEditedText(@NonNull String text) {
|
public void setEditedText(@NonNull String text) {
|
||||||
editText.setTag(""); // needed to indicate that the text was edited programmatically
|
showElements(fieldBoxContainer);
|
||||||
|
editText.setTag(""); // indicate that the text was edited programmatically
|
||||||
editText.setText(text);
|
editText.setText(text);
|
||||||
editText.setTag(null);
|
editText.setTag(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
public String getEditedText() {
|
public String getEditedText() {
|
||||||
return editText.getText().toString();
|
return editText.getText().toString();
|
||||||
}
|
}
|
||||||
|
@ -156,7 +201,8 @@ public class OnlineRoutingCard extends BaseCard {
|
||||||
showElements(bottomDivider);
|
showElements(bottomDivider);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setButton(String title, OnClickListener listener) {
|
public void setButton(@NonNull String title,
|
||||||
|
@NonNull OnClickListener listener) {
|
||||||
showElements(button);
|
showElements(button);
|
||||||
button.setOnClickListener(listener);
|
button.setOnClickListener(listener);
|
||||||
UiUtilities.setupDialogButton(nightMode, button, DialogButtonType.PRIMARY, title);
|
UiUtilities.setupDialogButton(nightMode, button, DialogButtonType.PRIMARY, title);
|
||||||
|
@ -186,11 +232,11 @@ public class OnlineRoutingCard extends BaseCard {
|
||||||
AndroidUiHelper.setVisibility(View.GONE, views);
|
AndroidUiHelper.setVisibility(View.GONE, views);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setOnTextChangedListener(OnTextChangedListener onTextChangedListener) {
|
public void setOnTextChangedListener(@Nullable OnTextChangedListener onTextChangedListener) {
|
||||||
this.onTextChangedListener = onTextChangedListener;
|
this.onTextChangedListener = onTextChangedListener;
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface OnTextChangedListener {
|
public interface OnTextChangedListener {
|
||||||
void onTextChanged(boolean editedByUser, String text);
|
void onTextChanged(boolean editedByUser, @NonNull String text);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,721 @@
|
||||||
|
package net.osmand.plus.onlinerouting.ui;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.DialogInterface;
|
||||||
|
import android.graphics.Rect;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.MotionEvent;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.View.OnClickListener;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.view.ViewTreeObserver;
|
||||||
|
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
|
||||||
|
import android.widget.FrameLayout;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.ScrollView;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.activity.OnBackPressedCallback;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.appcompat.app.AlertDialog;
|
||||||
|
import androidx.appcompat.widget.Toolbar;
|
||||||
|
import androidx.fragment.app.FragmentActivity;
|
||||||
|
import androidx.fragment.app.FragmentManager;
|
||||||
|
|
||||||
|
import net.osmand.AndroidUtils;
|
||||||
|
import net.osmand.CallbackWithObject;
|
||||||
|
import net.osmand.data.LatLon;
|
||||||
|
import net.osmand.plus.OsmandApplication;
|
||||||
|
import net.osmand.plus.R;
|
||||||
|
import net.osmand.plus.UiUtilities;
|
||||||
|
import net.osmand.plus.UiUtilities.DialogButtonType;
|
||||||
|
import net.osmand.plus.activities.MapActivity;
|
||||||
|
import net.osmand.plus.base.BaseOsmAndFragment;
|
||||||
|
import net.osmand.plus.mapcontextmenu.other.HorizontalSelectionAdapter.HorizontalSelectionItem;
|
||||||
|
import net.osmand.plus.onlinerouting.EngineParameter;
|
||||||
|
import net.osmand.plus.onlinerouting.OnlineRoutingFactory;
|
||||||
|
import net.osmand.plus.onlinerouting.OnlineRoutingHelper;
|
||||||
|
import net.osmand.plus.onlinerouting.VehicleType;
|
||||||
|
import net.osmand.plus.onlinerouting.ui.OnlineRoutingCard.OnTextChangedListener;
|
||||||
|
import net.osmand.plus.onlinerouting.engine.EngineType;
|
||||||
|
import net.osmand.plus.onlinerouting.engine.OnlineRoutingEngine;
|
||||||
|
import net.osmand.plus.routepreparationmenu.cards.BaseCard;
|
||||||
|
import net.osmand.plus.settings.backend.ApplicationMode;
|
||||||
|
import net.osmand.util.Algorithms;
|
||||||
|
|
||||||
|
import org.json.JSONException;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static net.osmand.plus.onlinerouting.engine.OnlineRoutingEngine.CUSTOM_VEHICLE;
|
||||||
|
|
||||||
|
public class OnlineRoutingEngineFragment extends BaseOsmAndFragment {
|
||||||
|
|
||||||
|
public static final String TAG = OnlineRoutingEngineFragment.class.getSimpleName();
|
||||||
|
|
||||||
|
private static final String ENGINE_TYPE_KEY = "engine_type";
|
||||||
|
private static final String ENGINE_CUSTOM_VEHICLE_KEY = "engine_custom_vehicle";
|
||||||
|
private static final String EXAMPLE_LOCATION_KEY = "example_location";
|
||||||
|
private static final String APP_MODE_KEY = "app_mode";
|
||||||
|
private static final String EDITED_ENGINE_KEY = "edited_engine_key";
|
||||||
|
|
||||||
|
private OsmandApplication app;
|
||||||
|
private ApplicationMode appMode;
|
||||||
|
private MapActivity mapActivity;
|
||||||
|
private OnlineRoutingHelper helper;
|
||||||
|
|
||||||
|
private View view;
|
||||||
|
private ViewGroup segmentsContainer;
|
||||||
|
private OnlineRoutingCard nameCard;
|
||||||
|
private OnlineRoutingCard typeCard;
|
||||||
|
private OnlineRoutingCard vehicleCard;
|
||||||
|
private OnlineRoutingCard apiKeyCard;
|
||||||
|
private OnlineRoutingCard exampleCard;
|
||||||
|
private View testResultsContainer;
|
||||||
|
private View saveButton;
|
||||||
|
private ScrollView scrollView;
|
||||||
|
private OnGlobalLayoutListener onGlobalLayout;
|
||||||
|
private boolean isKeyboardShown = false;
|
||||||
|
|
||||||
|
private OnlineRoutingEngine engine;
|
||||||
|
private OnlineRoutingEngine initEngine;
|
||||||
|
private String customVehicleKey;
|
||||||
|
private ExampleLocation selectedLocation;
|
||||||
|
private String editedEngineKey;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
app = requireMyApplication();
|
||||||
|
mapActivity = getMapActivity();
|
||||||
|
helper = app.getOnlineRoutingHelper();
|
||||||
|
if (savedInstanceState != null) {
|
||||||
|
restoreState(savedInstanceState);
|
||||||
|
} else {
|
||||||
|
initState();
|
||||||
|
}
|
||||||
|
requireMyActivity().getOnBackPressedDispatcher().addCallback(this, new OnBackPressedCallback(true) {
|
||||||
|
public void handleOnBackPressed() {
|
||||||
|
MapActivity mapActivity = getMapActivity();
|
||||||
|
if (mapActivity != null) {
|
||||||
|
showExitDialog();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("ClickableViewAccessibility")
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public View onCreateView(@NonNull LayoutInflater inflater,
|
||||||
|
@Nullable ViewGroup container,
|
||||||
|
@Nullable Bundle savedInstanceState) {
|
||||||
|
view = getInflater().inflate(
|
||||||
|
R.layout.online_routing_engine_fragment, container, false);
|
||||||
|
segmentsContainer = (ViewGroup) view.findViewById(R.id.segments_container);
|
||||||
|
scrollView = (ScrollView) segmentsContainer.getParent();
|
||||||
|
if (Build.VERSION.SDK_INT >= 21) {
|
||||||
|
AndroidUtils.addStatusBarPadding21v(getContext(), view);
|
||||||
|
}
|
||||||
|
setupToolbar((Toolbar) view.findViewById(R.id.toolbar));
|
||||||
|
|
||||||
|
setupNameCard();
|
||||||
|
setupTypeCard();
|
||||||
|
setupVehicleCard();
|
||||||
|
setupApiKeyCard();
|
||||||
|
setupExampleCard();
|
||||||
|
setupResultsContainer();
|
||||||
|
setupButtons();
|
||||||
|
|
||||||
|
generateUniqueNameIfNeeded();
|
||||||
|
updateCardViews(nameCard, typeCard, vehicleCard, exampleCard);
|
||||||
|
|
||||||
|
scrollView.setOnTouchListener(new View.OnTouchListener() {
|
||||||
|
int scrollViewY = 0;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onTouch(View v, MotionEvent event) {
|
||||||
|
int y = scrollView.getScrollY();
|
||||||
|
if (isKeyboardShown && scrollViewY != y) {
|
||||||
|
scrollViewY = y;
|
||||||
|
View focus = mapActivity.getCurrentFocus();
|
||||||
|
if (focus != null) {
|
||||||
|
AndroidUtils.hideSoftKeyboard(mapActivity, focus);
|
||||||
|
focus.clearFocus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
onGlobalLayout = new ViewTreeObserver.OnGlobalLayoutListener() {
|
||||||
|
private int layoutHeightPrevious;
|
||||||
|
private int layoutHeightMin;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onGlobalLayout() {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
|
||||||
|
view.getViewTreeObserver().removeOnGlobalLayoutListener(this);
|
||||||
|
} else {
|
||||||
|
view.getViewTreeObserver().removeGlobalOnLayoutListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
Rect visibleDisplayFrame = new Rect();
|
||||||
|
view.getWindowVisibleDisplayFrame(visibleDisplayFrame);
|
||||||
|
int layoutHeight = visibleDisplayFrame.bottom;
|
||||||
|
|
||||||
|
if (layoutHeight < layoutHeightPrevious) {
|
||||||
|
isKeyboardShown = true;
|
||||||
|
layoutHeightMin = layoutHeight;
|
||||||
|
} else {
|
||||||
|
isKeyboardShown = layoutHeight == layoutHeightMin;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (layoutHeight != layoutHeightPrevious) {
|
||||||
|
FrameLayout.LayoutParams rootViewLayout = (FrameLayout.LayoutParams) view.getLayoutParams();
|
||||||
|
rootViewLayout.height = layoutHeight;
|
||||||
|
view.requestLayout();
|
||||||
|
layoutHeightPrevious = layoutHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
view.post(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
view.getViewTreeObserver().addOnGlobalLayoutListener(onGlobalLayout);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
|
||||||
|
view.getViewTreeObserver().addOnGlobalLayoutListener(onGlobalLayout);
|
||||||
|
}
|
||||||
|
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupToolbar(Toolbar toolbar) {
|
||||||
|
ImageView navigationIcon = toolbar.findViewById(R.id.close_button);
|
||||||
|
navigationIcon.setImageResource(R.drawable.ic_action_close);
|
||||||
|
navigationIcon.setOnClickListener(new OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
showExitDialog();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
TextView title = toolbar.findViewById(R.id.toolbar_title);
|
||||||
|
toolbar.findViewById(R.id.toolbar_subtitle).setVisibility(View.GONE);
|
||||||
|
View actionBtn = toolbar.findViewById(R.id.action_button);
|
||||||
|
if (isEditingMode()) {
|
||||||
|
title.setText(getString(R.string.edit_online_routing_engine));
|
||||||
|
ImageView ivBtn = toolbar.findViewById(R.id.action_button_icon);
|
||||||
|
ivBtn.setImageDrawable(
|
||||||
|
getIcon(R.drawable.ic_action_delete_dark, R.color.color_osm_edit_delete));
|
||||||
|
actionBtn.setOnClickListener(new OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
onDeleteEngine();
|
||||||
|
dismiss();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
title.setText(getString(R.string.add_online_routing_engine));
|
||||||
|
actionBtn.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupNameCard() {
|
||||||
|
nameCard = new OnlineRoutingCard(mapActivity, isNightMode(), appMode);
|
||||||
|
nameCard.build(mapActivity);
|
||||||
|
nameCard.setDescription(getString(R.string.select_nav_profile_dialog_message));
|
||||||
|
nameCard.setEditedText(engine.getName(app));
|
||||||
|
nameCard.setFieldBoxLabelText(getString(R.string.shared_string_name));
|
||||||
|
nameCard.setOnTextChangedListener(new OnTextChangedListener() {
|
||||||
|
@Override
|
||||||
|
public void onTextChanged(boolean changedByUser, @NonNull String text) {
|
||||||
|
if (changedByUser) {
|
||||||
|
engine.put(EngineParameter.CUSTOM_NAME, text);
|
||||||
|
checkCustomNameUnique(engine);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
nameCard.showDivider();
|
||||||
|
segmentsContainer.addView(nameCard.getView());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupTypeCard() {
|
||||||
|
typeCard = new OnlineRoutingCard(mapActivity, isNightMode(), appMode);
|
||||||
|
typeCard.build(mapActivity);
|
||||||
|
typeCard.setHeaderTitle(getString(R.string.shared_string_type));
|
||||||
|
List<HorizontalSelectionItem> serverItems = new ArrayList<>();
|
||||||
|
for (EngineType server : EngineType.values()) {
|
||||||
|
serverItems.add(new HorizontalSelectionItem(server.getTitle(), server));
|
||||||
|
}
|
||||||
|
typeCard.setSelectionMenu(serverItems, engine.getType().getTitle(),
|
||||||
|
new CallbackWithObject<HorizontalSelectionItem>() {
|
||||||
|
@Override
|
||||||
|
public boolean processResult(HorizontalSelectionItem result) {
|
||||||
|
EngineType type = (EngineType) result.getObject();
|
||||||
|
if (engine.getType() != type) {
|
||||||
|
changeEngineType(type);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
typeCard.setOnTextChangedListener(new OnTextChangedListener() {
|
||||||
|
@Override
|
||||||
|
public void onTextChanged(boolean editedByUser, @NonNull String text) {
|
||||||
|
if (editedByUser) {
|
||||||
|
engine.put(EngineParameter.CUSTOM_URL, text);
|
||||||
|
updateCardViews(exampleCard);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
typeCard.setFieldBoxLabelText(getString(R.string.shared_string_server_url));
|
||||||
|
typeCard.showDivider();
|
||||||
|
segmentsContainer.addView(typeCard.getView());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupVehicleCard() {
|
||||||
|
vehicleCard = new OnlineRoutingCard(mapActivity, isNightMode(), appMode);
|
||||||
|
vehicleCard.build(mapActivity);
|
||||||
|
vehicleCard.setHeaderTitle(getString(R.string.shared_string_vehicle));
|
||||||
|
vehicleCard.setFieldBoxLabelText(getString(R.string.shared_string_custom));
|
||||||
|
vehicleCard.setOnTextChangedListener(new OnTextChangedListener() {
|
||||||
|
@Override
|
||||||
|
public void onTextChanged(boolean editedByUser, @NonNull String text) {
|
||||||
|
if (editedByUser) {
|
||||||
|
customVehicleKey = text;
|
||||||
|
engine.put(EngineParameter.VEHICLE_KEY, customVehicleKey);
|
||||||
|
updateCardViews(nameCard, exampleCard);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
vehicleCard.setEditedText(customVehicleKey);
|
||||||
|
vehicleCard.setFieldBoxHelperText(getString(R.string.shared_string_enter_param));
|
||||||
|
vehicleCard.showDivider();
|
||||||
|
segmentsContainer.addView(vehicleCard.getView());
|
||||||
|
setupVehicleTypes();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupVehicleTypes() {
|
||||||
|
List<HorizontalSelectionItem> vehicleItems = new ArrayList<>();
|
||||||
|
for (VehicleType vehicle : engine.getAllowedVehicles()) {
|
||||||
|
vehicleItems.add(new HorizontalSelectionItem(vehicle.getTitle(app), vehicle));
|
||||||
|
}
|
||||||
|
vehicleCard.setSelectionMenu(vehicleItems, engine.getSelectedVehicleType().getTitle(app),
|
||||||
|
new CallbackWithObject<HorizontalSelectionItem>() {
|
||||||
|
@Override
|
||||||
|
public boolean processResult(HorizontalSelectionItem result) {
|
||||||
|
VehicleType vehicle = (VehicleType) result.getObject();
|
||||||
|
if (!Algorithms.objectEquals(engine.getSelectedVehicleType(), vehicle)) {
|
||||||
|
String vehicleKey = vehicle.equals(CUSTOM_VEHICLE) ? customVehicleKey : vehicle.getKey();
|
||||||
|
engine.put(EngineParameter.VEHICLE_KEY, vehicleKey);
|
||||||
|
generateUniqueNameIfNeeded();
|
||||||
|
updateCardViews(nameCard, vehicleCard, exampleCard);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupApiKeyCard() {
|
||||||
|
apiKeyCard = new OnlineRoutingCard(mapActivity, isNightMode(), appMode);
|
||||||
|
apiKeyCard.build(mapActivity);
|
||||||
|
apiKeyCard.setHeaderTitle(getString(R.string.shared_string_api_key));
|
||||||
|
apiKeyCard.setFieldBoxLabelText(getString(R.string.keep_it_empty_if_not));
|
||||||
|
String apiKey = engine.get(EngineParameter.API_KEY);
|
||||||
|
if (apiKey != null) {
|
||||||
|
apiKeyCard.setEditedText(apiKey);
|
||||||
|
}
|
||||||
|
apiKeyCard.showDivider();
|
||||||
|
apiKeyCard.setOnTextChangedListener(new OnTextChangedListener() {
|
||||||
|
@Override
|
||||||
|
public void onTextChanged(boolean editedByUser, @NonNull String text) {
|
||||||
|
if (Algorithms.isBlank(text)) {
|
||||||
|
engine.remove(EngineParameter.API_KEY);
|
||||||
|
} else {
|
||||||
|
engine.put(EngineParameter.API_KEY, text);
|
||||||
|
}
|
||||||
|
updateCardViews(exampleCard);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
segmentsContainer.addView(apiKeyCard.getView());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupExampleCard() {
|
||||||
|
exampleCard = new OnlineRoutingCard(mapActivity, isNightMode(), appMode);
|
||||||
|
exampleCard.build(mapActivity);
|
||||||
|
exampleCard.setHeaderTitle(getString(R.string.shared_string_example));
|
||||||
|
List<HorizontalSelectionItem> locationItems = new ArrayList<>();
|
||||||
|
for (ExampleLocation location : ExampleLocation.values()) {
|
||||||
|
locationItems.add(new HorizontalSelectionItem(location.getName(), location));
|
||||||
|
}
|
||||||
|
exampleCard.setSelectionMenu(locationItems, selectedLocation.getName(),
|
||||||
|
new CallbackWithObject<HorizontalSelectionItem>() {
|
||||||
|
@Override
|
||||||
|
public boolean processResult(HorizontalSelectionItem result) {
|
||||||
|
ExampleLocation location = (ExampleLocation) result.getObject();
|
||||||
|
if (selectedLocation != location) {
|
||||||
|
selectedLocation = location;
|
||||||
|
updateCardViews(exampleCard);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
exampleCard.setDescription(getString(R.string.online_routing_example_hint));
|
||||||
|
exampleCard.showFieldBox();
|
||||||
|
exampleCard.setButton(getString(R.string.test_route_calculation), new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
testEngineWork();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
segmentsContainer.addView(exampleCard.getView());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupResultsContainer() {
|
||||||
|
testResultsContainer = getInflater().inflate(
|
||||||
|
R.layout.bottom_sheet_item_with_descr_64dp, segmentsContainer, false);
|
||||||
|
testResultsContainer.setVisibility(View.INVISIBLE);
|
||||||
|
segmentsContainer.addView(testResultsContainer);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupButtons() {
|
||||||
|
boolean nightMode = isNightMode();
|
||||||
|
View cancelButton = view.findViewById(R.id.dismiss_button);
|
||||||
|
UiUtilities.setupDialogButton(nightMode, cancelButton,
|
||||||
|
DialogButtonType.SECONDARY, R.string.shared_string_cancel);
|
||||||
|
cancelButton.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
showExitDialog();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
view.findViewById(R.id.buttons_divider).setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
|
saveButton = view.findViewById(R.id.right_bottom_button);
|
||||||
|
UiUtilities.setupDialogButton(nightMode, saveButton,
|
||||||
|
UiUtilities.DialogButtonType.PRIMARY, R.string.shared_string_save);
|
||||||
|
saveButton.setVisibility(View.VISIBLE);
|
||||||
|
saveButton.setOnClickListener(new OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
onSaveEngine();
|
||||||
|
dismiss();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void changeEngineType(EngineType type) {
|
||||||
|
OnlineRoutingEngine tmp = (OnlineRoutingEngine) engine.clone();
|
||||||
|
engine = OnlineRoutingFactory.createEngine(type, tmp.getParams());
|
||||||
|
|
||||||
|
// after changing the type, select the vehicle
|
||||||
|
// with the same name that was selected before
|
||||||
|
VehicleType previous = tmp.getSelectedVehicleType();
|
||||||
|
VehicleType next = null;
|
||||||
|
for (VehicleType vt : engine.getAllowedVehicles()) {
|
||||||
|
if (Algorithms.objectEquals(previous.getTitle(app), vt.getTitle(app))) {
|
||||||
|
next = vt;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String vehicleKey;
|
||||||
|
if (next != null) {
|
||||||
|
vehicleKey = next.equals(CUSTOM_VEHICLE) ? customVehicleKey : next.getKey();
|
||||||
|
} else {
|
||||||
|
vehicleKey = engine.getAllowedVehicles().get(0).getKey();
|
||||||
|
}
|
||||||
|
engine.put(EngineParameter.VEHICLE_KEY, vehicleKey);
|
||||||
|
|
||||||
|
setupVehicleTypes();
|
||||||
|
generateUniqueNameIfNeeded();
|
||||||
|
updateCardViews(nameCard, typeCard, vehicleCard, exampleCard);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void generateUniqueNameIfNeeded() {
|
||||||
|
if (engine.get(EngineParameter.CUSTOM_NAME) == null) {
|
||||||
|
engine.remove(EngineParameter.NAME_INDEX);
|
||||||
|
if (hasNameDuplicate(engine.getName(app))) {
|
||||||
|
int index = 0;
|
||||||
|
do {
|
||||||
|
engine.put(EngineParameter.NAME_INDEX, String.valueOf(++index));
|
||||||
|
} while (hasNameDuplicate(engine.getName(app)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkCustomNameUnique(@NonNull OnlineRoutingEngine engine) {
|
||||||
|
if (hasNameDuplicate(engine.getName(app))) {
|
||||||
|
nameCard.showFieldBoxError(getString(R.string.message_name_is_already_exists));
|
||||||
|
saveButton.setEnabled(false);
|
||||||
|
} else {
|
||||||
|
nameCard.hideFieldBoxError();
|
||||||
|
saveButton.setEnabled(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasNameDuplicate(@NonNull String name) {
|
||||||
|
for (OnlineRoutingEngine engine : helper.getEnginesExceptMentioned(editedEngineKey)) {
|
||||||
|
if (Algorithms.objectEquals(engine.getName(app), name)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onSaveEngine() {
|
||||||
|
if (engine != null) {
|
||||||
|
helper.saveEngine(engine);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onDeleteEngine() {
|
||||||
|
helper.deleteEngine(engine);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isEditingMode() {
|
||||||
|
return editedEngineKey != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getTestUrl() {
|
||||||
|
List<LatLon> path = new ArrayList<>();
|
||||||
|
path.add(selectedLocation.getCityCenterLatLon());
|
||||||
|
path.add(selectedLocation.getCityAirportLatLon());
|
||||||
|
return engine.getFullUrl(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void testEngineWork() {
|
||||||
|
final OnlineRoutingEngine requestedEngine = (OnlineRoutingEngine) engine.clone();
|
||||||
|
final ExampleLocation location = selectedLocation;
|
||||||
|
new Thread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
StringBuilder message = new StringBuilder();
|
||||||
|
boolean resultOk = false;
|
||||||
|
try {
|
||||||
|
String response = helper.makeRequest(exampleCard.getEditedText());
|
||||||
|
resultOk = requestedEngine.parseServerMessage(message, response);
|
||||||
|
} catch (IOException | JSONException e) {
|
||||||
|
message.append(e.toString());
|
||||||
|
}
|
||||||
|
showTestResults(resultOk, message.toString(), location);
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showTestResults(final boolean resultOk,
|
||||||
|
final @NonNull String message,
|
||||||
|
final @NonNull ExampleLocation location) {
|
||||||
|
app.runInUIThread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
testResultsContainer.setVisibility(View.VISIBLE);
|
||||||
|
ImageView ivImage = testResultsContainer.findViewById(R.id.icon);
|
||||||
|
TextView tvTitle = testResultsContainer.findViewById(R.id.title);
|
||||||
|
TextView tvDescription = testResultsContainer.findViewById(R.id.description);
|
||||||
|
if (resultOk) {
|
||||||
|
ivImage.setImageDrawable(getContentIcon(R.drawable.ic_action_gdirections_dark));
|
||||||
|
tvTitle.setText(getString(R.string.shared_string_ok));
|
||||||
|
} else {
|
||||||
|
ivImage.setImageDrawable(getContentIcon(R.drawable.ic_action_alert));
|
||||||
|
tvTitle.setText(String.format(getString(R.string.message_server_error), message));
|
||||||
|
}
|
||||||
|
tvDescription.setText(location.getName());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateCardViews(@NonNull BaseCard... cardsToUpdate) {
|
||||||
|
for (BaseCard card : cardsToUpdate) {
|
||||||
|
if (nameCard.equals(card)) {
|
||||||
|
if (Algorithms.isEmpty(engine.get(EngineParameter.CUSTOM_NAME))) {
|
||||||
|
nameCard.setEditedText(engine.getName(app));
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (typeCard.equals(card)) {
|
||||||
|
typeCard.setHeaderSubtitle(engine.getType().getTitle());
|
||||||
|
typeCard.setEditedText(engine.getBaseUrl());
|
||||||
|
if (engine.isParameterAllowed(EngineParameter.API_KEY)) {
|
||||||
|
apiKeyCard.show();
|
||||||
|
} else {
|
||||||
|
apiKeyCard.hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (vehicleCard.equals(card)) {
|
||||||
|
VehicleType vt = engine.getSelectedVehicleType();
|
||||||
|
vehicleCard.setHeaderSubtitle(vt.getTitle(app));
|
||||||
|
if (vt.equals(CUSTOM_VEHICLE)) {
|
||||||
|
vehicleCard.showFieldBox();
|
||||||
|
vehicleCard.setEditedText(customVehicleKey);
|
||||||
|
} else {
|
||||||
|
vehicleCard.hideFieldBox();
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (exampleCard.equals(card)) {
|
||||||
|
exampleCard.setEditedText(getTestUrl());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void showExitDialog() {
|
||||||
|
View focus = view.findFocus();
|
||||||
|
AndroidUtils.hideSoftKeyboard(mapActivity, focus);
|
||||||
|
if (!engine.equals(initEngine)) {
|
||||||
|
AlertDialog.Builder dismissDialog = createWarningDialog(mapActivity,
|
||||||
|
R.string.shared_string_dismiss, R.string.exit_without_saving, R.string.shared_string_cancel);
|
||||||
|
dismissDialog.setPositiveButton(R.string.shared_string_exit, new DialogInterface.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
|
dismiss();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
dismissDialog.show();
|
||||||
|
} else {
|
||||||
|
dismiss();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private AlertDialog.Builder createWarningDialog(Activity activity, int title, int message, int negButton) {
|
||||||
|
Context themedContext = UiUtilities.getThemedContext(activity, isNightMode());
|
||||||
|
AlertDialog.Builder warningDialog = new AlertDialog.Builder(themedContext);
|
||||||
|
warningDialog.setTitle(getString(title));
|
||||||
|
warningDialog.setMessage(getString(message));
|
||||||
|
warningDialog.setNegativeButton(negButton, null);
|
||||||
|
return warningDialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void dismiss() {
|
||||||
|
FragmentActivity activity = getActivity();
|
||||||
|
if (activity != null) {
|
||||||
|
FragmentManager fragmentManager = activity.getSupportFragmentManager();
|
||||||
|
if (!fragmentManager.isStateSaved()) {
|
||||||
|
fragmentManager.popBackStack();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isNightMode() {
|
||||||
|
return !app.getSettings().isLightContentForMode(getAppMode());
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
private ApplicationMode getAppMode() {
|
||||||
|
return appMode != null ? appMode : app.getSettings().getApplicationMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private MapActivity getMapActivity() {
|
||||||
|
FragmentActivity activity = getActivity();
|
||||||
|
if (activity instanceof MapActivity) {
|
||||||
|
return (MapActivity) activity;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private LayoutInflater getInflater() {
|
||||||
|
return UiUtilities.getInflater(mapActivity, isNightMode());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroyView() {
|
||||||
|
super.onDestroyView();
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
|
||||||
|
view.getViewTreeObserver().removeOnGlobalLayoutListener(onGlobalLayout);
|
||||||
|
} else {
|
||||||
|
view.getViewTreeObserver().removeGlobalOnLayoutListener(onGlobalLayout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSaveInstanceState(@NonNull Bundle outState) {
|
||||||
|
super.onSaveInstanceState(outState);
|
||||||
|
saveState(outState);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void saveState(@NonNull Bundle outState) {
|
||||||
|
outState.putString(ENGINE_TYPE_KEY, engine.getType().name());
|
||||||
|
for (EngineParameter key : EngineParameter.values()) {
|
||||||
|
String value = engine.get(key);
|
||||||
|
if (value != null) {
|
||||||
|
outState.putString(key.name(), value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
outState.putString(ENGINE_CUSTOM_VEHICLE_KEY, customVehicleKey);
|
||||||
|
outState.putString(EXAMPLE_LOCATION_KEY, selectedLocation.name());
|
||||||
|
outState.putString(APP_MODE_KEY, getAppMode().getStringKey());
|
||||||
|
outState.putString(EDITED_ENGINE_KEY, editedEngineKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void restoreState(@NonNull Bundle savedState) {
|
||||||
|
editedEngineKey = savedState.getString(EngineParameter.KEY.name());
|
||||||
|
initEngine = createInitStateEngine();
|
||||||
|
String typeKey = savedState.getString(ENGINE_TYPE_KEY);
|
||||||
|
EngineType type = EngineType.getTypeByName(typeKey);
|
||||||
|
engine = OnlineRoutingFactory.createEngine(type);
|
||||||
|
for (EngineParameter key : EngineParameter.values()) {
|
||||||
|
String value = savedState.getString(key.name());
|
||||||
|
if (value != null) {
|
||||||
|
engine.put(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
customVehicleKey = savedState.getString(ENGINE_CUSTOM_VEHICLE_KEY);
|
||||||
|
selectedLocation = ExampleLocation.valueOf(savedState.getString(EXAMPLE_LOCATION_KEY));
|
||||||
|
appMode = ApplicationMode.valueOfStringKey(savedState.getString(APP_MODE_KEY), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initState() {
|
||||||
|
initEngine = createInitStateEngine();
|
||||||
|
selectedLocation = ExampleLocation.values()[0];
|
||||||
|
engine = (OnlineRoutingEngine) initEngine.clone();
|
||||||
|
if (Algorithms.objectEquals(engine.getSelectedVehicleType(), CUSTOM_VEHICLE)) {
|
||||||
|
customVehicleKey = engine.get(EngineParameter.VEHICLE_KEY);
|
||||||
|
} else {
|
||||||
|
customVehicleKey = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private OnlineRoutingEngine createInitStateEngine() {
|
||||||
|
OnlineRoutingEngine engine;
|
||||||
|
OnlineRoutingEngine editedEngine = helper.getEngineByKey(editedEngineKey);
|
||||||
|
if (editedEngine != null) {
|
||||||
|
engine = (OnlineRoutingEngine) editedEngine.clone();
|
||||||
|
} else {
|
||||||
|
engine = OnlineRoutingFactory.createEngine(EngineType.values()[0]);
|
||||||
|
String vehicle = engine.getAllowedVehicles().get(0).getKey();
|
||||||
|
engine.put(EngineParameter.VEHICLE_KEY, vehicle);
|
||||||
|
if (editedEngineKey != null) {
|
||||||
|
engine.put(EngineParameter.KEY, editedEngineKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return engine;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void showInstance(@NonNull FragmentActivity activity,
|
||||||
|
@NonNull ApplicationMode appMode,
|
||||||
|
@Nullable String editedEngineKey) {
|
||||||
|
FragmentManager fm = activity.getSupportFragmentManager();
|
||||||
|
if (!fm.isStateSaved() && fm.findFragmentByTag(OnlineRoutingEngineFragment.TAG) == null) {
|
||||||
|
OnlineRoutingEngineFragment fragment = new OnlineRoutingEngineFragment();
|
||||||
|
fragment.appMode = appMode;
|
||||||
|
fragment.editedEngineKey = editedEngineKey;
|
||||||
|
fm.beginTransaction()
|
||||||
|
.add(R.id.fragmentContainer, fragment, TAG)
|
||||||
|
.addToBackStack(TAG).commitAllowingStateLoss();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,12 +1,27 @@
|
||||||
package net.osmand.plus.profiles;
|
package net.osmand.plus.profiles;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import net.osmand.plus.R;
|
import net.osmand.plus.R;
|
||||||
|
|
||||||
public class OnlineRoutingEngineDataObject extends ProfileDataObject {
|
public class OnlineRoutingEngineDataObject extends ProfileDataObject {
|
||||||
|
|
||||||
|
private int order;
|
||||||
|
|
||||||
public OnlineRoutingEngineDataObject(String name,
|
public OnlineRoutingEngineDataObject(String name,
|
||||||
String description,
|
String description,
|
||||||
String stringKey) {
|
String stringKey,
|
||||||
|
int order) {
|
||||||
super(name, description, stringKey, R.drawable.ic_world_globe_dark, false, null);
|
super(name, description, stringKey, R.drawable.ic_world_globe_dark, false, null);
|
||||||
|
this.order = order;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(@NonNull ProfileDataObject profileDataObject) {
|
||||||
|
if (profileDataObject instanceof OnlineRoutingEngineDataObject) {
|
||||||
|
OnlineRoutingEngineDataObject another = (OnlineRoutingEngineDataObject) profileDataObject;
|
||||||
|
return (this.order < another.order) ? -1 : ((this.order == another.order) ? 0 : 1);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ import android.content.Context;
|
||||||
import net.osmand.plus.OsmandApplication;
|
import net.osmand.plus.OsmandApplication;
|
||||||
import net.osmand.plus.OsmandPlugin;
|
import net.osmand.plus.OsmandPlugin;
|
||||||
import net.osmand.plus.R;
|
import net.osmand.plus.R;
|
||||||
import net.osmand.plus.onlinerouting.OnlineRoutingEngine;
|
import net.osmand.plus.onlinerouting.engine.OnlineRoutingEngine;
|
||||||
import net.osmand.plus.profiles.RoutingProfileDataObject.RoutingProfilesResources;
|
import net.osmand.plus.profiles.RoutingProfileDataObject.RoutingProfilesResources;
|
||||||
import net.osmand.plus.settings.backend.ApplicationMode;
|
import net.osmand.plus.settings.backend.ApplicationMode;
|
||||||
import net.osmand.router.GeneralRouter;
|
import net.osmand.router.GeneralRouter;
|
||||||
|
@ -56,7 +56,22 @@ public class ProfileDataUtils {
|
||||||
Collections.sort(fileNames, new Comparator<String>() {
|
Collections.sort(fileNames, new Comparator<String>() {
|
||||||
@Override
|
@Override
|
||||||
public int compare(String s, String t1) {
|
public int compare(String s, String t1) {
|
||||||
return s.equals(OSMAND_NAVIGATION) ? -1 : t1.equals(OSMAND_NAVIGATION) ? 1 : s.compareToIgnoreCase(t1);
|
// OsmAnd navigation should be at the top of the list
|
||||||
|
if (s.equals(OSMAND_NAVIGATION)) {
|
||||||
|
return -1;
|
||||||
|
} else if (t1.equals(OSMAND_NAVIGATION)) {
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
// Online navigation should be at the bottom of the list
|
||||||
|
} else if (s.equals(ONLINE_NAVIGATION)) {
|
||||||
|
return 1;
|
||||||
|
} else if (t1.equals(ONLINE_NAVIGATION)) {
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
// Other sorted by file names
|
||||||
|
} else {
|
||||||
|
return s.compareToIgnoreCase(t1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
for (String fileName : fileNames) {
|
for (String fileName : fileNames) {
|
||||||
|
@ -71,9 +86,11 @@ public class ProfileDataUtils {
|
||||||
|
|
||||||
public static List<OnlineRoutingEngineDataObject> getOnlineRoutingProfiles(OsmandApplication app) {
|
public static List<OnlineRoutingEngineDataObject> getOnlineRoutingProfiles(OsmandApplication app) {
|
||||||
List<OnlineRoutingEngineDataObject> objects = new ArrayList<>();
|
List<OnlineRoutingEngineDataObject> objects = new ArrayList<>();
|
||||||
for (OnlineRoutingEngine engine : app.getOnlineRoutingHelper().getEngines()) {
|
List<OnlineRoutingEngine> engines = app.getOnlineRoutingHelper().getEngines();
|
||||||
|
for (int i = 0; i < engines.size(); i++) {
|
||||||
|
OnlineRoutingEngine engine = engines.get(i);
|
||||||
objects.add(new OnlineRoutingEngineDataObject(
|
objects.add(new OnlineRoutingEngineDataObject(
|
||||||
engine.getName(app), engine.getBaseUrl(), engine.getStringKey()));
|
engine.getName(app), engine.getBaseUrl(), engine.getStringKey(), i));
|
||||||
}
|
}
|
||||||
return objects;
|
return objects;
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,8 +39,9 @@ import net.osmand.plus.base.bottomsheetmenu.simpleitems.TitleItem;
|
||||||
import net.osmand.plus.helpers.FontCache;
|
import net.osmand.plus.helpers.FontCache;
|
||||||
import net.osmand.plus.settings.backend.ApplicationMode;
|
import net.osmand.plus.settings.backend.ApplicationMode;
|
||||||
import net.osmand.plus.settings.bottomsheets.BasePreferenceBottomSheet;
|
import net.osmand.plus.settings.bottomsheets.BasePreferenceBottomSheet;
|
||||||
import net.osmand.plus.onlinerouting.OnlineRoutingEngineFragment;
|
import net.osmand.plus.onlinerouting.ui.OnlineRoutingEngineFragment;
|
||||||
import net.osmand.router.RoutingConfiguration;
|
import net.osmand.router.RoutingConfiguration;
|
||||||
|
import net.osmand.util.Algorithms;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
|
|
||||||
|
@ -250,7 +251,7 @@ public class SelectProfileBottomSheet extends BasePreferenceBottomSheet {
|
||||||
tvTitle.setText(profile.getName());
|
tvTitle.setText(profile.getName());
|
||||||
tvDescription.setText(profile.getDescription());
|
tvDescription.setText(profile.getDescription());
|
||||||
|
|
||||||
boolean isSelected = setupSelected && profile.getStringKey().equals(selectedItemKey);
|
boolean isSelected = setupSelected && Algorithms.objectEquals(profile.getStringKey(), selectedItemKey);
|
||||||
int iconColor;
|
int iconColor;
|
||||||
if (dialogMode == DialogMode.NAVIGATION_PROFILE) {
|
if (dialogMode == DialogMode.NAVIGATION_PROFILE) {
|
||||||
iconColor = isSelected ? activeColorResId : iconDefaultColorResId;
|
iconColor = isSelected ? activeColorResId : iconDefaultColorResId;
|
||||||
|
|
|
@ -2,7 +2,6 @@ package net.osmand.plus.routing;
|
||||||
|
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Build;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.util.Base64;
|
import android.util.Base64;
|
||||||
|
|
||||||
|
@ -20,16 +19,14 @@ import net.osmand.binary.BinaryMapIndexReader;
|
||||||
import net.osmand.data.LatLon;
|
import net.osmand.data.LatLon;
|
||||||
import net.osmand.data.LocationPoint;
|
import net.osmand.data.LocationPoint;
|
||||||
import net.osmand.data.WptLocationPoint;
|
import net.osmand.data.WptLocationPoint;
|
||||||
import net.osmand.osm.io.NetworkUtils;
|
|
||||||
import net.osmand.plus.OsmandApplication;
|
import net.osmand.plus.OsmandApplication;
|
||||||
import net.osmand.plus.onlinerouting.OnlineRoutingEngine;
|
|
||||||
import net.osmand.plus.onlinerouting.OnlineRoutingHelper;
|
import net.osmand.plus.onlinerouting.OnlineRoutingHelper;
|
||||||
|
import net.osmand.plus.onlinerouting.engine.OnlineRoutingEngine;
|
||||||
import net.osmand.plus.settings.backend.OsmandSettings;
|
import net.osmand.plus.settings.backend.OsmandSettings;
|
||||||
import net.osmand.plus.settings.backend.CommonPreference;
|
import net.osmand.plus.settings.backend.CommonPreference;
|
||||||
import net.osmand.plus.R;
|
import net.osmand.plus.R;
|
||||||
import net.osmand.plus.TargetPointsHelper;
|
import net.osmand.plus.TargetPointsHelper;
|
||||||
import net.osmand.plus.TargetPointsHelper.TargetPoint;
|
import net.osmand.plus.TargetPointsHelper.TargetPoint;
|
||||||
import net.osmand.plus.Version;
|
|
||||||
import net.osmand.plus.render.NativeOsmandLibrary;
|
import net.osmand.plus.render.NativeOsmandLibrary;
|
||||||
import net.osmand.plus.settings.backend.ApplicationMode;
|
import net.osmand.plus.settings.backend.ApplicationMode;
|
||||||
import net.osmand.router.GeneralRouter;
|
import net.osmand.router.GeneralRouter;
|
||||||
|
@ -48,21 +45,16 @@ import net.osmand.router.RoutingConfiguration.Builder;
|
||||||
import net.osmand.router.RoutingContext;
|
import net.osmand.router.RoutingContext;
|
||||||
import net.osmand.router.TurnType;
|
import net.osmand.router.TurnType;
|
||||||
import net.osmand.util.Algorithms;
|
import net.osmand.util.Algorithms;
|
||||||
import net.osmand.util.GeoPolylineParserUtil;
|
|
||||||
import net.osmand.util.MapUtils;
|
import net.osmand.util.MapUtils;
|
||||||
|
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
|
||||||
import org.xml.sax.SAXException;
|
import org.xml.sax.SAXException;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.net.URLConnection;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
@ -1210,8 +1202,12 @@ public class RouteProvider {
|
||||||
private RouteCalculationResult findOnlineRoute(RouteCalculationParams params) throws IOException, JSONException {
|
private RouteCalculationResult findOnlineRoute(RouteCalculationParams params) throws IOException, JSONException {
|
||||||
OnlineRoutingHelper helper = params.ctx.getOnlineRoutingHelper();
|
OnlineRoutingHelper helper = params.ctx.getOnlineRoutingHelper();
|
||||||
String stringKey = params.mode.getRoutingProfile();
|
String stringKey = params.mode.getRoutingProfile();
|
||||||
List<LatLon> route = helper.calculateRouteOnline(helper.getEngineByKey(stringKey), getFullPathFromParams(params));
|
OnlineRoutingEngine engine = helper.getEngineByKey(stringKey);
|
||||||
if (!route.isEmpty()) {
|
List<LatLon> route = null;
|
||||||
|
if (engine != null) {
|
||||||
|
route = helper.calculateRouteOnline(engine, getFullPathFromParams(params));
|
||||||
|
}
|
||||||
|
if (!Algorithms.isEmpty(route)) {
|
||||||
List<Location> res = new ArrayList<>();
|
List<Location> res = new ArrayList<>();
|
||||||
for (LatLon pt : route) {
|
for (LatLon pt : route) {
|
||||||
WptPt wpt = new WptPt();
|
WptPt wpt = new WptPt();
|
||||||
|
|
|
@ -194,7 +194,7 @@ public class RoutingHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void setFinalAndCurrentLocation(LatLon finalLocation, List<LatLon> intermediatePoints, Location currentLocation) {
|
public synchronized void setFinalAndCurrentLocation(LatLon finalLocation, List<LatLon> intermediatePoints, Location currentLocation) {
|
||||||
RoutingHelperUtils.checkAndUpdateStartLocation(app, currentLocation);
|
RoutingHelperUtils.checkAndUpdateStartLocation(app, currentLocation, false);
|
||||||
RouteCalculationResult previousRoute = route;
|
RouteCalculationResult previousRoute = route;
|
||||||
clearCurrentRoute(finalLocation, intermediatePoints);
|
clearCurrentRoute(finalLocation, intermediatePoints);
|
||||||
// to update route
|
// to update route
|
||||||
|
|
|
@ -8,9 +8,6 @@ import net.osmand.data.LatLon;
|
||||||
import net.osmand.data.QuadRect;
|
import net.osmand.data.QuadRect;
|
||||||
import net.osmand.plus.OsmandApplication;
|
import net.osmand.plus.OsmandApplication;
|
||||||
import net.osmand.plus.TargetPointsHelper;
|
import net.osmand.plus.TargetPointsHelper;
|
||||||
import net.osmand.plus.helpers.enums.MetricsConstants;
|
|
||||||
import net.osmand.plus.settings.backend.ApplicationMode;
|
|
||||||
import net.osmand.plus.settings.backend.OsmandSettings;
|
|
||||||
import net.osmand.util.MapUtils;
|
import net.osmand.util.MapUtils;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -164,19 +161,20 @@ public class RoutingHelperUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static void checkAndUpdateStartLocation(@NonNull OsmandApplication app, LatLon newStartLocation) {
|
public static void checkAndUpdateStartLocation(@NonNull OsmandApplication app, LatLon newStartLocation, boolean force) {
|
||||||
if (newStartLocation != null) {
|
if (newStartLocation != null) {
|
||||||
LatLon lastStartLocation = app.getSettings().getLastStartPoint();
|
LatLon lastStartLocation = app.getSettings().getLastStartPoint();
|
||||||
if (lastStartLocation == null || MapUtils.getDistance(newStartLocation, lastStartLocation) > CACHE_RADIUS) {
|
if (lastStartLocation == null || MapUtils.getDistance(newStartLocation, lastStartLocation) > CACHE_RADIUS || force) {
|
||||||
app.getMapViewTrackingUtilities().detectDrivingRegion(newStartLocation);
|
app.getMapViewTrackingUtilities().detectDrivingRegion(newStartLocation);
|
||||||
app.getSettings().setLastStartPoint(newStartLocation);
|
app.getSettings().setLastStartPoint(newStartLocation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void checkAndUpdateStartLocation(@NonNull OsmandApplication app, Location nextStartLocation) {
|
public static void checkAndUpdateStartLocation(@NonNull OsmandApplication app, Location nextStartLocation, boolean force) {
|
||||||
if (nextStartLocation != null) {
|
if (nextStartLocation != null) {
|
||||||
checkAndUpdateStartLocation(app, new LatLon(nextStartLocation.getLatitude(), nextStartLocation.getLongitude()));
|
LatLon newStartLocation = new LatLon(nextStartLocation.getLatitude(), nextStartLocation.getLongitude());
|
||||||
|
checkAndUpdateStartLocation(app, newStartLocation, force);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,8 +7,9 @@ import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import net.osmand.plus.OsmandApplication;
|
import net.osmand.plus.OsmandApplication;
|
||||||
import net.osmand.plus.R;
|
import net.osmand.plus.R;
|
||||||
import net.osmand.plus.onlinerouting.OnlineRoutingEngine;
|
import net.osmand.plus.onlinerouting.EngineParameter;
|
||||||
import net.osmand.plus.onlinerouting.OnlineRoutingEngine.EngineParameter;
|
import net.osmand.plus.onlinerouting.OnlineRoutingFactory;
|
||||||
|
import net.osmand.plus.onlinerouting.engine.OnlineRoutingEngine;
|
||||||
import net.osmand.plus.onlinerouting.OnlineRoutingHelper;
|
import net.osmand.plus.onlinerouting.OnlineRoutingHelper;
|
||||||
|
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
|
@ -93,8 +94,8 @@ public class OnlineRoutingSettingsItem extends CollectionSettingsItem<OnlineRout
|
||||||
int number = 0;
|
int number = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
number++;
|
number++;
|
||||||
OnlineRoutingEngine renamedItem = OnlineRoutingEngine.createNewEngine(item.getType(), item.getVehicleKey(), item.getParams());
|
OnlineRoutingEngine renamedItem = OnlineRoutingFactory.createEngine(item.getType(), item.getParams());
|
||||||
renamedItem.putParameter(EngineParameter.CUSTOM_NAME, renamedItem.getName(app) + "_" + number);
|
renamedItem.put(EngineParameter.CUSTOM_NAME, renamedItem.getName(app) + "_" + number);
|
||||||
if (!isDuplicate(renamedItem)) {
|
if (!isDuplicate(renamedItem)) {
|
||||||
return renamedItem;
|
return renamedItem;
|
||||||
}
|
}
|
||||||
|
@ -105,7 +106,7 @@ public class OnlineRoutingSettingsItem extends CollectionSettingsItem<OnlineRout
|
||||||
void readItemsFromJson(@NonNull JSONObject json) throws IllegalArgumentException {
|
void readItemsFromJson(@NonNull JSONObject json) throws IllegalArgumentException {
|
||||||
try {
|
try {
|
||||||
OnlineRoutingHelper.readFromJson(json, items);
|
OnlineRoutingHelper.readFromJson(json, items);
|
||||||
} catch (JSONException e) {
|
} catch (JSONException | IllegalArgumentException e) {
|
||||||
warnings.add(app.getString(R.string.settings_item_read_error, String.valueOf(getType())));
|
warnings.add(app.getString(R.string.settings_item_read_error, String.valueOf(getType())));
|
||||||
throw new IllegalArgumentException("Json parse error", e);
|
throw new IllegalArgumentException("Json parse error", e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@ import net.osmand.plus.helpers.SearchHistoryHelper;
|
||||||
import net.osmand.plus.helpers.SearchHistoryHelper.HistoryEntry;
|
import net.osmand.plus.helpers.SearchHistoryHelper.HistoryEntry;
|
||||||
import net.osmand.plus.mapmarkers.MapMarker;
|
import net.osmand.plus.mapmarkers.MapMarker;
|
||||||
import net.osmand.plus.mapmarkers.MapMarkersGroup;
|
import net.osmand.plus.mapmarkers.MapMarkersGroup;
|
||||||
import net.osmand.plus.onlinerouting.OnlineRoutingEngine;
|
import net.osmand.plus.onlinerouting.engine.OnlineRoutingEngine;
|
||||||
import net.osmand.plus.osmedit.OpenstreetmapPoint;
|
import net.osmand.plus.osmedit.OpenstreetmapPoint;
|
||||||
import net.osmand.plus.osmedit.OsmEditingPlugin;
|
import net.osmand.plus.osmedit.OsmEditingPlugin;
|
||||||
import net.osmand.plus.osmedit.OsmNotesPoint;
|
import net.osmand.plus.osmedit.OsmNotesPoint;
|
||||||
|
|
|
@ -23,7 +23,7 @@ import net.osmand.plus.helpers.FileNameTranslationHelper;
|
||||||
import net.osmand.plus.helpers.GpxUiHelper;
|
import net.osmand.plus.helpers.GpxUiHelper;
|
||||||
import net.osmand.plus.helpers.SearchHistoryHelper.HistoryEntry;
|
import net.osmand.plus.helpers.SearchHistoryHelper.HistoryEntry;
|
||||||
import net.osmand.plus.mapmarkers.MapMarker;
|
import net.osmand.plus.mapmarkers.MapMarker;
|
||||||
import net.osmand.plus.onlinerouting.OnlineRoutingEngine;
|
import net.osmand.plus.onlinerouting.engine.OnlineRoutingEngine;
|
||||||
import net.osmand.plus.poi.PoiUIFilter;
|
import net.osmand.plus.poi.PoiUIFilter;
|
||||||
import net.osmand.plus.profiles.ProfileIconColors;
|
import net.osmand.plus.profiles.ProfileIconColors;
|
||||||
import net.osmand.plus.profiles.RoutingProfileDataObject.RoutingProfilesResources;
|
import net.osmand.plus.profiles.RoutingProfileDataObject.RoutingProfilesResources;
|
||||||
|
|
|
@ -40,7 +40,7 @@ import net.osmand.plus.helpers.FileNameTranslationHelper;
|
||||||
import net.osmand.plus.helpers.GpxUiHelper;
|
import net.osmand.plus.helpers.GpxUiHelper;
|
||||||
import net.osmand.plus.helpers.SearchHistoryHelper.HistoryEntry;
|
import net.osmand.plus.helpers.SearchHistoryHelper.HistoryEntry;
|
||||||
import net.osmand.plus.mapmarkers.MapMarkersGroup;
|
import net.osmand.plus.mapmarkers.MapMarkersGroup;
|
||||||
import net.osmand.plus.onlinerouting.OnlineRoutingEngine;
|
import net.osmand.plus.onlinerouting.engine.OnlineRoutingEngine;
|
||||||
import net.osmand.plus.osmedit.OpenstreetmapPoint;
|
import net.osmand.plus.osmedit.OpenstreetmapPoint;
|
||||||
import net.osmand.plus.osmedit.OsmEditingPlugin;
|
import net.osmand.plus.osmedit.OsmEditingPlugin;
|
||||||
import net.osmand.plus.osmedit.OsmNotesPoint;
|
import net.osmand.plus.osmedit.OsmNotesPoint;
|
||||||
|
|
|
@ -34,7 +34,7 @@ import net.osmand.plus.base.BaseOsmAndFragment;
|
||||||
import net.osmand.plus.helpers.AvoidSpecificRoads.AvoidRoadInfo;
|
import net.osmand.plus.helpers.AvoidSpecificRoads.AvoidRoadInfo;
|
||||||
import net.osmand.plus.helpers.SearchHistoryHelper.HistoryEntry;
|
import net.osmand.plus.helpers.SearchHistoryHelper.HistoryEntry;
|
||||||
import net.osmand.plus.mapmarkers.MapMarker;
|
import net.osmand.plus.mapmarkers.MapMarker;
|
||||||
import net.osmand.plus.onlinerouting.OnlineRoutingEngine;
|
import net.osmand.plus.onlinerouting.engine.OnlineRoutingEngine;
|
||||||
import net.osmand.plus.osmedit.OpenstreetmapPoint;
|
import net.osmand.plus.osmedit.OpenstreetmapPoint;
|
||||||
import net.osmand.plus.osmedit.OsmNotesPoint;
|
import net.osmand.plus.osmedit.OsmNotesPoint;
|
||||||
import net.osmand.plus.poi.PoiUIFilter;
|
import net.osmand.plus.poi.PoiUIFilter;
|
||||||
|
|
|
@ -36,7 +36,7 @@ import net.osmand.plus.helpers.AvoidSpecificRoads.AvoidRoadInfo;
|
||||||
import net.osmand.plus.helpers.SearchHistoryHelper.HistoryEntry;
|
import net.osmand.plus.helpers.SearchHistoryHelper.HistoryEntry;
|
||||||
import net.osmand.plus.mapmarkers.MapMarker;
|
import net.osmand.plus.mapmarkers.MapMarker;
|
||||||
import net.osmand.plus.mapmarkers.MapMarkersGroup;
|
import net.osmand.plus.mapmarkers.MapMarkersGroup;
|
||||||
import net.osmand.plus.onlinerouting.OnlineRoutingEngine;
|
import net.osmand.plus.onlinerouting.engine.OnlineRoutingEngine;
|
||||||
import net.osmand.plus.osmedit.OpenstreetmapPoint;
|
import net.osmand.plus.osmedit.OpenstreetmapPoint;
|
||||||
import net.osmand.plus.osmedit.OsmNotesPoint;
|
import net.osmand.plus.osmedit.OsmNotesPoint;
|
||||||
import net.osmand.plus.poi.PoiUIFilter;
|
import net.osmand.plus.poi.PoiUIFilter;
|
||||||
|
|
|
@ -27,7 +27,7 @@ import net.osmand.util.Algorithms;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import static net.osmand.plus.onlinerouting.OnlineRoutingEngine.ONLINE_ROUTING_ENGINE_PREFIX;
|
import static net.osmand.plus.onlinerouting.engine.OnlineRoutingEngine.ONLINE_ROUTING_ENGINE_PREFIX;
|
||||||
import static net.osmand.plus.profiles.SelectProfileBottomSheet.PROFILES_LIST_UPDATED_ARG;
|
import static net.osmand.plus.profiles.SelectProfileBottomSheet.PROFILES_LIST_UPDATED_ARG;
|
||||||
import static net.osmand.plus.profiles.SelectProfileBottomSheet.PROFILE_KEY_ARG;
|
import static net.osmand.plus.profiles.SelectProfileBottomSheet.PROFILE_KEY_ARG;
|
||||||
import static net.osmand.plus.routepreparationmenu.RouteOptionsBottomSheet.DIALOG_MODE_KEY;
|
import static net.osmand.plus.routepreparationmenu.RouteOptionsBottomSheet.DIALOG_MODE_KEY;
|
||||||
|
|
|
@ -42,6 +42,7 @@ import net.osmand.plus.dialogs.GpxAppearanceAdapter;
|
||||||
import net.osmand.plus.dialogs.GpxAppearanceAdapter.AppearanceListItem;
|
import net.osmand.plus.dialogs.GpxAppearanceAdapter.AppearanceListItem;
|
||||||
import net.osmand.plus.dialogs.GpxAppearanceAdapter.GpxAppearanceAdapterType;
|
import net.osmand.plus.dialogs.GpxAppearanceAdapter.GpxAppearanceAdapterType;
|
||||||
import net.osmand.plus.helpers.AndroidUiHelper;
|
import net.osmand.plus.helpers.AndroidUiHelper;
|
||||||
|
import net.osmand.plus.monitoring.TripRecordingBottomSheet;
|
||||||
import net.osmand.plus.routepreparationmenu.cards.BaseCard;
|
import net.osmand.plus.routepreparationmenu.cards.BaseCard;
|
||||||
import net.osmand.plus.routepreparationmenu.cards.BaseCard.CardListener;
|
import net.osmand.plus.routepreparationmenu.cards.BaseCard.CardListener;
|
||||||
import net.osmand.plus.settings.backend.CommonPreference;
|
import net.osmand.plus.settings.backend.CommonPreference;
|
||||||
|
@ -160,8 +161,13 @@ public class TrackAppearanceFragment extends ContextMenuScrollFragment implement
|
||||||
public void handleOnBackPressed() {
|
public void handleOnBackPressed() {
|
||||||
MapActivity mapActivity = getMapActivity();
|
MapActivity mapActivity = getMapActivity();
|
||||||
if (mapActivity != null) {
|
if (mapActivity != null) {
|
||||||
|
TripRecordingBottomSheet fragment = mapActivity.getTripRecordingBottomSheet();
|
||||||
|
if (fragment != null) {
|
||||||
|
fragment.show();
|
||||||
|
} else {
|
||||||
|
mapActivity.launchPrevActivityIntent();
|
||||||
|
}
|
||||||
dismissImmediate();
|
dismissImmediate();
|
||||||
mapActivity.launchPrevActivityIntent();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -405,7 +411,7 @@ public class TrackAppearanceFragment extends ContextMenuScrollFragment implement
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Drawable getTrackIcon(OsmandApplication app, String widthAttr, boolean showArrows, @ColorInt int color) {
|
public static Drawable getTrackIcon(OsmandApplication app, String widthAttr, boolean showArrows, @ColorInt int color) {
|
||||||
int widthIconId = getWidthIconId(widthAttr);
|
int widthIconId = getWidthIconId(widthAttr);
|
||||||
Drawable widthIcon = app.getUIUtilities().getPaintedIcon(widthIconId, color);
|
Drawable widthIcon = app.getUIUtilities().getPaintedIcon(widthIconId, color);
|
||||||
|
|
||||||
|
@ -423,7 +429,7 @@ public class TrackAppearanceFragment extends ContextMenuScrollFragment implement
|
||||||
return UiUtilities.getLayeredIcon(transparencyIcon, widthIcon, strokeIcon);
|
return UiUtilities.getLayeredIcon(transparencyIcon, widthIcon, strokeIcon);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Drawable getTransparencyIcon(OsmandApplication app, String widthAttr, @ColorInt int color) {
|
private static Drawable getTransparencyIcon(OsmandApplication app, String widthAttr, @ColorInt int color) {
|
||||||
int transparencyIconId = getTransparencyIconId(widthAttr);
|
int transparencyIconId = getTransparencyIconId(widthAttr);
|
||||||
int colorWithoutAlpha = UiUtilities.removeAlpha(color);
|
int colorWithoutAlpha = UiUtilities.removeAlpha(color);
|
||||||
int transparencyColor = UiUtilities.getColorWithAlpha(colorWithoutAlpha, 0.8f);
|
int transparencyColor = UiUtilities.getColorWithAlpha(colorWithoutAlpha, 0.8f);
|
||||||
|
|
|
@ -871,19 +871,18 @@ public class MapControlsLayer extends OsmandMapLayer {
|
||||||
boolean showBottomMenuButtons = (showRouteCalculationControls || !routeFollowingMode)
|
boolean showBottomMenuButtons = (showRouteCalculationControls || !routeFollowingMode)
|
||||||
&& !isInMovingMarkerMode() && !isInGpxDetailsMode() && !isInMeasurementToolMode()
|
&& !isInMovingMarkerMode() && !isInGpxDetailsMode() && !isInMeasurementToolMode()
|
||||||
&& !isInPlanRouteMode() && !contextMenuOpened && !isInChoosingRoutesMode()
|
&& !isInPlanRouteMode() && !contextMenuOpened && !isInChoosingRoutesMode()
|
||||||
&& !isInWaypointsChoosingMode() && !isInFollowTrackMode() && !isInTrackAppearanceMode()
|
&& !isInWaypointsChoosingMode() && !isInFollowTrackMode() && !isInTrackAppearanceMode();
|
||||||
&& !isInTrackMenuMode();
|
|
||||||
routePlanningBtn.updateVisibility(showBottomMenuButtons);
|
routePlanningBtn.updateVisibility(showBottomMenuButtons);
|
||||||
menuControl.updateVisibility(showBottomMenuButtons);
|
menuControl.updateVisibility(showBottomMenuButtons);
|
||||||
|
|
||||||
boolean showZoomButtons = !routeDialogOpened && !contextMenuOpened && !isInTrackAppearanceMode()
|
boolean showZoomButtons = !routeDialogOpened && !contextMenuOpened && !isInTrackAppearanceMode()
|
||||||
&& !isInTrackMenuMode() && (!isInGpxApproximationMode() || !isPotrait())
|
&& (!isInGpxApproximationMode() || !isPotrait())
|
||||||
&& !isInFollowTrackMode() && (!isInChoosingRoutesMode() || !isInWaypointsChoosingMode() || !portrait);
|
&& !isInFollowTrackMode() && (!isInChoosingRoutesMode() || !isInWaypointsChoosingMode() || !portrait);
|
||||||
mapZoomIn.updateVisibility(showZoomButtons);
|
mapZoomIn.updateVisibility(showZoomButtons);
|
||||||
mapZoomOut.updateVisibility(showZoomButtons);
|
mapZoomOut.updateVisibility(showZoomButtons);
|
||||||
|
|
||||||
boolean forceHideCompass = routeDialogOpened || trackDialogOpened || isInMeasurementToolMode()
|
boolean forceHideCompass = routeDialogOpened || trackDialogOpened || isInMeasurementToolMode()
|
||||||
|| isInPlanRouteMode() || contextMenuOpened || isInChoosingRoutesMode() || isInTrackMenuMode()
|
|| isInPlanRouteMode() || contextMenuOpened || isInChoosingRoutesMode()
|
||||||
|| isInTrackAppearanceMode() || isInWaypointsChoosingMode() || isInFollowTrackMode();
|
|| isInTrackAppearanceMode() || isInWaypointsChoosingMode() || isInFollowTrackMode();
|
||||||
compassHud.forceHideCompass = forceHideCompass;
|
compassHud.forceHideCompass = forceHideCompass;
|
||||||
compassHud.updateVisibility(!forceHideCompass && shouldShowCompass());
|
compassHud.updateVisibility(!forceHideCompass && shouldShowCompass());
|
||||||
|
@ -895,8 +894,7 @@ public class MapControlsLayer extends OsmandMapLayer {
|
||||||
}
|
}
|
||||||
boolean showTopButtons = !routeDialogOpened && !trackDialogOpened && !contextMenuOpened
|
boolean showTopButtons = !routeDialogOpened && !trackDialogOpened && !contextMenuOpened
|
||||||
&& !isInMeasurementToolMode() && !isInPlanRouteMode() && !isInChoosingRoutesMode()
|
&& !isInMeasurementToolMode() && !isInPlanRouteMode() && !isInChoosingRoutesMode()
|
||||||
&& !isInTrackAppearanceMode() && !isInWaypointsChoosingMode() && !isInFollowTrackMode()
|
&& !isInTrackAppearanceMode() && !isInWaypointsChoosingMode() && !isInFollowTrackMode();
|
||||||
&& !isInTrackMenuMode();
|
|
||||||
layersHud.updateVisibility(showTopButtons);
|
layersHud.updateVisibility(showTopButtons);
|
||||||
quickSearchHud.updateVisibility(showTopButtons);
|
quickSearchHud.updateVisibility(showTopButtons);
|
||||||
|
|
||||||
|
@ -1023,8 +1021,7 @@ public class MapControlsLayer extends OsmandMapLayer {
|
||||||
boolean tracked = mapActivity.getMapViewTrackingUtilities().isMapLinkedToLocation();
|
boolean tracked = mapActivity.getMapViewTrackingUtilities().isMapLinkedToLocation();
|
||||||
boolean visible = !(tracked && rh.isFollowingMode()) && (!isInGpxApproximationMode() || !isPotrait());
|
boolean visible = !(tracked && rh.isFollowingMode()) && (!isInGpxApproximationMode() || !isPotrait());
|
||||||
backToLocationControl.updateVisibility(visible && !dialogOpened && !isInPlanRouteMode()
|
backToLocationControl.updateVisibility(visible && !dialogOpened && !isInPlanRouteMode()
|
||||||
&& !isInTrackAppearanceMode() && !isInTrackMenuMode()
|
&& !isInTrackAppearanceMode() && (!isInChoosingRoutesMode() || !isInWaypointsChoosingMode() || !isInFollowTrackMode() || !isPotrait()));
|
||||||
&& (!isInChoosingRoutesMode() || !isInWaypointsChoosingMode() || !isInFollowTrackMode() || !isPotrait()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean onSingleTap(PointF point, RotatedTileBox tileBox) {
|
public boolean onSingleTap(PointF point, RotatedTileBox tileBox) {
|
||||||
|
|
|
@ -425,7 +425,6 @@ public class MapQuickActionLayer extends OsmandMapLayer implements QuickActionRe
|
||||||
measurementToolLayer.isInMeasurementMode() ||
|
measurementToolLayer.isInMeasurementMode() ||
|
||||||
mapMarkersLayer.isInPlanRouteMode() ||
|
mapMarkersLayer.isInPlanRouteMode() ||
|
||||||
gpxLayer.isInTrackAppearanceMode() ||
|
gpxLayer.isInTrackAppearanceMode() ||
|
||||||
mapControlsLayer.isInTrackMenuMode() ||
|
|
||||||
mapRouteInfoMenu.isVisible() ||
|
mapRouteInfoMenu.isVisible() ||
|
||||||
MapRouteInfoMenu.chooseRoutesVisible ||
|
MapRouteInfoMenu.chooseRoutesVisible ||
|
||||||
MapRouteInfoMenu.waypointsVisible ||
|
MapRouteInfoMenu.waypointsVisible ||
|
||||||
|
|
|
@ -1235,7 +1235,6 @@ public class MapInfoWidgetsFactory {
|
||||||
boolean visible = settings.SHOW_COORDINATES_WIDGET.get() && map.getContextMenu().shouldShowTopControls()
|
boolean visible = settings.SHOW_COORDINATES_WIDGET.get() && map.getContextMenu().shouldShowTopControls()
|
||||||
&& map.getMapRouteInfoMenu().shouldShowTopControls() && !map.isTopToolbarActive()
|
&& map.getMapRouteInfoMenu().shouldShowTopControls() && !map.isTopToolbarActive()
|
||||||
&& !map.getMapLayers().getGpxLayer().isInTrackAppearanceMode()
|
&& !map.getMapLayers().getGpxLayer().isInTrackAppearanceMode()
|
||||||
&& !map.getMapLayers().getMapControlsLayer().isInTrackMenuMode()
|
|
||||||
&& !MapRouteInfoMenu.chooseRoutesVisible && !MapRouteInfoMenu.waypointsVisible
|
&& !MapRouteInfoMenu.chooseRoutesVisible && !MapRouteInfoMenu.waypointsVisible
|
||||||
&& !MapRouteInfoMenu.followTrackVisible;
|
&& !MapRouteInfoMenu.followTrackVisible;
|
||||||
|
|
||||||
|
|
|
@ -193,8 +193,7 @@ public class MapMarkersWidgetsFactory {
|
||||||
|| map.isTopToolbarActive()
|
|| map.isTopToolbarActive()
|
||||||
|| !map.getContextMenu().shouldShowTopControls()
|
|| !map.getContextMenu().shouldShowTopControls()
|
||||||
|| map.getMapLayers().getGpxLayer().isInTrackAppearanceMode()
|
|| map.getMapLayers().getGpxLayer().isInTrackAppearanceMode()
|
||||||
|| map.getMapLayers().getMapMarkersLayer().isInPlanRouteMode()
|
|| map.getMapLayers().getMapMarkersLayer().isInPlanRouteMode()) {
|
||||||
|| map.getMapLayers().getMapControlsLayer().isInTrackMenuMode()) {
|
|
||||||
updateVisibility(false);
|
updateVisibility(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,6 @@ import androidx.fragment.app.FragmentActivity;
|
||||||
import androidx.fragment.app.FragmentManager;
|
import androidx.fragment.app.FragmentManager;
|
||||||
|
|
||||||
import net.osmand.AndroidUtils;
|
import net.osmand.AndroidUtils;
|
||||||
import net.osmand.GPXUtilities;
|
|
||||||
import net.osmand.GPXUtilities.GPXFile;
|
import net.osmand.GPXUtilities.GPXFile;
|
||||||
import net.osmand.GPXUtilities.WptPt;
|
import net.osmand.GPXUtilities.WptPt;
|
||||||
import net.osmand.data.LatLon;
|
import net.osmand.data.LatLon;
|
||||||
|
@ -26,6 +25,7 @@ import net.osmand.plus.wikivoyage.article.WikivoyageArticleDialogFragment;
|
||||||
import net.osmand.plus.wikivoyage.data.TravelArticle;
|
import net.osmand.plus.wikivoyage.data.TravelArticle;
|
||||||
import net.osmand.plus.wikivoyage.data.TravelArticle.TravelArticleIdentifier;
|
import net.osmand.plus.wikivoyage.data.TravelArticle.TravelArticleIdentifier;
|
||||||
import net.osmand.plus.wikivoyage.explore.WikivoyageExploreActivity;
|
import net.osmand.plus.wikivoyage.explore.WikivoyageExploreActivity;
|
||||||
|
import net.osmand.util.MapUtils;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -41,6 +41,7 @@ import static net.osmand.plus.wikipedia.WikiArticleHelper.WIKI_DOMAIN;
|
||||||
public class WikivoyageWebViewClient extends WebViewClient {
|
public class WikivoyageWebViewClient extends WebViewClient {
|
||||||
|
|
||||||
private static final String TAG = WikivoyageWebViewClient.class.getSimpleName();
|
private static final String TAG = WikivoyageWebViewClient.class.getSimpleName();
|
||||||
|
public static final int ROUNDING_ERROR = 3;
|
||||||
|
|
||||||
private OsmandApplication app;
|
private OsmandApplication app;
|
||||||
private FragmentManager fragmentManager;
|
private FragmentManager fragmentManager;
|
||||||
|
@ -85,29 +86,29 @@ public class WikivoyageWebViewClient extends WebViewClient {
|
||||||
} else if (isWebPage) {
|
} else if (isWebPage) {
|
||||||
WikiArticleHelper.warnAboutExternalLoad(url, activity, nightMode);
|
WikiArticleHelper.warnAboutExternalLoad(url, activity, nightMode);
|
||||||
} else if (url.startsWith(PREFIX_GEO)) {
|
} else if (url.startsWith(PREFIX_GEO)) {
|
||||||
if (article != null) {
|
if (article != null && article.getGpxFile() != null) {
|
||||||
List<WptPt> points = article.getGpxFile().getPoints();
|
List<WptPt> points = article.getGpxFile().getPoints();
|
||||||
WptPt gpxPoint = null;
|
WptPt gpxPoint = null;
|
||||||
String coordinates = url.replace(PREFIX_GEO, "");
|
String coordinates = url.replace(PREFIX_GEO, "");
|
||||||
double lat;
|
double lat;
|
||||||
double lon;
|
double lon;
|
||||||
try {
|
try {
|
||||||
lat = Double.valueOf(coordinates.substring(0, coordinates.indexOf(",")));
|
lat = Double.parseDouble(coordinates.substring(0, coordinates.indexOf(",")));
|
||||||
lon = Double.valueOf(coordinates.substring(coordinates.indexOf(",") + 1,
|
lon = Double.parseDouble(coordinates.substring(coordinates.indexOf(",") + 1));
|
||||||
coordinates.length()));
|
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
Log.w(TAG, e.getMessage(), e);
|
Log.w(TAG, e.getMessage(), e);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
for (WptPt point : points) {
|
for (WptPt point : points) {
|
||||||
if (point.getLatitude() == lat && point.getLongitude() == lon) {
|
if (MapUtils.getDistance(point.getLatitude(), point.getLongitude(), lat, lon) < ROUNDING_ERROR) {
|
||||||
gpxPoint = point;
|
gpxPoint = point;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (gpxPoint != null) {
|
if (gpxPoint != null) {
|
||||||
final OsmandSettings settings = app.getSettings();
|
final OsmandSettings settings = app.getSettings();
|
||||||
settings.setMapLocationToShow(lat, lon, settings.getLastKnownMapZoom(),
|
settings.setMapLocationToShow(gpxPoint.getLatitude(), gpxPoint.getLongitude(),
|
||||||
|
settings.getLastKnownMapZoom(),
|
||||||
new PointDescription(PointDescription.POINT_TYPE_WPT, gpxPoint.name),
|
new PointDescription(PointDescription.POINT_TYPE_WPT, gpxPoint.name),
|
||||||
false,
|
false,
|
||||||
gpxPoint);
|
gpxPoint);
|
||||||
|
|
Loading…
Reference in a new issue