Update ipfs image

This commit is contained in:
Victor Shcherb 2021-02-03 16:31:15 +01:00
commit 0f9673cd2e
101 changed files with 2835 additions and 1876 deletions

View file

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

View file

@ -94,6 +94,10 @@ public class OsmOAuthAuthorizationClient {
return accessToken;
}
public OAuth1RequestToken getRequestToken() {
return requestToken;
}
public Response performRequestWithoutAuth(String url, String requestMethod, String requestBody)
throws InterruptedException, ExecutionException, IOException {
Verb verb = parseRequestMethod(requestMethod);

View file

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

View file

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

View file

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

View file

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

View file

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

View file

@ -1,36 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/bg_color"
android:clickable="true"
android:focusable="true"
android:orientation="vertical">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/bg_color"
android:orientation="vertical">
<LinearLayout
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="@dimen/toolbar_height"
android:layout_marginTop="@dimen/dialog_content_margin">
android:gravity="center_vertical"
android:padding="0dp" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/back_button"
style="@style/Widget.AppCompat.Toolbar.Button.Navigation"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:contentDescription="@string/shared_string_back"
app:srcCompat="@drawable/ic_arrow_back"
app:tint="@color/icon_color_default_light" />
</LinearLayout>
<androidx.core.widget.NestedScrollView
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/toolbar"
android:layout_above="@id/buttons">
android:layout_height="0dp"
android:layout_weight="1">
<LinearLayout
android:layout_width="match_parent"
@ -49,7 +35,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/content_padding"
android:layout_marginTop="@dimen/content_padding"
android:layout_marginTop="@dimen/content_padding_small"
android:layout_marginRight="@dimen/content_padding"
android:layout_marginBottom="@dimen/dashPadding"
android:gravity="center_horizontal"
@ -68,23 +54,25 @@
android:layout_marginTop="@dimen/dashPadding"
android:layout_marginRight="@dimen/content_padding"
android:lineSpacingMultiplier="@dimen/bottom_sheet_text_spacing_multiplier"
app:typeface="@string/font_roboto_regular"
android:text="@string/register_on_openplacereviews_desc"
android:textColor="?android:textColorPrimary"
android:textColorLink="@color/icon_color_active_light"
android:textSize="@dimen/default_list_text_size"
android:textColorLink="@color/icon_color_active_light" />
app:typeface="@string/font_roboto_regular" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</ScrollView>
<LinearLayout
android:id="@+id/buttons"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:layout_marginLeft="@dimen/content_padding"
android:layout_marginTop="@dimen/content_padding_small"
android:layout_marginRight="@dimen/content_padding"
android:layout_marginBottom="@dimen/content_padding_small"
android:layout_alignParentBottom="true"
android:orientation="vertical">
<include
@ -102,4 +90,4 @@
</LinearLayout>
</RelativeLayout>
</LinearLayout>

View file

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

View file

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

View file

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

View file

@ -61,6 +61,13 @@
android:layout_gravity="center_vertical"
android:text="@string/amenity_type_finance"/>
<LinearLayout
android:id="@+id/context_menu_custom_address_line"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:visibility="gone" />
</LinearLayout>
</LinearLayout>

View file

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

View file

@ -1,5 +1,4 @@
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
@ -8,7 +7,8 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="56dp"
android:layout_height="wrap_content"
android:minHeight="@dimen/context_menu_action_buttons_height"
android:background="?attr/pstsTabBackground"
android:gravity="center_vertical"
android:orientation="horizontal">
@ -19,19 +19,19 @@
android:layout_width="52dp"
android:layout_height="52dp"
android:contentDescription="@string/shared_string_close"
app:srcCompat="@drawable/ic_action_remove_dark"/>
app:srcCompat="@drawable/ic_action_remove_dark" />
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/titleTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginLeft="20dp"
android:text="@string/osm_live_subscription"
android:textColor="@color/color_white"
android:textSize="@dimen/default_list_text_size_large"
android:textStyle="bold"
app:typeface="@string/font_roboto_regular"
android:layout_marginStart="20dp" />
app:typeface="@string/font_roboto_regular" />
</LinearLayout>
@ -39,7 +39,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
<include layout="@layout/card_bottom_divider"/>
<include layout="@layout/card_bottom_divider" />
<ScrollView
android:layout_width="match_parent"
@ -67,8 +67,8 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:minHeight="56dp"
android:orientation="horizontal">
@ -76,54 +76,81 @@
android:layout_width="56dp"
android:layout_height="48dp"
android:scaleType="center"
app:srcCompat="@drawable/ic_action_osm_live"
android:tint="@color/osmand_orange"/>
android:tint="@color/osmand_orange"
app:srcCompat="@drawable/ic_action_osm_live" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
android:paddingStart="2dp"
android:paddingLeft="2dp"
android:text="@string/osm_live_subscription_desc"
android:textColor="?android:attr/textColorPrimary"
android:layout_marginEnd="16dp"
android:paddingStart="2dp"
android:layout_marginStart="16dp" />
android:textColor="?android:attr/textColorPrimary" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginTop="4dp"
android:layout_marginBottom="8dp"
android:minHeight="56dp"
android:orientation="vertical">
android:orientation="horizontal">
<androidx.appcompat.widget.AppCompatCheckBox
android:id="@+id/donationCheckbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:paddingLeft="34dp"
android:text="@string/donation_to_osm"
android:paddingStart="34dp"
android:layout_marginStart="16dp" />
android:layout_marginTop="@dimen/context_menu_second_line_top_margin"
android:layout_marginStart="@dimen/list_content_padding"
android:layout_marginLeft="@dimen/list_content_padding"
android:paddingStart="@dimen/local_size_height"
android:paddingLeft="@dimen/local_size_height"
android:paddingEnd="@dimen/local_size_height"
android:paddingRight="@dimen/local_size_height"
android:text="@string/donation_to_osm" />
<TextView
android:layout_width="match_parent"
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="72dp"
android:layout_marginRight="16dp"
android:layout_marginTop="8dp"
android:paddingLeft="2dp"
android:text="@string/donation_to_osm_desc"
android:textColor="?android:attr/textColorSecondary"
android:layout_marginEnd="16dp"
android:layout_marginStart="72dp"
android:paddingStart="2dp" />
android:minHeight="56dp"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/list_content_padding_large"
android:layout_marginLeft="@dimen/context_menu_progress_padding_left"
android:layout_marginEnd="@dimen/context_menu_progress_padding_left"
android:layout_marginRight="@dimen/context_menu_progress_padding_left"
android:paddingStart="@dimen/subHeaderPadding"
android:paddingLeft="@dimen/subHeaderPadding"
android:paddingEnd="@dimen/subHeaderPadding"
android:paddingRight="@dimen/subHeaderPadding"
android:textColor="?android:textColorPrimary"
android:textSize="@dimen/default_list_text_size"
android:text="@string/donation_to_osm" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/list_content_padding_large"
android:layout_marginLeft="@dimen/context_menu_progress_padding_left"
android:layout_marginEnd="@dimen/context_menu_progress_padding_left"
android:layout_marginRight="@dimen/context_menu_progress_padding_left"
android:paddingStart="@dimen/subHeaderPadding"
android:paddingLeft="@dimen/subHeaderPadding"
android:paddingEnd="@dimen/subHeaderPadding"
android:paddingRight="@dimen/subHeaderPadding"
android:text="@string/donation_to_osm_desc"
android:textColor="?android:attr/textColorSecondary"/>
</LinearLayout>
</LinearLayout>
@ -140,13 +167,13 @@
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginBottom="6dp"
android:background="?attr/dashboard_divider"/>
android:background="?attr/dashboard_divider" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginTop="4dp"
android:layout_marginBottom="8dp"
android:minHeight="56dp"
android:orientation="horizontal">
@ -155,47 +182,48 @@
android:layout_width="56dp"
android:layout_height="48dp"
android:scaleType="center"
app:srcCompat="@drawable/ic_world_globe_dark"/>
app:srcCompat="@drawable/ic_world_globe_dark" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:layout_marginTop="8dp"
android:orientation="vertical"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp">
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="2dp"
android:paddingStart="@dimen/subHeaderPadding"
android:paddingEnd="@dimen/subHeaderPadding"
android:paddingLeft="@dimen/subHeaderPadding"
android:paddingRight="@dimen/subHeaderPadding"
android:text="@string/osm_live_support_region"
android:textColor="?android:attr/textColorSecondary"
android:paddingStart="2dp" />
android:textColor="?android:attr/textColorSecondary" />
<net.osmand.plus.widgets.AutoCompleteTextViewEx
android:id="@+id/selectCountryEdit"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
app:drawableRightCompat="@drawable/ic_action_arrow_drop_down"
app:drawableEndCompat="@drawable/ic_action_arrow_drop_down"
android:editable="false"
android:paddingStart="2dp"
android:paddingLeft="2dp"
android:paddingEnd="0dp"
android:paddingRight="0dp"
android:text="Ukraine"
android:paddingStart="2dp"
android:paddingEnd="0dp" />
app:drawableEndCompat="@drawable/ic_action_arrow_drop_down"
app:drawableRightCompat="@drawable/ic_action_arrow_drop_down" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:paddingStart="2dp"
android:paddingLeft="2dp"
android:text="@string/osm_live_region_desc"
android:textColor="?android:attr/textColorSecondary"
android:paddingStart="2dp" />
android:textColor="?android:attr/textColorSecondary" />
</LinearLayout>
@ -213,21 +241,21 @@
android:layout_width="56dp"
android:layout_height="48dp"
android:scaleType="center"
app:srcCompat="@drawable/ic_action_message"/>
app:srcCompat="@drawable/ic_action_message" />
<EditText
android:id="@+id/emailEdit"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
android:hint="@string/shared_string_email_address"
android:inputType="textEmailAddress"
android:paddingLeft="2dp"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:paddingStart="2dp" />
android:paddingStart="2dp"
android:paddingLeft="2dp" />
</LinearLayout>
@ -235,14 +263,14 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="72dp"
android:layout_marginLeft="72dp"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
android:paddingStart="2dp"
android:paddingLeft="2dp"
android:text="@string/osm_live_email_desc"
android:textColor="?android:attr/textColorSecondary"
android:paddingStart="2dp"
android:layout_marginStart="72dp"
android:layout_marginEnd="16dp" />
android:textColor="?android:attr/textColorSecondary" />
<LinearLayout
@ -261,21 +289,21 @@
android:layout_width="56dp"
android:layout_height="48dp"
android:scaleType="center"
app:srcCompat="@drawable/ic_action_user"/>
app:srcCompat="@drawable/ic_action_user" />
<EditText
android:id="@+id/userNameEdit"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
android:hint="@string/osm_live_user_public_name"
android:inputType="text"
android:paddingLeft="2dp"
android:layout_marginEnd="16dp"
android:layout_marginStart="16dp"
android:paddingStart="2dp" />
android:paddingStart="2dp"
android:paddingLeft="2dp" />
</LinearLayout>
@ -284,16 +312,16 @@
android:id="@+id/hideUserNameCheckbox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="12dp"
android:layout_marginStart="72dp"
android:layout_marginLeft="72dp"
android:layout_marginRight="16dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
android:layout_marginBottom="12dp"
android:paddingStart="4dp"
android:paddingLeft="4dp"
android:text="@string/osm_live_hide_user_name"
android:textColor="?android:attr/textColorPrimary"
android:layout_marginEnd="16dp"
android:paddingStart="4dp"
android:layout_marginStart="72dp" />
android:textColor="?android:attr/textColorPrimary" />
</LinearLayout>
@ -303,35 +331,35 @@
android:id="@+id/editModeBottomView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:layout_marginTop="16dp"
android:layout_marginBottom="16dp"
android:visibility="visible">
<Button
android:id="@+id/saveChangesButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="72dp"
android:layout_marginLeft="72dp"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
android:background="?attr/btn_round"
android:paddingStart="16dp"
android:paddingLeft="16dp"
android:paddingEnd="16dp"
android:paddingRight="16dp"
android:text="@string/shared_string_save_changes"
android:textColor="@color/color_white"
android:layout_marginStart="72dp"
android:layout_marginEnd="16dp"
android:paddingStart="16dp"
android:paddingEnd="16dp" />
android:textColor="@color/color_white" />
</LinearLayout>
</LinearLayout>
<include layout="@layout/card_bottom_divider"/>
<include layout="@layout/card_bottom_divider" />
<View
android:layout_width="match_parent"
android:layout_height="16dp"/>
android:layout_height="16dp" />
</LinearLayout>

View file

@ -24,7 +24,7 @@
android:layout_gravity="center_vertical"
android:layout_marginRight="@dimen/favorites_icon_right_margin"
tools:src="@drawable/ic_map"
android:layout_marginEnd="@dimen/favorites_icon_right_margin" />
android:layout_marginEnd="@dimen/favorites_icon_right_margin" />
<LinearLayout
android:layout_width="0dp"
@ -81,26 +81,26 @@
android:visibility="gone"
tools:src="@drawable/ic_action_import"
tools:visibility="visible"
android:layout_marginStart="@dimen/dashFavIconMargin" />
android:layout_marginStart="@dimen/dashFavIconMargin" />
<Button
android:id="@+id/rightButton"
android:layout_width="wrap_content"
android:layout_height="33dp"
android:minWidth="40dp"
android:paddingLeft="18dp"
android:paddingRight="18dp"
android:background="@drawable/buy_btn_background_light"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="@dimen/dashFavIconMargin"
android:layout_marginLeft="@dimen/dashFavIconMargin"
android:layout_marginRight="8dp"
android:textColor="@color/buy_button_color"
android:layout_marginEnd="@dimen/list_header_padding"
android:layout_marginRight="@dimen/list_header_padding"
android:minWidth="@dimen/list_header_height"
android:minHeight="@dimen/list_content_padding_large"
android:paddingStart="@dimen/context_menu_progress_padding_left"
android:paddingLeft="@dimen/context_menu_progress_padding_left"
android:paddingEnd="@dimen/context_menu_progress_padding_left"
android:paddingRight="@dimen/context_menu_progress_padding_left"
android:text="@string/buy"
android:visibility="gone"
android:layout_marginStart="@dimen/dashFavIconMargin"
android:layout_marginEnd="8dp"
android:paddingEnd="18dp"
android:paddingStart="18dp" />
android:textColor="@color/text_color_tab_active_light"
android:visibility="gone" />
</LinearLayout>

View file

@ -12,6 +12,11 @@
-->
<string name="login_open_place_reviews">Login to OpenPlaceReviews</string>
<string name="opr_use_dev_url">Use test.openplacereviews.org</string>
<string name="open_place_reviews">OpenPlaceReviews</string>
<string name="open_place_reviews_plugin_description">OpenPlaceReviews is a community-driven project about public places such as restaurants, hotels, museums, waypoints. It collects all public information about them such as photos, reviews, links to other systems link OpenStreetMap, Wikipedia.\n\nAll OpenPlaceReview data is open and available to everyone: http://openplacereviews.org/data.\n\nYou can read more at: http://openplacereviews.org</string>
<string name="hillshade_slope_contour_lines">Hillshade / Slope / Contour lines</string>
<string name="toast_select_edits_for_upload">Select edits for upload</string>
<string name="uploaded_count">Uploaded %1$d of %2$d</string>
<string name="uploading_count">Uploading %1$d of %2$d</string>

View file

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

View file

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

View file

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:title="@string/open_place_reviews">
<Preference
android:key="opr_settings_info"
android:layout="@layout/preference_info"
android:persistent="false"
android:selectable="false"
android:title="@string/plugin_global_prefs_info" />
<Preference
android:key="opr_login_data"
android:layout="@layout/preference_with_descr"
android:persistent="false"
android:title="@string/login_open_place_reviews" />
<Preference
android:key="opr_logout"
android:layout="@layout/preference_login"
android:persistent="false"
android:title="@string/login_account" />
<net.osmand.plus.settings.preferences.SwitchPreferenceEx
android:key="opr_use_dev_url"
android:layout="@layout/preference_with_descr_dialog_and_switch"
android:title="@string/opr_use_dev_url"
tools:icon="@drawable/ic_plugin_developer" />
</PreferenceScreen>

View file

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

View file

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

View file

@ -28,7 +28,6 @@ import net.osmand.map.OsmandRegions.RegionTranslation;
import net.osmand.map.WorldRegion;
import net.osmand.osm.AbstractPoiType;
import net.osmand.osm.MapPoiTypes;
import net.osmand.plus.helpers.DayNightHelper;
import net.osmand.plus.activities.LocalIndexHelper;
import net.osmand.plus.activities.LocalIndexInfo;
import net.osmand.plus.activities.SavingTrackHelper;
@ -36,6 +35,7 @@ import net.osmand.plus.base.MapViewTrackingUtilities;
import net.osmand.plus.download.DownloadActivity;
import net.osmand.plus.download.ui.AbstractLoadLocalIndexTask;
import net.osmand.plus.helpers.AvoidSpecificRoads;
import net.osmand.plus.helpers.DayNightHelper;
import net.osmand.plus.helpers.LockHelper;
import net.osmand.plus.helpers.WaypointHelper;
import net.osmand.plus.inapp.InAppPurchaseHelperImpl;
@ -45,6 +45,7 @@ import net.osmand.plus.mapmarkers.MapMarkersHelper;
import net.osmand.plus.monitoring.LiveMonitoringHelper;
import net.osmand.plus.monitoring.OsmandMonitoringPlugin;
import net.osmand.plus.onlinerouting.OnlineRoutingHelper;
import net.osmand.plus.openplacereviews.OprAuthHelper;
import net.osmand.plus.osmedit.oauth.OsmOAuthHelper;
import net.osmand.plus.poi.PoiFiltersHelper;
import net.osmand.plus.quickaction.QuickActionRegistry;
@ -468,6 +469,7 @@ public class AppInitializer implements IProgress {
app.settingsHelper = startupInit(new SettingsHelper(app), SettingsHelper.class);
app.quickActionRegistry = startupInit(new QuickActionRegistry(app.getSettings()), QuickActionRegistry.class);
app.osmOAuthHelper = startupInit(new OsmOAuthHelper(app), OsmOAuthHelper.class);
app.oprAuthHelper = startupInit(new OprAuthHelper(app), OprAuthHelper.class);
app.onlineRoutingHelper = startupInit(new OnlineRoutingHelper(app), OnlineRoutingHelper.class);
initOpeningHoursParser();

View file

@ -344,8 +344,8 @@ public class OsmAndFormatter {
if (minperkm >= 10) {
return ((int) Math.round(minperkm)) + " " + mc.toShortString(ctx);
} else {
int mph10 = (int) Math.round(minperkm * 10f);
return (mph10 / 10f) + " " + mc.toShortString(ctx);
int seconds = Math.round(minperkm * 60);
return Algorithms.formatDuration(seconds, false) + " " + mc.toShortString(ctx);
}
} else if (mc == SpeedConstants.MINUTES_PER_MILE) {
if (metersperseconds < 0.111111111) {

View file

@ -68,6 +68,7 @@ import net.osmand.plus.mapmarkers.MapMarkersHelper;
import net.osmand.plus.measurementtool.MeasurementEditingContext;
import net.osmand.plus.monitoring.LiveMonitoringHelper;
import net.osmand.plus.onlinerouting.OnlineRoutingHelper;
import net.osmand.plus.openplacereviews.OprAuthHelper;
import net.osmand.plus.osmedit.oauth.OsmOAuthHelper;
import net.osmand.plus.poi.PoiFiltersHelper;
import net.osmand.plus.quickaction.QuickActionRegistry;
@ -159,6 +160,7 @@ public class OsmandApplication extends MultiDexApplication {
GpxDbHelper gpxDbHelper;
QuickActionRegistry quickActionRegistry;
OsmOAuthHelper osmOAuthHelper;
OprAuthHelper oprAuthHelper;
MeasurementEditingContext measurementEditingContext;
OnlineRoutingHelper onlineRoutingHelper;
@ -394,6 +396,10 @@ public class OsmandApplication extends MultiDexApplication {
return osmOAuthHelper;
}
public OprAuthHelper getOprAuthHelper() {
return oprAuthHelper;
}
public synchronized DownloadIndexesThread getDownloadThread() {
if (downloadIndexesThread == null) {
downloadIndexesThread = new DownloadIndexesThread(this);

View file

@ -35,9 +35,12 @@ import net.osmand.plus.dialogs.PluginInstalledBottomSheetDialog;
import net.osmand.plus.download.IndexItem;
import net.osmand.plus.mapcontextmenu.MenuBuilder;
import net.osmand.plus.mapcontextmenu.MenuController;
import net.osmand.plus.mapcontextmenu.builders.cards.ImageCard;
import net.osmand.plus.mapcontextmenu.builders.cards.ImageCard.GetImageCardsTask.GetImageCardsListener;
import net.osmand.plus.mapillary.MapillaryPlugin;
import net.osmand.plus.monitoring.OsmandMonitoringPlugin;
import net.osmand.plus.myplaces.FavoritesActivity;
import net.osmand.plus.openplacereviews.OpenPlaceReviewsPlugin;
import net.osmand.plus.openseamapsplugin.NauticalMapsPlugin;
import net.osmand.plus.osmedit.OsmEditingPlugin;
import net.osmand.plus.parkingpoint.ParkingPositionPlugin;
@ -66,6 +69,7 @@ import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
public abstract class OsmandPlugin {
@ -133,7 +137,7 @@ public abstract class OsmandPlugin {
public boolean init(@NonNull OsmandApplication app, @Nullable Activity activity) {
if (activity != null) {
// called from UI
for (ApplicationMode appMode: getAddedAppModes()) {
for (ApplicationMode appMode : getAddedAppModes()) {
ApplicationMode.changeProfileAvailability(appMode, true, app);
}
}
@ -208,6 +212,16 @@ public abstract class OsmandPlugin {
return Collections.emptyList();
}
protected List<ImageCard> getContextMenuImageCards(@NonNull Map<String, String> params,
@Nullable Map<String, String> additionalParams,
@Nullable GetImageCardsListener listener) {
return Collections.emptyList();
}
protected ImageCard createContextMenuImageCard(@NonNull JSONObject imageObject) {
return null;
}
/**
* Plugin was installed
*/
@ -266,9 +280,9 @@ public abstract class OsmandPlugin {
allPlugins.clear();
enableHiddenPlugin(app, enabledPlugins, new MapillaryPlugin(app));
enableHiddenPlugin(app, enabledPlugins, new WikipediaPlugin(app));
allPlugins.add(new MapillaryPlugin(app));
allPlugins.add(new OsmandRasterMapsPlugin(app));
allPlugins.add(new OsmandMonitoringPlugin(app));
checkMarketPlugin(app, enabledPlugins, new SRTMPlugin(app));
@ -282,6 +296,7 @@ public abstract class OsmandPlugin {
checkMarketPlugin(app, enabledPlugins, new ParkingPositionPlugin(app));
allPlugins.add(new AccessibilityPlugin(app));
allPlugins.add(new OsmEditingPlugin(app));
allPlugins.add(new OpenPlaceReviewsPlugin(app));
allPlugins.add(new OsmandDevelopmentPlugin(app));
loadCustomPlugins(app);
@ -734,7 +749,6 @@ public abstract class OsmandPlugin {
return l;
}
public static void onMapActivityCreate(MapActivity activity) {
for (OsmandPlugin plugin : getEnabledPlugins()) {
plugin.mapActivityCreate(activity);
@ -868,6 +882,23 @@ public abstract class OsmandPlugin {
return collection;
}
public static void populateContextMenuImageCards(@NonNull List<ImageCard> imageCards, @NonNull Map<String, String> params,
@Nullable Map<String, String> additionalParams, @Nullable GetImageCardsListener listener) {
for (OsmandPlugin plugin : getEnabledPlugins()) {
imageCards.addAll(plugin.getContextMenuImageCards(params, additionalParams, listener));
}
}
public static ImageCard createImageCardForJson(@NonNull JSONObject imageObject) {
for (OsmandPlugin plugin : getEnabledPlugins()) {
ImageCard imageCard = plugin.createContextMenuImageCard(imageObject);
if (imageCard != null) {
return imageCard;
}
}
return null;
}
public static boolean isPackageInstalled(String packageInfo, Context ctx) {
if (packageInfo == null) {
return false;

View file

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

View file

@ -10,6 +10,7 @@ import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.text.Html;
import android.text.Spanned;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
@ -88,6 +89,8 @@ public class FavoritesTreeFragment extends OsmandExpandableListFragment implemen
public static final int IMPORT_FAVOURITES_ID = 7;
public static final String GROUP_EXPANDED_POSTFIX = "_group_expanded";
private static final int MAX_POINTS_IN_DESCRIPTION = 100;
private FavouritesAdapter favouritesAdapter;
private FavouritesDbHelper helper;
@ -606,29 +609,39 @@ public class FavoritesTreeFragment extends OsmandExpandableListFragment implemen
}
}
private StringBuilder generateHtmlPrint(List<FavoriteGroup> groups) {
private String generateHtmlPrint(List<FavoriteGroup> groups) {
StringBuilder html = new StringBuilder();
html.append("<h1>My Favorites</h1>");
int addedPoints = 0;
for (FavoriteGroup group : groups) {
html.append("<h3>" + group.getDisplayName(app) + "</h3>");
html.append("<h3>").append(group.getDisplayName(app)).append("</h3>");
for (FavouritePoint fp : group.getPoints()) {
String url = "geo:" + ((float) fp.getLatitude()) + "," + ((float) fp.getLongitude()) + "?m=" + fp.getName();
html.append("<p>" + fp.getDisplayName(app) + " - " + "<a href=\"" + url + "\">geo:"
+ ((float) fp.getLatitude()) + "," + ((float) fp.getLongitude()) + "</a><br>");
if (fp.isAddressSpecified()) {
html.append(": " + fp.getAddress());
html.append("<br>");
if (addedPoints >= MAX_POINTS_IN_DESCRIPTION) {
break;
}
if (!Algorithms.isEmpty(fp.getDescription())) {
html.append(": " + fp.getDescription());
}
html.append("</p>");
float lat = (float) fp.getLatitude();
float lon = (float) fp.getLongitude();
String url = "geo:" + lat + "," + lon + "?m=" + fp.getName();
html.append("<p>")
.append(fp.getDisplayName(app))
.append(" - <a href=\"")
.append(url)
.append("\">geo:")
.append(lat).append(",").append(lon)
.append("</a><br></p>");
addedPoints++;
}
if (addedPoints >= MAX_POINTS_IN_DESCRIPTION) {
html.append("<p>...</p>");
break;
}
}
return html;
return html.toString();
}
private void shareFavourites() {
if (favouritesAdapter.isEmpty()) {
Toast.makeText(getActivity(), R.string.no_fav_to_save, Toast.LENGTH_LONG).show();
@ -646,6 +659,7 @@ public class FavoritesTreeFragment extends OsmandExpandableListFragment implemen
File src = null;
File dst = null;
Spanned descriptionOfPoints;
@Override
protected void onPreExecute() {
@ -662,9 +676,15 @@ public class FavoritesTreeFragment extends OsmandExpandableListFragment implemen
@Override
protected Void doInBackground(Void... params) {
List<FavoriteGroup> groups;
if (group != null) {
helper.saveFile(group.getPoints(), dst);
groups = new ArrayList<>();
groups.add(group);
} else {
groups = getMyApplication().getFavorites().getFavoriteGroups();
}
descriptionOfPoints = Html.fromHtml(generateHtmlPrint(groups));
return null;
}
@ -680,19 +700,12 @@ public class FavoritesTreeFragment extends OsmandExpandableListFragment implemen
Algorithms.fileCopy(src, dst);
}
final Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
List<FavoriteGroup> groups;
if (group != null) {
groups = new ArrayList<>();
groups.add(group);
} else {
groups = getMyApplication().getFavorites().getFavoriteGroups();
}
sendIntent.putExtra(Intent.EXTRA_TEXT, Html.fromHtml(generateHtmlPrint(groups).toString()));
sendIntent.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.share_fav_subject));
sendIntent.putExtra(Intent.EXTRA_STREAM, AndroidUtils.getUriForFile(getMyApplication(), dst));
sendIntent.setType("text/plain");
sendIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
sendIntent.setAction(Intent.ACTION_SEND)
.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.share_fav_subject))
.putExtra(Intent.EXTRA_TEXT, descriptionOfPoints)
.putExtra(Intent.EXTRA_STREAM, AndroidUtils.getUriForFile(getMyApplication(), dst))
.setType("text/plain")
.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(sendIntent);
} catch (IOException e) {
Toast.makeText(getActivity(), "Error sharing favorites: " + e.getMessage(), Toast.LENGTH_SHORT).show();

View file

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

View file

@ -38,10 +38,10 @@ import java.util.Locale;
import java.util.Map;
public class SavingTrackHelper extends SQLiteOpenHelper {
public final static String DATABASE_NAME = "tracks"; //$NON-NLS-1$
public final static int DATABASE_VERSION = 6;
public final static int DATABASE_VERSION = 7;
public final static String TRACK_NAME = "track"; //$NON-NLS-1$
public final static String TRACK_COL_DATE = "date"; //$NON-NLS-1$
public final static String TRACK_COL_LAT = "lat"; //$NON-NLS-1$
@ -50,7 +50,7 @@ public class SavingTrackHelper extends SQLiteOpenHelper {
public final static String TRACK_COL_SPEED = "speed"; //$NON-NLS-1$
public final static String TRACK_COL_HDOP = "hdop"; //$NON-NLS-1$
public final static String TRACK_COL_HEADING = "heading"; //$NON-NLS-1$
public final static String POINT_NAME = "point"; //$NON-NLS-1$
public final static String POINT_COL_DATE = "date"; //$NON-NLS-1$
public final static String POINT_COL_LAT = "lat"; //$NON-NLS-1$
@ -59,7 +59,9 @@ public class SavingTrackHelper extends SQLiteOpenHelper {
public final static String POINT_COL_CATEGORY = "category"; //$NON-NLS-1$
public final static String POINT_COL_DESCRIPTION = "description"; //$NON-NLS-1$
public final static String POINT_COL_COLOR = "color"; //$NON-NLS-1$
public final static String POINT_COL_ICON = "icon"; //$NON-NLS-1$
public final static String POINT_COL_BACKGROUND = "background"; //$NON-NLS-1$
public final static float NO_HEADING = -1.0f;
public final static Log log = PlatformUtil.getLog(SavingTrackHelper.class);
@ -76,8 +78,8 @@ public class SavingTrackHelper extends SQLiteOpenHelper {
private SelectedGpxFile currentTrack;
private int points;
private int trkPoints = 0;
public SavingTrackHelper(OsmandApplication ctx){
public SavingTrackHelper(OsmandApplication ctx) {
super(ctx, DATABASE_NAME, null, DATABASE_VERSION);
this.ctx = ctx;
this.currentTrack = new SelectedGpxFile();
@ -88,11 +90,14 @@ public class SavingTrackHelper extends SQLiteOpenHelper {
prepareCurrentTrackForRecording();
updateScript = "INSERT INTO " + TRACK_NAME + " (" + TRACK_COL_LAT + ", " + TRACK_COL_LON + ", "
+ TRACK_COL_ALTITUDE + ", " + TRACK_COL_SPEED + ", " + TRACK_COL_HDOP + ", "
+ TRACK_COL_DATE + ", " + TRACK_COL_HEADING + ")"
+ TRACK_COL_ALTITUDE + ", " + TRACK_COL_SPEED + ", " + TRACK_COL_HDOP + ", "
+ TRACK_COL_DATE + ", " + TRACK_COL_HEADING + ")"
+ " VALUES (?, ?, ?, ?, ?, ?, ?)"; //$NON-NLS-1$ //$NON-NLS-2$
insertPointsScript = "INSERT INTO " + POINT_NAME + " VALUES (?, ?, ?, ?, ?, ?, ?)"; //$NON-NLS-1$ //$NON-NLS-2$
insertPointsScript = "INSERT INTO " + POINT_NAME + " (" + POINT_COL_LAT + ", " + POINT_COL_LON + ", "
+ POINT_COL_DATE + ", " + POINT_COL_DESCRIPTION + ", " + POINT_COL_NAME + ", "
+ POINT_COL_CATEGORY + ", " + POINT_COL_COLOR + ", " + POINT_COL_ICON + ", "
+ POINT_COL_BACKGROUND + ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"; //$NON-NLS-1$ //$NON-NLS-2$
}
@Override
@ -100,19 +105,19 @@ public class SavingTrackHelper extends SQLiteOpenHelper {
createTableForTrack(db);
createTableForPoints(db);
}
private void createTableForTrack(SQLiteDatabase db){
private void createTableForTrack(SQLiteDatabase db) {
db.execSQL("CREATE TABLE " + TRACK_NAME + " (" + TRACK_COL_LAT + " double, " + TRACK_COL_LON + " double, " //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ TRACK_COL_ALTITUDE + " double, " + TRACK_COL_SPEED + " double, " //$NON-NLS-1$ //$NON-NLS-2$
+ TRACK_COL_HDOP + " double, " + TRACK_COL_DATE + " long, "
+ TRACK_COL_HEADING + " float )"); //$NON-NLS-1$ //$NON-NLS-2$
}
private void createTableForPoints(SQLiteDatabase db){
private void createTableForPoints(SQLiteDatabase db) {
try {
db.execSQL("CREATE TABLE " + POINT_NAME + " (" + POINT_COL_LAT + " double, " + POINT_COL_LON + " double, " //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ POINT_COL_DATE + " long, " + POINT_COL_DESCRIPTION + " text, " + POINT_COL_NAME + " text, "
+ POINT_COL_CATEGORY + " text, " + POINT_COL_COLOR + " long" + ")"); //$NON-NLS-1$ //$NON-NLS-2$
+ POINT_COL_CATEGORY + " text, " + POINT_COL_COLOR + " long, " + POINT_COL_ICON + " text, " + POINT_COL_BACKGROUND + " text )"); //$NON-NLS-1$ //$NON-NLS-2$
} catch (RuntimeException e) {
// ignore if already exists
}
@ -120,25 +125,29 @@ public class SavingTrackHelper extends SQLiteOpenHelper {
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if(oldVersion < 2){
if (oldVersion < 2) {
createTableForPoints(db);
}
if(oldVersion < 3){
if (oldVersion < 3) {
db.execSQL("ALTER TABLE " + TRACK_NAME + " ADD " + TRACK_COL_HDOP + " double");
}
if(oldVersion < 4){
db.execSQL("ALTER TABLE " + POINT_NAME + " ADD " + POINT_COL_NAME + " text");
db.execSQL("ALTER TABLE " + POINT_NAME + " ADD " + POINT_COL_CATEGORY + " text");
if (oldVersion < 4) {
db.execSQL("ALTER TABLE " + POINT_NAME + " ADD " + POINT_COL_NAME + " text");
db.execSQL("ALTER TABLE " + POINT_NAME + " ADD " + POINT_COL_CATEGORY + " text");
}
if(oldVersion < 5){
db.execSQL("ALTER TABLE " + POINT_NAME + " ADD " + POINT_COL_COLOR + " long");
if (oldVersion < 5) {
db.execSQL("ALTER TABLE " + POINT_NAME + " ADD " + POINT_COL_COLOR + " long");
}
if(oldVersion < 6){
db.execSQL("ALTER TABLE " + TRACK_NAME + " ADD " + TRACK_COL_HEADING + " float");
if (oldVersion < 6) {
db.execSQL("ALTER TABLE " + TRACK_NAME + " ADD " + TRACK_COL_HEADING + " float");
}
if (oldVersion < 7) {
db.execSQL("ALTER TABLE " + POINT_NAME + " ADD " + POINT_COL_ICON + " text");
db.execSQL("ALTER TABLE " + POINT_NAME + " ADD " + POINT_COL_BACKGROUND + " text");
}
}
public long getLastTrackPointTime() {
long res = 0;
try {
@ -146,7 +155,7 @@ public class SavingTrackHelper extends SQLiteOpenHelper {
if (db != null) {
try {
Cursor query = db.rawQuery("SELECT " + TRACK_COL_DATE + " FROM " + TRACK_NAME + " ORDER BY " + TRACK_COL_DATE + " DESC", null); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
if(query.moveToFirst()) {
if (query.moveToFirst()) {
res = query.getLong(0);
}
query.close();
@ -154,11 +163,11 @@ public class SavingTrackHelper extends SQLiteOpenHelper {
db.close();
}
}
} catch(RuntimeException e) {
} catch (RuntimeException e) {
}
return res;
}
public synchronized boolean hasDataToSave() {
try {
SQLiteDatabase db = getWritableDatabase();
@ -172,11 +181,11 @@ public class SavingTrackHelper extends SQLiteOpenHelper {
}
q = db.query(false, POINT_NAME, new String[]{POINT_COL_LAT, POINT_COL_LON}, null, null, null, null, null, null);
has = q.moveToFirst();
while(has) {
if(q.getDouble(0) != 0 || q.getDouble(1) != 0) {
while (has) {
if (q.getDouble(0) != 0 || q.getDouble(1) != 0) {
break;
}
if(!q.moveToNext()) {
if (!q.moveToNext()) {
has = false;
break;
}
@ -189,7 +198,7 @@ public class SavingTrackHelper extends SQLiteOpenHelper {
db.close();
}
}
} catch(RuntimeException e) {
} catch (RuntimeException e) {
return false;
}
@ -294,7 +303,8 @@ public class SavingTrackHelper extends SQLiteOpenHelper {
private void collectDBPoints(SQLiteDatabase db, Map<String, GPXFile> dataTracks) {
Cursor query = db.rawQuery("SELECT " + POINT_COL_LAT + "," + POINT_COL_LON + "," + POINT_COL_DATE + "," //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ POINT_COL_DESCRIPTION + "," + POINT_COL_NAME + "," + POINT_COL_CATEGORY + "," + POINT_COL_COLOR + " FROM " + POINT_NAME+" ORDER BY " + POINT_COL_DATE +" ASC", null); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ POINT_COL_DESCRIPTION + "," + POINT_COL_NAME + "," + POINT_COL_CATEGORY + "," + POINT_COL_COLOR + ","
+ POINT_COL_ICON + "," + POINT_COL_BACKGROUND + " FROM " + POINT_NAME + " ORDER BY " + POINT_COL_DATE + " ASC", null); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
if (query.moveToFirst()) {
do {
WptPt pt = new WptPt();
@ -309,18 +319,20 @@ public class SavingTrackHelper extends SQLiteOpenHelper {
if (color != 0) {
pt.setColor(color);
}
pt.setIconName(query.getString(7));
pt.setBackgroundType(query.getString(8));
// check if name is extension (needed for audio/video plugin & josm integration)
if(pt.name != null && pt.name.length() > 4 && pt.name.charAt(pt.name.length() - 4) == '.') {
if (pt.name != null && pt.name.length() > 4 && pt.name.charAt(pt.name.length() - 4) == '.') {
pt.link = pt.name;
}
String date = DateFormat.format("yyyy-MM-dd", time).toString(); //$NON-NLS-1$
GPXFile gpx;
if (dataTracks.containsKey(date)) {
gpx = dataTracks.get(date);
} else {
gpx = new GPXFile(Version.getFullVersion(ctx));
gpx = new GPXFile(Version.getFullVersion(ctx));
dataTracks.put(date, gpx);
}
ctx.getSelectedGpxHelper().addPoint(pt, gpx);
@ -329,10 +341,10 @@ public class SavingTrackHelper extends SQLiteOpenHelper {
}
query.close();
}
private void collectDBTracks(SQLiteDatabase db, Map<String, GPXFile> dataTracks) {
Cursor query = db.rawQuery("SELECT " + TRACK_COL_LAT + "," + TRACK_COL_LON + "," + TRACK_COL_ALTITUDE + "," //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ TRACK_COL_SPEED + "," + TRACK_COL_HDOP + "," + TRACK_COL_DATE + "," + TRACK_COL_HEADING + " FROM " + TRACK_NAME +" ORDER BY " + TRACK_COL_DATE +" ASC", null); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ TRACK_COL_SPEED + "," + TRACK_COL_HDOP + "," + TRACK_COL_DATE + "," + TRACK_COL_HEADING + " FROM " + TRACK_NAME + " ORDER BY " + TRACK_COL_DATE + " ASC", null); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
long previousTime = 0;
long previousInterval = 0;
TrkSegment segment = null;
@ -351,14 +363,14 @@ public class SavingTrackHelper extends SQLiteOpenHelper {
pt.heading = heading == NO_HEADING ? Float.NaN : heading;
long currentInterval = Math.abs(time - previousTime);
boolean newInterval = pt.lat == 0 && pt.lon == 0;
if (track != null && !newInterval && (!ctx.getSettings().AUTO_SPLIT_RECORDING.get() || currentInterval < 6 * 60 * 1000 || currentInterval < 10 * previousInterval)) {
// 6 minute - same segment
segment.points.add(pt);
} else if (track != null && (ctx.getSettings().AUTO_SPLIT_RECORDING.get() && currentInterval < 2 * 60 * 60 * 1000)) {
// 2 hour - same track
segment = new TrkSegment();
if(!newInterval) {
if (!newInterval) {
segment.points.add(pt);
}
track.segments.add(segment);
@ -367,10 +379,10 @@ public class SavingTrackHelper extends SQLiteOpenHelper {
track = new Track();
segment = new TrkSegment();
track.segments.add(segment);
if(!newInterval) {
if (!newInterval) {
segment.points.add(pt);
}
String date = new SimpleDateFormat("yyyy-MM-dd", Locale.US).format(new Date(time));; //$NON-NLS-1$
String date = new SimpleDateFormat("yyyy-MM-dd", Locale.US).format(new Date(time)); //$NON-NLS-1$
if (dataTracks.containsKey(date)) {
GPXFile gpx = dataTracks.get(date);
gpx.tracks.add(track);
@ -411,14 +423,14 @@ public class SavingTrackHelper extends SQLiteOpenHelper {
dataTracks.remove(date);
}
}
public void startNewSegment() {
lastTimeUpdated = 0;
lastPoint = null;
execWithClose(updateScript, new Object[] { 0, 0, 0, 0, 0, System.currentTimeMillis(), NO_HEADING});
execWithClose(updateScript, new Object[]{0, 0, 0, 0, 0, System.currentTimeMillis(), NO_HEADING});
addTrackPoint(null, true, System.currentTimeMillis());
}
public void updateLocation(net.osmand.Location location, Float heading) {
// use because there is a bug on some devices with location.getTime()
long locationTime = System.currentTimeMillis();
@ -459,12 +471,12 @@ public class SavingTrackHelper extends SQLiteOpenHelper {
ctx.getNotificationHelper().refreshNotification(NotificationType.GPX);
}
}
public void insertData(double lat, double lon, double alt, double speed, double hdop, long time, float heading,
OsmandSettings settings) {
OsmandSettings settings) {
// * 1000 in next line seems to be wrong with new IntervalChooseDialog
// if (time - lastTimeUpdated > settings.SAVE_TRACK_INTERVAL.get() * 1000) {
execWithClose(updateScript, new Object[] { lat, lon, alt, speed, hdop, time, heading });
execWithClose(updateScript, new Object[]{lat, lon, alt, speed, hdop, time, heading});
boolean newSegment = false;
if (lastPoint == null || (time - lastTimeUpdated) > 180 * 1000) {
lastPoint = new LatLon(lat, lon);
@ -485,7 +497,7 @@ public class SavingTrackHelper extends SQLiteOpenHelper {
addTrackPoint(pt, newSegment, time);
trkPoints++;
}
private void addTrackPoint(WptPt pt, boolean newSegment, long time) {
List<TrkSegment> points = currentTrack.getModifiablePointsToDisplay();
Track track = currentTrack.getModifiableGpxFile().tracks.get(0);
@ -511,12 +523,12 @@ public class SavingTrackHelper extends SQLiteOpenHelper {
}
public WptPt insertPointData(double lat, double lon, long time, String description, String name, String category,
int color) {
int color) {
return insertPointData(lat, lon, time, description, name, category, color, null, null);
}
public WptPt insertPointData(double lat, double lon, long time, String description, String name, String category,
int color, String iconName, String backgroundName) {
int color, String iconName, String backgroundName) {
final WptPt pt = new WptPt(lat, lon, time, Double.NaN, 0, Double.NaN);
pt.name = name;
pt.category = category;
@ -529,7 +541,7 @@ public class SavingTrackHelper extends SQLiteOpenHelper {
ctx.getSelectedGpxHelper().addPoint(pt, currentTrack.getModifiableGpxFile());
currentTrack.getModifiableGpxFile().modifiedTime = time;
points++;
execWithClose(insertPointsScript, new Object[] { lat, lon, time, description, name, category, color });
execWithClose(insertPointsScript, new Object[]{lat, lon, time, description, name, category, color, iconName, backgroundName});
return pt;
}
@ -538,7 +550,7 @@ public class SavingTrackHelper extends SQLiteOpenHelper {
}
public void updatePointData(WptPt pt, double lat, double lon, long time, String description, String name,
String category, int color, String iconName, String iconBackground) {
String category, int color, String iconName, String iconBackground) {
currentTrack.getModifiableGpxFile().modifiedTime = time;
List<Object> params = new ArrayList<>();
@ -549,6 +561,8 @@ public class SavingTrackHelper extends SQLiteOpenHelper {
params.add(name);
params.add(category);
params.add(color);
params.add(iconName);
params.add(iconBackground);
params.add(pt.getLatitude());
params.add(pt.getLongitude());
@ -563,7 +577,9 @@ public class SavingTrackHelper extends SQLiteOpenHelper {
+ POINT_COL_DESCRIPTION + "=?, "
+ POINT_COL_NAME + "=?, "
+ POINT_COL_CATEGORY + "=?, "
+ POINT_COL_COLOR + "=? "
+ POINT_COL_COLOR + "=?, "
+ POINT_COL_ICON + "=?, "
+ POINT_COL_BACKGROUND + "=? "
+ "WHERE "
+ POINT_COL_LAT + "=? AND "
+ POINT_COL_LON + "=? AND "
@ -662,10 +678,10 @@ public class SavingTrackHelper extends SQLiteOpenHelper {
}
}
public void loadGpxFromDatabase(){
public void loadGpxFromDatabase() {
Map<String, GPXFile> files = collectRecordedData();
currentTrack.getModifiableGpxFile().tracks.clear();
for (Map.Entry<String, GPXFile> entry : files.entrySet()){
for (Map.Entry<String, GPXFile> entry : files.entrySet()) {
ctx.getSelectedGpxHelper().addPoints(entry.getValue().getPoints(), currentTrack.getModifiableGpxFile());
currentTrack.getModifiableGpxFile().tracks.addAll(entry.getValue().tracks);
}
@ -679,10 +695,10 @@ public class SavingTrackHelper extends SQLiteOpenHelper {
}
private void prepareCurrentTrackForRecording() {
if(currentTrack.getModifiableGpxFile().tracks.size() == 0) {
if (currentTrack.getModifiableGpxFile().tracks.size() == 0) {
currentTrack.getModifiableGpxFile().tracks.add(new Track());
}
while(currentTrack.getPointsToDisplay().size() < currentTrack.getModifiableGpxFile().tracks.size()) {
while (currentTrack.getPointsToDisplay().size() < currentTrack.getModifiableGpxFile().tracks.size()) {
TrkSegment trkSegment = new TrkSegment();
currentTrack.getModifiablePointsToDisplay().add(trkSegment);
}
@ -705,7 +721,7 @@ public class SavingTrackHelper extends SQLiteOpenHelper {
public int getPoints() {
return points;
}
public int getTrkPoints() {
return trkPoints;
}
@ -717,11 +733,11 @@ public class SavingTrackHelper extends SQLiteOpenHelper {
public GPXFile getCurrentGpx() {
return currentTrack.getGpxFile();
}
public SelectedGpxFile getCurrentTrack() {
return currentTrack;
}
public class SaveGpxResult {
public SaveGpxResult(List<String> warnings, List<String> filenames) {

View file

@ -143,8 +143,8 @@ public class OsmandDevelopmentPlugin extends OsmandPlugin {
@Override
public void disable(OsmandApplication app) {
if (app.getSettings().USE_DEV_URL.get()) {
app.getSettings().USE_DEV_URL.set(false);
if (app.getSettings().OSM_USE_DEV_URL.get()) {
app.getSettings().OSM_USE_DEV_URL.set(false);
app.getOsmOAuthHelper().resetAuthorization();
}
super.disable(app);

View file

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

View file

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

View file

@ -22,6 +22,7 @@ import net.osmand.plus.mapmarkers.MapMarkersDialogFragment;
import net.osmand.plus.mapmarkers.MapMarkersGroup;
import net.osmand.plus.mapsource.EditMapSourceDialogFragment;
import net.osmand.plus.openplacereviews.OPRConstants;
import net.osmand.plus.openplacereviews.OprAuthHelper.OprAuthorizationListener;
import net.osmand.plus.search.QuickSearchDialogFragment;
import net.osmand.plus.settings.backend.ApplicationMode;
import net.osmand.plus.settings.backend.OsmandSettings;
@ -326,8 +327,8 @@ public class IntentHelper {
if (uri.toString().startsWith(OPRConstants.OPR_OAUTH_PREFIX)) {
String token = uri.getQueryParameter("opr-token");
String username = uri.getQueryParameter("opr-nickname");
app.getSettings().OPR_ACCESS_TOKEN.set(token);
app.getSettings().OPR_USERNAME.set(username);
app.getOprAuthHelper().addListener(getOprAuthorizationListener());
app.getOprAuthHelper().authorize(token, username);
mapActivity.setIntent(null);
return true;
}
@ -348,6 +349,19 @@ public class IntentHelper {
};
}
private OprAuthorizationListener getOprAuthorizationListener() {
return new OprAuthorizationListener() {
@Override
public void authorizationCompleted() {
for (Fragment fragment : mapActivity.getSupportFragmentManager().getFragments()) {
if (fragment instanceof OprAuthorizationListener) {
((OprAuthorizationListener) fragment).authorizationCompleted();
}
}
}
};
}
private boolean handleSendText(Intent intent) {
String sharedText = intent.getStringExtra(Intent.EXTRA_TEXT);
if (!Algorithms.isEmpty(sharedText)) {

View file

@ -63,7 +63,7 @@ class GpxOrFavouritesImportTask extends BaseLoadAsyncTask<Void, Void, GPXFile> {
ZipEntry entry;
while ((entry = zis.getNextEntry()) != null) {
if (entry.getName().endsWith(ImportHelper.KML_SUFFIX)) {
InputStream gpxStream = convertKmlToGpxStream(is);
InputStream gpxStream = convertKmlToGpxStream(zis);
if (gpxStream != null) {
fileSize = gpxStream.available();
return GPXUtilities.loadGPXFile(gpxStream);

View file

@ -49,7 +49,7 @@ class KmzImportTask extends BaseLoadAsyncTask<Void, Void, GPXFile> {
ZipEntry entry;
while ((entry = zis.getNextEntry()) != null) {
if (entry.getName().endsWith(KML_SUFFIX)) {
InputStream gpxStream = convertKmlToGpxStream(is);
InputStream gpxStream = convertKmlToGpxStream(zis);
if (gpxStream != null) {
fileSize = gpxStream.available();
return GPXUtilities.loadGPXFile(gpxStream);

View file

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

View file

@ -58,6 +58,7 @@ import net.osmand.plus.ContextMenuItem;
import net.osmand.plus.LockableScrollView;
import net.osmand.plus.OsmAndFormatter;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.helpers.AndroidUiHelper;
import net.osmand.plus.settings.backend.MainContextMenuItemsSettings;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.R;
@ -1674,6 +1675,12 @@ public class MapContextMenuFragment extends BaseOsmAndFragment implements Downlo
line2MeasuredHeight = line2.getMeasuredHeight();
}
int customAddressLineHeight = 0;
View customAddressLine = view.findViewById(R.id.context_menu_custom_address_line);
if (customAddressLine.getVisibility() == View.VISIBLE) {
customAddressLineHeight = customAddressLine.getMeasuredHeight();
}
int line3Height = 0;
View line3Container = view.findViewById(R.id.additional_info_row_container);
if (line3Container.getVisibility() == View.VISIBLE) {
@ -1717,12 +1724,12 @@ public class MapContextMenuFragment extends BaseOsmAndFragment implements Downlo
titleHeight = line1.getMeasuredHeight() + line2MeasuredHeight;
}
newMenuTopViewHeight = menuTopViewHeightExcludingTitle + titleHeight
+ titleButtonHeight + downloadButtonsHeight
+ titleButtonHeight + customAddressLineHeight + downloadButtonsHeight
+ titleBottomButtonHeight + additionalButtonsHeight + titleProgressHeight + line3Height;
dy = Math.max(0, newMenuTopViewHeight - menuTopViewHeight
- (newMenuTopShadowAllHeight - menuTopShadowAllHeight));
} else {
menuTopViewHeightExcludingTitle = newMenuTopViewHeight - line1.getMeasuredHeight() - line2MeasuredHeight
menuTopViewHeightExcludingTitle = newMenuTopViewHeight - line1.getMeasuredHeight() - line2MeasuredHeight - customAddressLineHeight
- titleButtonHeight - downloadButtonsHeight - titleBottomButtonHeight - additionalButtonsHeight - titleProgressHeight - line3Height;
menuTitleTopBottomPadding = (line1.getMeasuredHeight() - line1.getLineCount() * line1.getLineHeight())
+ (line2MeasuredHeight - line2LineCount * line2LineHeight);
@ -1818,12 +1825,16 @@ public class MapContextMenuFragment extends BaseOsmAndFragment implements Downlo
line1.setText(menu.getTitleStr());
toolbarTextView.setText(menu.getTitleStr());
// Text line 2
LinearLayout line2layout = view.findViewById(R.id.context_menu_line2_layout);
TextView line2 = view.findViewById(R.id.context_menu_line2);
LinearLayout customAddressLine = view.findViewById(R.id.context_menu_custom_address_line);
customAddressLine.removeAllViews();
if (menu.hasCustomAddressLine()) {
line2layout.removeAllViews();
menu.buildCustomAddressLine(line2layout);
menu.buildCustomAddressLine(customAddressLine);
AndroidUiHelper.updateVisibility(line2, false);
AndroidUiHelper.updateVisibility(customAddressLine, true);
} else {
AndroidUiHelper.updateVisibility(line2, true);
AndroidUiHelper.updateVisibility(customAddressLine, false);
String typeStr = menu.getTypeStr();
String streetStr = menu.getStreetStr();
StringBuilder line2Str = new StringBuilder();

View file

@ -36,6 +36,7 @@ import androidx.core.content.ContextCompat;
import androidx.core.graphics.drawable.DrawableCompat;
import net.osmand.AndroidUtils;
import net.osmand.PlatformUtil;
import net.osmand.data.Amenity;
import net.osmand.data.LatLon;
import net.osmand.data.PointDescription;
@ -47,11 +48,12 @@ import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandPlugin;
import net.osmand.plus.R;
import net.osmand.plus.UiUtilities;
import net.osmand.plus.Version;
import net.osmand.plus.activities.ActivityResultListener;
import net.osmand.plus.activities.ActivityResultListener.OnActivityResultListener;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.helpers.AndroidUiHelper;
import net.osmand.plus.helpers.FontCache;
import net.osmand.plus.mapcontextmenu.UploadPhotosAsyncTask.UploadPhotosListener;
import net.osmand.plus.mapcontextmenu.builders.cards.AbstractCard;
import net.osmand.plus.mapcontextmenu.builders.cards.CardsRowBuilder;
import net.osmand.plus.mapcontextmenu.builders.cards.ImageCard;
@ -75,6 +77,10 @@ import net.osmand.plus.widgets.tools.ClickableSpanTouchListener;
import net.osmand.util.Algorithms;
import net.osmand.util.MapUtils;
import org.apache.commons.logging.Log;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
@ -87,6 +93,7 @@ import static net.osmand.plus.mapcontextmenu.builders.cards.ImageCard.GetImageCa
public class MenuBuilder {
private static final Log LOG = PlatformUtil.getLog(MenuBuilder.class);
private static final int PICK_IMAGE = 1231;
public static final float SHADOW_HEIGHT_TOP_DP = 17f;
public static final int TITLE_LIMIT = 60;
@ -131,16 +138,14 @@ public class MenuBuilder {
}
@Override
public void onPlaceIdAcquired(String[] placeId) {
public void onPlaceIdAcquired(final String[] placeId) {
MenuBuilder.this.placeId = placeId;
if (placeId.length < 2) {
app.runInUIThread(new Runnable() {
@Override
public void run() {
photoButton.setVisibility(View.GONE);
}
});
}
app.runInUIThread(new Runnable() {
@Override
public void run() {
AndroidUiHelper.updateVisibility(photoButton, placeId.length >= 2);
}
});
}
@Override
@ -158,6 +163,16 @@ public class MenuBuilder {
}
};
public void addImageCard(ImageCard card) {
if (onlinePhotoCards.size() == 1 && onlinePhotoCards.get(0) instanceof NoImagesCard) {
onlinePhotoCards.clear();
}
onlinePhotoCards.add(0, card);
if (onlinePhotoCardsRow != null) {
onlinePhotoCardsRow.setCards(onlinePhotoCards);
}
}
public interface CollapseExpandListener {
void onCollapseExpand(boolean collapsed);
}
@ -443,10 +458,7 @@ public class MenuBuilder {
}
}
});
//TODO This feature is under development
if (!Version.isDeveloperVersion(app)) {
view.setVisibility(View.GONE);
}
AndroidUiHelper.updateVisibility(view, false);
photoButton = view;
return view;
}
@ -481,7 +493,27 @@ public class MenuBuilder {
}
}
}
execute(new UploadPhotosAsyncTask(mapActivity, imagesUri, getLatLon(), placeId, getAdditionalCardParams(), imageCardListener));
UploadPhotosListener listener = new UploadPhotosListener() {
@Override
public void uploadPhotosSuccess(final String response) {
app.runInUIThread(new Runnable() {
@Override
public void run() {
if (AndroidUtils.isActivityNotDestroyed(mapActivity)) {
try {
ImageCard imageCard = OsmandPlugin.createImageCardForJson(new JSONObject(response));
if (imageCard != null) {
addImageCard(imageCard);
}
} catch (JSONException e) {
LOG.error(e);
}
}
}
});
}
};
execute(new UploadPhotosAsyncTask(mapActivity, imagesUri, placeId, listener));
}
}
}));

View file

@ -13,14 +13,11 @@ import androidx.fragment.app.FragmentManager;
import net.osmand.AndroidUtils;
import net.osmand.PlatformUtil;
import net.osmand.data.LatLon;
import net.osmand.osm.io.NetworkUtils;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.dialogs.UploadPhotoProgressBottomSheet;
import net.osmand.plus.mapcontextmenu.builders.cards.ImageCard.GetImageCardsTask;
import net.osmand.plus.mapcontextmenu.builders.cards.ImageCard.GetImageCardsTask.GetImageCardsListener;
import net.osmand.plus.openplacereviews.OPRConstants;
import net.osmand.plus.openplacereviews.OprStartFragment;
import net.osmand.plus.osmedit.opr.OpenDBAPI;
@ -34,8 +31,8 @@ import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class UploadPhotosAsyncTask extends AsyncTask<Void, Integer, Void> {
@ -45,24 +42,18 @@ public class UploadPhotosAsyncTask extends AsyncTask<Void, Integer, Void> {
private final OsmandApplication app;
private final WeakReference<MapActivity> activityRef;
private UploadPhotosListener listener;
private final OpenDBAPI openDBAPI = new OpenDBAPI();
private final LatLon latLon;
private final List<Uri> data;
private final String[] placeId;
private final Map<String, String> params;
private final GetImageCardsListener imageCardListener;
private final UploadPhotosListener listener;
private UploadPhotosProgressListener progressListener;
public UploadPhotosAsyncTask(MapActivity activity, List<Uri> data, LatLon latLon, String[] placeId,
Map<String, String> params, GetImageCardsListener imageCardListener) {
public UploadPhotosAsyncTask(MapActivity activity, List<Uri> data, String[] placeId, UploadPhotosListener listener) {
app = (OsmandApplication) activity.getApplicationContext();
activityRef = new WeakReference<>(activity);
this.data = data;
this.latLon = latLon;
this.params = params;
this.placeId = placeId;
this.imageCardListener = imageCardListener;
this.listener = listener;
}
@Override
@ -70,7 +61,7 @@ public class UploadPhotosAsyncTask extends AsyncTask<Void, Integer, Void> {
FragmentActivity activity = activityRef.get();
if (AndroidUtils.isActivityNotDestroyed(activity)) {
FragmentManager manager = activity.getSupportFragmentManager();
listener = UploadPhotoProgressBottomSheet.showInstance(manager, data.size(), new OnDismissListener() {
progressListener = UploadPhotoProgressBottomSheet.showInstance(manager, data.size(), new OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog) {
cancel(false);
@ -81,36 +72,40 @@ public class UploadPhotosAsyncTask extends AsyncTask<Void, Integer, Void> {
@Override
protected void onProgressUpdate(Integer... values) {
if (listener != null) {
listener.uploadPhotosProgressUpdate(values[0]);
if (progressListener != null) {
progressListener.uploadPhotosProgressUpdate(values[0]);
}
}
protected Void doInBackground(Void... uris) {
List<Uri> uploadedPhotoUris = new ArrayList<>();
for (int i = 0; i < data.size(); i++) {
if (isCancelled()) {
break;
}
Uri uri = data.get(i);
handleSelectedImage(uri);
publishProgress(i + 1);
if (handleSelectedImage(uri)) {
uploadedPhotoUris.add(uri);
publishProgress(uploadedPhotoUris.size());
}
}
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
if (listener != null) {
listener.uploadPhotosFinished();
if (progressListener != null) {
progressListener.uploadPhotosFinished();
}
}
private void handleSelectedImage(final Uri uri) {
private boolean handleSelectedImage(final Uri uri) {
boolean success = false;
InputStream inputStream = null;
try {
inputStream = app.getContentResolver().openInputStream(uri);
if (inputStream != null) {
uploadImageToPlace(inputStream);
success = uploadImageToPlace(inputStream);
}
} catch (Exception e) {
LOG.error(e);
@ -118,11 +113,13 @@ public class UploadPhotosAsyncTask extends AsyncTask<Void, Integer, Void> {
} finally {
Algorithms.closeStream(inputStream);
}
return success;
}
private void uploadImageToPlace(InputStream image) {
private boolean uploadImageToPlace(InputStream image) {
boolean success = false;
InputStream serverData = new ByteArrayInputStream(compressImageToJpeg(image));
final String baseUrl = OPRConstants.getBaseUrl(app);
String baseUrl = OPRConstants.getBaseUrl(app);
// all these should be constant
String url = baseUrl + "api/ipfs/image";
String response = NetworkUtils.sendPostDataRequest(url, "file", "compressed.jpeg", serverData);
@ -140,8 +137,6 @@ public class UploadPhotosAsyncTask extends AsyncTask<Void, Integer, Void> {
response, error);
if (res != 200) {
app.showToastMessage(error.toString());
} else {
//ok, continue
}
} catch (FailedVerificationException e) {
LOG.error(e);
@ -151,18 +146,16 @@ public class UploadPhotosAsyncTask extends AsyncTask<Void, Integer, Void> {
//image was uploaded but not added to blockchain
checkTokenAndShowScreen();
} else {
String str = app.getString(R.string.successfully_uploaded_pattern, 1, 1);
app.showToastMessage(str);
success = true;
//refresh the image
MapActivity activity = activityRef.get();
if (activity != null) {
MenuBuilder.execute(new GetImageCardsTask(activity, latLon, params, imageCardListener));
if (listener != null) {
listener.uploadPhotosSuccess(response);
}
}
} else {
checkTokenAndShowScreen();
}
return success;
}
//This method runs on non main thread
@ -209,12 +202,17 @@ public class UploadPhotosAsyncTask extends AsyncTask<Void, Integer, Void> {
return os.toByteArray();
}
public interface UploadPhotosListener {
public interface UploadPhotosProgressListener {
void uploadPhotosProgressUpdate(int progress);
void uploadPhotosFinished();
}
public interface UploadPhotosListener {
void uploadPhotosSuccess(String response);
}
}

View file

@ -19,17 +19,13 @@ import net.osmand.AndroidNetworkUtils;
import net.osmand.AndroidUtils;
import net.osmand.Location;
import net.osmand.PlatformUtil;
import net.osmand.data.Amenity;
import net.osmand.data.LatLon;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandPlugin;
import net.osmand.plus.R;
import net.osmand.plus.Version;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.mapcontextmenu.MenuBuilder;
import net.osmand.plus.mapillary.MapillaryContributeCard;
import net.osmand.plus.mapillary.MapillaryImageCard;
import net.osmand.plus.openplacereviews.OPRConstants;
import net.osmand.plus.wikimedia.WikiImageHelper;
import net.osmand.util.Algorithms;
import org.apache.commons.logging.Log;
@ -41,18 +37,17 @@ import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import static net.osmand.plus.mapillary.MapillaryPlugin.TYPE_MAPILLARY_CONTRIBUTE;
import static net.osmand.plus.mapillary.MapillaryPlugin.TYPE_MAPILLARY_PHOTO;
public abstract class ImageCard extends AbstractCard {
public static String TYPE_MAPILLARY_PHOTO = "mapillary-photo";
public static String TYPE_MAPILLARY_CONTRIBUTE = "mapillary-contribute";
private static final Log LOG = PlatformUtil.getLog(ImageCard.class);
protected String type;
@ -184,11 +179,7 @@ public abstract class ImageCard extends AbstractCard {
try {
if (imageObject.has("type")) {
String type = imageObject.getString("type");
if (TYPE_MAPILLARY_PHOTO.equals(type)) {
imageCard = new MapillaryImageCard(mapActivity, imageObject);
} else if (TYPE_MAPILLARY_CONTRIBUTE.equals(type)) {
imageCard = new MapillaryContributeCard(mapActivity, imageObject);
} else {
if (!TYPE_MAPILLARY_CONTRIBUTE.equals(type) && !TYPE_MAPILLARY_PHOTO.equals(type)) {
imageCard = new UrlImageCard(mapActivity, imageObject);
}
}
@ -198,14 +189,6 @@ public abstract class ImageCard extends AbstractCard {
return imageCard;
}
private static ImageCard createCardOpr(MapActivity mapActivity, JSONObject imageObject) {
ImageCard imageCard = null;
if (imageObject.has("cid")) {
imageCard = new IPFSImageCard(mapActivity, imageObject);
}
return imageCard;
}
public double getCa() {
return ca;
}
@ -410,28 +393,6 @@ public abstract class ImageCard extends AbstractCard {
}
}
private static String[] getIdFromResponse(String response) {
try {
JSONArray obj = new JSONObject(response).getJSONArray("objects");
JSONArray images = (JSONArray) ((JSONObject) obj.get(0)).get("id");
return toStringArray(images);
} catch (JSONException e) {
e.printStackTrace();
}
return new String[0];
}
private static String[] toStringArray(JSONArray array) {
if (array == null)
return null;
String[] arr = new String[array.length()];
for (int i = 0; i < arr.length; i++) {
arr[i] = array.optString(i);
}
return arr;
}
public static class GetImageCardsTask extends AsyncTask<Void, Void, List<ImageCard>> {
private MapActivity mapActivity;
@ -451,7 +412,7 @@ public abstract class ImageCard extends AbstractCard {
}
public GetImageCardsTask(@NonNull MapActivity mapActivity, LatLon latLon,
@Nullable Map<String, String> params, GetImageCardsListener listener) {
@Nullable Map<String, String> params, GetImageCardsListener listener) {
this.mapActivity = mapActivity;
this.app = mapActivity.getMyApplication();
this.latLon = latLon;
@ -460,23 +421,9 @@ public abstract class ImageCard extends AbstractCard {
}
@Override
protected List<ImageCard> doInBackground(Void... params) {
protected List<ImageCard> doInBackground(Void... voids) {
TrafficStats.setThreadStatsTag(GET_IMAGE_CARD_THREAD_ID);
List<ImageCard> result = new ArrayList<>();
Object o = mapActivity.getMapLayers().getContextMenuLayer().getSelectedObject();
if (o instanceof Amenity) {
Amenity am = (Amenity) o;
long amenityId = am.getId() >> 1;
String baseUrl = OPRConstants.getBaseUrl(app);
String url = baseUrl + "api/objects-by-index?type=opr.place&index=osmid&key=" + amenityId;
String response = AndroidNetworkUtils.sendRequest(app, url, Collections.<String, String>emptyMap(),
"Requesting location images...", false, false);
if (response != null) {
getPicturesForPlace(result, response);
String[] id = getIdFromResponse(response);
listener.onPlaceIdAcquired(id);
}
}
try {
final Map<String, String> pms = new LinkedHashMap<>();
pms.put("lat", "" + (float) latLon.getLatitude());
@ -493,19 +440,8 @@ public abstract class ImageCard extends AbstractCard {
if (!Algorithms.isEmpty(preferredLang)) {
pms.put("lang", preferredLang);
}
if (this.params != null) {
String wikidataId = this.params.get(Amenity.WIKIDATA);
if (wikidataId != null) {
this.params.remove(Amenity.WIKIDATA);
WikiImageHelper.addWikidataImageCards(mapActivity, wikidataId, result);
}
String wikimediaContent = this.params.get(Amenity.WIKIMEDIA_COMMONS);
if (wikimediaContent != null) {
this.params.remove(Amenity.WIKIMEDIA_COMMONS);
WikiImageHelper.addWikimediaImageCards(mapActivity, wikimediaContent, result);
}
pms.putAll(this.params);
}
OsmandPlugin.populateContextMenuImageCards(result, pms, params, listener);
String response = AndroidNetworkUtils.sendRequest(app, "https://osmand.net/api/cm_place", pms,
"Requesting location images...", false, false);
@ -517,7 +453,10 @@ public abstract class ImageCard extends AbstractCard {
try {
JSONObject imageObject = (JSONObject) images.get(i);
if (imageObject != JSONObject.NULL) {
ImageCard imageCard = ImageCard.createCard(mapActivity, imageObject);
ImageCard imageCard = OsmandPlugin.createImageCardForJson(imageObject);
if (imageCard == null) {
imageCard = ImageCard.createCard(mapActivity, imageObject);
}
if (imageCard != null) {
result.add(imageCard);
}
@ -537,36 +476,6 @@ public abstract class ImageCard extends AbstractCard {
return result;
}
private void getPicturesForPlace(List<ImageCard> result, String response) {
try {
if (!Algorithms.isEmpty(response)) {
JSONArray obj = new JSONObject(response).getJSONArray("objects");
JSONObject imagesWrapper = ((JSONObject) ((JSONObject) obj.get(0)).get("images"));
Iterator<String> it = imagesWrapper.keys();
while (it.hasNext()) {
JSONArray images = imagesWrapper.getJSONArray(it.next());
if (images.length() > 0) {
for (int i = 0; i < images.length(); i++) {
try {
JSONObject imageObject = (JSONObject) images.get(i);
if (imageObject != JSONObject.NULL) {
ImageCard imageCard = ImageCard.createCardOpr(mapActivity, imageObject);
if (imageCard != null) {
result.add(imageCard);
}
}
} catch (JSONException e) {
LOG.error(e);
}
}
}
}
}
} catch (Exception e) {
LOG.error(e);
}
}
@Override
protected void onPostExecute(List<ImageCard> cardList) {
result = cardList;

View file

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

View file

@ -17,27 +17,34 @@ import androidx.appcompat.widget.SwitchCompat;
import androidx.fragment.app.FragmentActivity;
import net.osmand.AndroidUtils;
import net.osmand.PlatformUtil;
import net.osmand.map.ITileSource;
import net.osmand.map.TileSourceManager;
import net.osmand.plus.settings.backend.ApplicationMode;
import net.osmand.plus.ContextMenuAdapter;
import net.osmand.plus.ContextMenuItem;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandPlugin;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.R;
import net.osmand.plus.Version;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.activities.MapActivityLayers;
import net.osmand.plus.base.BottomSheetDialogFragment;
import net.osmand.plus.dashboard.DashboardOnMap;
import net.osmand.plus.views.layers.MapInfoLayer;
import net.osmand.plus.mapcontextmenu.builders.cards.ImageCard;
import net.osmand.plus.openplacereviews.OpenPlaceReviewsPlugin;
import net.osmand.plus.settings.backend.ApplicationMode;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.views.MapTileLayer;
import net.osmand.plus.views.OsmandMapTileView;
import net.osmand.plus.views.layers.MapInfoLayer;
import net.osmand.plus.views.mapwidgets.MapWidgetRegistry.MapWidgetRegInfo;
import net.osmand.plus.views.mapwidgets.widgets.TextInfoWidget;
import net.osmand.util.Algorithms;
import org.apache.commons.logging.Log;
import org.json.JSONException;
import org.json.JSONObject;
import java.text.MessageFormat;
import java.util.List;
@ -47,11 +54,18 @@ import static net.osmand.plus.ContextMenuAdapter.makeDeleteAction;
public class MapillaryPlugin extends OsmandPlugin {
public static String TYPE_MAPILLARY_PHOTO = "mapillary-photo";
public static String TYPE_MAPILLARY_CONTRIBUTE = "mapillary-contribute";
public static final String ID = "osmand.mapillary";
private static final String MAPILLARY_PACKAGE_ID = "app.mapillary";
private static final Log LOG = PlatformUtil.getLog(OpenPlaceReviewsPlugin.class);
private OsmandSettings settings;
private MapActivity mapActivity;
private MapillaryRasterLayer rasterLayer;
private MapillaryVectorLayer vectorLayer;
private TextInfoWidget mapillaryControl;
@ -62,11 +76,6 @@ public class MapillaryPlugin extends OsmandPlugin {
settings = app.getSettings();
}
@Override
public boolean isVisible() {
return false;
}
@Override
public int getLogoResourceId() {
return R.drawable.ic_action_mapillary;
@ -228,6 +237,41 @@ public class MapillaryPlugin extends OsmandPlugin {
}
}
@Override
protected ImageCard createContextMenuImageCard(@NonNull JSONObject imageObject) {
ImageCard imageCard = null;
if (mapActivity != null) {
try {
if (imageObject.has("type")) {
String type = imageObject.getString("type");
if (TYPE_MAPILLARY_PHOTO.equals(type)) {
imageCard = new MapillaryImageCard(mapActivity, imageObject);
} else if (TYPE_MAPILLARY_CONTRIBUTE.equals(type)) {
imageCard = new MapillaryContributeCard(mapActivity, imageObject);
}
}
} catch (JSONException e) {
LOG.error(e);
}
}
return imageCard;
}
@Override
public void mapActivityResume(MapActivity activity) {
this.mapActivity = activity;
}
@Override
public void mapActivityResumeOnTop(MapActivity activity) {
this.mapActivity = activity;
}
@Override
public void mapActivityPause(MapActivity activity) {
this.mapActivity = null;
}
public static boolean openMapillary(FragmentActivity activity, String imageKey) {
boolean success = false;
OsmandApplication app = (OsmandApplication) activity.getApplication();

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,12 +1,16 @@
package net.osmand.plus.mapcontextmenu.builders.cards;
package net.osmand.plus.openplacereviews;
import android.view.View;
import androidx.core.content.ContextCompat;
import net.osmand.PlatformUtil;
import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.mapcontextmenu.builders.cards.ImageCard;
import net.osmand.util.Algorithms;
import org.apache.commons.logging.Log;
import org.json.JSONException;
import org.json.JSONObject;

View file

@ -1,9 +1,9 @@
package net.osmand.plus.openplacereviews;
import android.content.Context;
import androidx.annotation.NonNull;
import net.osmand.plus.R;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.osmedit.opr.OpenDBAPI;
public class OPRConstants {
@ -11,28 +11,27 @@ public class OPRConstants {
private static final String PURPOSE = OpenDBAPI.PURPOSE;
private static final String CALLBACK_URL = OPR_OAUTH_PREFIX + "://osmand_opr_auth";
public static String getBaseUrl(Context ctx) {
return ctx.getString(R.string.opr_base_url);
public static String getBaseUrl(@NonNull OsmandApplication app) {
return app.getSettings().getOprUrl();
}
public static String getLoginUrl(Context ctx) {
return getBaseUrl(ctx) + "login" + getQueryString(ctx);
public static String getLoginUrl(@NonNull OsmandApplication app) {
return getBaseUrl(app) + "login" + getQueryString();
}
public static String getRegisterUrl(Context ctx) {
return getBaseUrl(ctx) + "signup" + getQueryString(ctx);
public static String getRegisterUrl(@NonNull OsmandApplication app) {
return getBaseUrl(app) + "signup" + getQueryString();
}
public static String getQueryString(Context ctx) {
return "?" + getPurposeParam(ctx) + "&" + getCallbackParam(ctx);
public static String getQueryString() {
return "?" + getPurposeParam() + "&" + getCallbackParam();
}
public static String getPurposeParam(Context ctx) {
public static String getPurposeParam() {
return "purpose=" + PURPOSE;
}
public static String getCallbackParam(Context ctx) {
public static String getCallbackParam() {
return "callback=" + CALLBACK_URL;
}
}

View file

@ -0,0 +1,182 @@
package net.osmand.plus.openplacereviews;
import android.graphics.drawable.Drawable;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import net.osmand.AndroidNetworkUtils;
import net.osmand.PlatformUtil;
import net.osmand.data.Amenity;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandPlugin;
import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.mapcontextmenu.builders.cards.ImageCard;
import net.osmand.plus.mapcontextmenu.builders.cards.ImageCard.GetImageCardsTask.GetImageCardsListener;
import net.osmand.plus.settings.fragments.BaseSettingsFragment.SettingsScreenType;
import net.osmand.util.Algorithms;
import org.apache.commons.logging.Log;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
public class OpenPlaceReviewsPlugin extends OsmandPlugin {
private static final Log LOG = PlatformUtil.getLog(OpenPlaceReviewsPlugin.class);
private static final String ID = "osmand.openplacereviews";
private MapActivity mapActivity;
public OpenPlaceReviewsPlugin(OsmandApplication app) {
super(app);
}
@Override
public String getId() {
return ID;
}
@Override
public String getName() {
return app.getString(R.string.open_place_reviews);
}
@Override
public CharSequence getDescription() {
return app.getString(R.string.open_place_reviews_plugin_description);
}
@Override
public SettingsScreenType getSettingsScreenType() {
return SettingsScreenType.OPEN_PLACE_REVIEWS;
}
@Override
public int getLogoResourceId() {
return R.drawable.ic_img_logo_openplacereview;
}
@Override
public Drawable getAssetResourceImage() {
return app.getUIUtilities().getIcon(R.drawable.img_plugin_openplacereviews);
}
@Override
public void mapActivityResume(MapActivity activity) {
this.mapActivity = activity;
}
@Override
public void mapActivityResumeOnTop(MapActivity activity) {
this.mapActivity = activity;
}
@Override
public void mapActivityPause(MapActivity activity) {
this.mapActivity = null;
}
@Override
protected List<ImageCard> getContextMenuImageCards(@NonNull Map<String, String> params,
@Nullable Map<String, String> additionalParams,
@Nullable GetImageCardsListener listener) {
List<ImageCard> imageCards = new ArrayList<>();
if (mapActivity != null) {
Object object = mapActivity.getMapLayers().getContextMenuLayer().getSelectedObject();
if (object instanceof Amenity) {
Amenity am = (Amenity) object;
long amenityId = am.getId() >> 1;
String baseUrl = OPRConstants.getBaseUrl(app);
String url = baseUrl + "api/objects-by-index?type=opr.place&index=osmid&key=" + amenityId;
String response = AndroidNetworkUtils.sendRequest(app, url, Collections.<String, String>emptyMap(),
"Requesting location images...", false, false);
if (response != null) {
getPicturesForPlace(imageCards, response);
if (listener != null) {
listener.onPlaceIdAcquired(getIdFromResponse(response));
}
}
}
}
return imageCards;
}
private void getPicturesForPlace(List<ImageCard> result, String response) {
try {
if (!Algorithms.isEmpty(response)) {
JSONArray obj = new JSONObject(response).getJSONArray("objects");
JSONObject imagesWrapper = ((JSONObject) ((JSONObject) obj.get(0)).get("images"));
Iterator<String> it = imagesWrapper.keys();
while (it.hasNext()) {
JSONArray images = imagesWrapper.getJSONArray(it.next());
if (images.length() > 0) {
for (int i = 0; i < images.length(); i++) {
try {
JSONObject imageObject = (JSONObject) images.get(i);
if (imageObject != JSONObject.NULL) {
ImageCard imageCard = createCardOpr(mapActivity, imageObject);
if (imageCard != null) {
result.add(imageCard);
}
}
} catch (JSONException e) {
LOG.error(e);
}
}
}
}
}
} catch (Exception e) {
LOG.error(e);
}
}
public static ImageCard createCardOpr(MapActivity mapActivity, JSONObject imageObject) {
ImageCard imageCard = null;
if (imageObject.has("cid")) {
imageCard = new IPFSImageCard(mapActivity, imageObject);
}
return imageCard;
}
private static String[] getIdFromResponse(String response) {
try {
JSONArray obj = new JSONObject(response).getJSONArray("objects");
JSONArray images = (JSONArray) ((JSONObject) obj.get(0)).get("id");
return toStringArray(images);
} catch (JSONException e) {
e.printStackTrace();
}
return new String[0];
}
private static String[] toStringArray(JSONArray array) {
if (array == null)
return null;
String[] arr = new String[array.length()];
for (int i = 0; i < arr.length; i++) {
arr[i] = array.optString(i);
}
return arr;
}
@Override
public void disable(OsmandApplication app) {
if (app.getSettings().OPR_USE_DEV_URL.get()) {
app.getSettings().OPR_USE_DEV_URL.set(false);
app.getOprAuthHelper().resetAuthorization();
}
super.disable(app);
}
}

View file

@ -0,0 +1,95 @@
package net.osmand.plus.openplacereviews;
import android.os.AsyncTask;
import androidx.annotation.NonNull;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.osmedit.opr.OpenDBAPI;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.util.Algorithms;
import java.util.HashSet;
import java.util.Set;
public class OprAuthHelper {
private final OsmandApplication app;
private final OsmandSettings settings;
private final Set<OprAuthorizationListener> listeners = new HashSet<>();
public OprAuthHelper(@NonNull OsmandApplication app) {
this.app = app;
settings = app.getSettings();
}
public void addListener(OprAuthorizationListener listener) {
listeners.add(listener);
}
public void removeListener(OprAuthorizationListener listener) {
listeners.remove(listener);
}
public void resetAuthorization() {
if (isLoginExists()) {
settings.OPR_USERNAME.resetToDefault();
settings.OPR_ACCESS_TOKEN.resetToDefault();
settings.OPR_BLOCKCHAIN_NAME.resetToDefault();
}
}
public boolean isLoginExists() {
return !Algorithms.isEmpty(settings.OPR_USERNAME.get())
&& !Algorithms.isEmpty(settings.OPR_BLOCKCHAIN_NAME.get())
&& !Algorithms.isEmpty(settings.OPR_ACCESS_TOKEN.get());
}
private void notifyAndRemoveListeners() {
for (OprAuthorizationListener listener : listeners) {
listener.authorizationCompleted();
}
listeners.clear();
}
public void authorize(final String token, final String username) {
CheckOprAuthTask checkOprAuthTask = new CheckOprAuthTask(app, token, username);
checkOprAuthTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void) null);
}
private static class CheckOprAuthTask extends AsyncTask<Void, Void, Boolean> {
private final OsmandApplication app;
private final OpenDBAPI openDBAPI = new OpenDBAPI();
private final String token;
private final String username;
private CheckOprAuthTask(@NonNull OsmandApplication app, String token, String username) {
this.app = app;
this.token = token;
this.username = username;
}
@Override
protected Boolean doInBackground(Void... params) {
String baseUrl = OPRConstants.getBaseUrl(app);
return openDBAPI.checkPrivateKeyValid(app, baseUrl, username, token);
}
@Override
protected void onPostExecute(Boolean result) {
if (result) {
app.getSettings().OPR_ACCESS_TOKEN.set(token);
app.getSettings().OPR_USERNAME.set(username);
} else {
app.getOprAuthHelper().resetAuthorization();
}
app.getOprAuthHelper().notifyAndRemoveListeners();
}
}
public interface OprAuthorizationListener {
void authorizationCompleted();
}
}

View file

@ -0,0 +1,119 @@
package net.osmand.plus.openplacereviews;
import android.os.Bundle;
import androidx.activity.OnBackPressedCallback;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;
import androidx.preference.Preference;
import net.osmand.plus.OsmandPlugin;
import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.openplacereviews.OprAuthHelper.OprAuthorizationListener;
import net.osmand.plus.settings.fragments.BaseSettingsFragment;
import net.osmand.plus.settings.fragments.OnPreferenceChanged;
import net.osmand.plus.settings.preferences.SwitchPreferenceEx;
public class OprSettingsFragment extends BaseSettingsFragment implements OnPreferenceChanged, OprAuthorizationListener {
private static final String OPR_LOGOUT = "opr_logout";
public static final String OPR_LOGIN_DATA = "opr_login_data";
private OprAuthHelper authHelper;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
authHelper = app.getOprAuthHelper();
FragmentActivity activity = requireMyActivity();
activity.getOnBackPressedDispatcher().addCallback(this, new OnBackPressedCallback(true) {
public void handleOnBackPressed() {
MapActivity mapActivity = getMapActivity();
if (mapActivity != null) {
mapActivity.launchPrevActivityIntent();
}
dismiss();
}
});
}
@Override
protected void setupPreferences() {
Preference oprSettingsInfo = findPreference("opr_settings_info");
oprSettingsInfo.setIconSpaceReserved(false);
setupLoginPref();
setupLogoutPref();
setupUseDevUrlPref();
}
private void setupLoginPref() {
Preference nameAndPasswordPref = findPreference(OPR_LOGIN_DATA);
nameAndPasswordPref.setVisible(!authHelper.isLoginExists());
nameAndPasswordPref.setIcon(getContentIcon(R.drawable.ic_action_user_account));
}
private void setupLogoutPref() {
Preference nameAndPasswordPref = findPreference(OPR_LOGOUT);
nameAndPasswordPref.setVisible(authHelper.isLoginExists());
nameAndPasswordPref.setSummary(settings.OPR_USERNAME.get());
nameAndPasswordPref.setIcon(getContentIcon(R.drawable.ic_action_user_account));
}
private void setupUseDevUrlPref() {
SwitchPreferenceEx useDevUrlPref = findPreference(settings.OPR_USE_DEV_URL.getId());
useDevUrlPref.setVisible(OsmandPlugin.isDevelopment());
useDevUrlPref.setIcon(getPersistentPrefIcon(R.drawable.ic_plugin_developer));
}
@Override
public boolean onPreferenceClick(Preference preference) {
String prefId = preference.getKey();
if (OPR_LOGIN_DATA.equals(prefId)) {
FragmentManager fragmentManager = getFragmentManager();
if (fragmentManager != null) {
OprStartFragment.showInstance(fragmentManager);
return true;
}
} else if (OPR_LOGOUT.equals(prefId)) {
oprLogout();
return true;
}
return super.onPreferenceClick(preference);
}
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
String prefId = preference.getKey();
if (settings.OPR_USE_DEV_URL.getId().equals(prefId) && newValue instanceof Boolean) {
settings.OPR_USE_DEV_URL.set((Boolean) newValue);
oprLogout();
return true;
}
return super.onPreferenceChange(preference, newValue);
}
public void oprLogout() {
authHelper.resetAuthorization();
app.showShortToastMessage(R.string.osm_edit_logout_success);
updateAllSettings();
}
@Override
public void onPreferenceChanged(String prefId) {
if (settings.OPR_USE_DEV_URL.getId().equals(prefId)) {
oprLogout();
}
updateAllSettings();
}
@Override
public void authorizationCompleted() {
if (getContext() != null) {
updateAllSettings();
}
}
}

View file

@ -16,18 +16,21 @@ import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.Toolbar;
import androidx.browser.customtabs.CustomTabsIntent;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;
import net.osmand.AndroidUtils;
import net.osmand.PlatformUtil;
import net.osmand.plus.R;
import net.osmand.plus.UiUtilities;
import net.osmand.plus.base.BaseOsmAndFragment;
import net.osmand.plus.openplacereviews.OprAuthHelper.OprAuthorizationListener;
import org.apache.commons.logging.Log;
public class OprStartFragment extends BaseOsmAndFragment {
public class OprStartFragment extends BaseOsmAndFragment implements OprAuthorizationListener {
private static final String TAG = OprStartFragment.class.getSimpleName();
private static final Log LOG = PlatformUtil.getLog(OprStartFragment.class);
private static final String openPlaceReviewsUrl = "OpenPlaceReviews.org";
@ -36,18 +39,22 @@ public class OprStartFragment extends BaseOsmAndFragment {
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
nightMode = getMyApplication().getDaynightHelper().isNightModeForMapControls();
View v = UiUtilities.getInflater(requireMyActivity(), nightMode).inflate(R.layout.fragment_opr_login, container,
false);
View createAccount = v.findViewById(R.id.register_opr_create_account);
v.findViewById(R.id.back_button).setOnClickListener(new View.OnClickListener() {
View v = UiUtilities.getInflater(requireMyActivity(), nightMode).inflate(R.layout.fragment_opr_login, container, false);
AndroidUtils.addStatusBarPadding21v(requireMyActivity(), v);
Toolbar toolbar = (Toolbar) v.findViewById(R.id.toolbar);
int icBackResId = AndroidUtils.getNavigationIconResId(v.getContext());
toolbar.setNavigationIcon(getContentIcon(icBackResId));
toolbar.setNavigationContentDescription(R.string.access_shared_string_navigate_up);
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
FragmentActivity activity = getActivity();
if (activity != null) {
activity.getSupportFragmentManager().popBackStack();
}
public void onClick(View v) {
dismiss();
}
});
View createAccount = v.findViewById(R.id.register_opr_create_account);
UiUtilities.setupDialogButton(nightMode, createAccount, UiUtilities.DialogButtonType.PRIMARY,
R.string.register_opr_create_new_account);
createAccount.setOnClickListener(new View.OnClickListener() {
@ -70,14 +77,14 @@ public class OprStartFragment extends BaseOsmAndFragment {
}
private void handleHaveAccount() {
String url = OPRConstants.getLoginUrl(requireContext());
String url = OPRConstants.getLoginUrl(requireMyApplication());
CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder();
CustomTabsIntent customTabsIntent = builder.build();
customTabsIntent.launchUrl(requireContext(), Uri.parse(url));
}
private void handleCreateAccount() {
String url = OPRConstants.getRegisterUrl(requireContext());
String url = OPRConstants.getRegisterUrl(requireMyApplication());
CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder();
CustomTabsIntent customTabsIntent = builder.build();
customTabsIntent.launchUrl(requireContext(), Uri.parse(url));
@ -114,6 +121,17 @@ public class OprStartFragment extends BaseOsmAndFragment {
}
}
@Override
public void authorizationCompleted() {
dismiss();
}
protected void dismiss() {
FragmentActivity activity = getActivity();
if (activity != null) {
activity.getSupportFragmentManager().popBackStack();
}
}
public static void showInstance(@NonNull FragmentManager fm) {
try {

View file

@ -28,7 +28,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import static net.osmand.plus.osmedit.oauth.OsmOAuthHelper.*;
import static net.osmand.plus.osmedit.oauth.OsmOAuthHelper.OsmAuthorizationListener;
/**
* Created by Denis
@ -149,7 +149,9 @@ public class DashOsmEditsFragment extends DashBaseFragment
@Override
public void authorizationCompleted() {
SendPoiBottomSheetFragment.showInstance(getChildFragmentManager(), new OsmPoint[]{selectedPoint});
if (selectedPoint != null) {
SendPoiBottomSheetFragment.showInstance(getChildFragmentManager(), new OsmPoint[] {selectedPoint});
}
}
@Override

View file

@ -5,6 +5,7 @@ import android.graphics.drawable.Drawable;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.FragmentManager;
import net.osmand.data.PointDescription;
import net.osmand.osm.PoiType;
@ -51,19 +52,18 @@ public class EditPOIMenuController extends MenuController {
OsmandSettings settings = app.getSettings();
OsmOAuthAuthorizationAdapter client = new OsmOAuthAuthorizationAdapter(app);
boolean isLogged = client.isValidToken()
|| !Algorithms.isEmpty(settings.USER_NAME.get())
&& !Algorithms.isEmpty(settings.USER_PASSWORD.get());
|| !Algorithms.isEmpty(settings.OSM_USER_NAME.get())
&& !Algorithms.isEmpty(settings.OSM_USER_PASSWORD.get());
FragmentManager fragmentManager = activity.getSupportFragmentManager();
if (point instanceof OpenstreetmapPoint) {
if (isLogged) {
SendPoiBottomSheetFragment.showInstance(activity.getSupportFragmentManager(),
new OsmPoint[]{getOsmPoint()});
SendPoiBottomSheetFragment.showInstance(fragmentManager, new OsmPoint[] {point});
} else {
LoginBottomSheetFragment.showInstance(activity.getSupportFragmentManager(), null);
LoginBottomSheetFragment.showInstance(fragmentManager, null);
}
} else if (point instanceof OsmNotesPoint) {
SendOsmNoteBottomSheetFragment.showInstance(activity.getSupportFragmentManager(),
new OsmPoint[]{getOsmPoint()});
SendOsmNoteBottomSheetFragment.showInstance(fragmentManager, new OsmPoint[] {point});
}
}
}

View file

@ -84,7 +84,7 @@ public class OpenstreetmapRemoteUtil implements OpenstreetmapUtil {
additionalData.put("tags", tagstring);
additionalData.put("visibility", visibility);
return NetworkUtils.uploadFile(url, f,
settings.USER_NAME.get() + ":" + settings.USER_PASSWORD.get(),
settings.OSM_USER_NAME.get() + ":" + settings.OSM_USER_PASSWORD.get(),
adapter.getClient(),
"file",
true, additionalData);
@ -138,7 +138,7 @@ public class OpenstreetmapRemoteUtil implements OpenstreetmapUtil {
connection.setRequestMethod(requestMethod);
connection.setRequestProperty("User-Agent", Version.getFullVersion(ctx)); //$NON-NLS-1$
StringBuilder responseBody = new StringBuilder();
String token = settings.USER_NAME.get() + ":" + settings.USER_PASSWORD.get(); //$NON-NLS-1$
String token = settings.OSM_USER_NAME.get() + ":" + settings.OSM_USER_PASSWORD.get(); //$NON-NLS-1$
connection.addRequestProperty("Authorization", "Basic " + Base64.encode(token.getBytes("UTF-8"))); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
connection.setDoInput(true);
if (requestMethod.equals("PUT") || requestMethod.equals("POST") || requestMethod.equals("DELETE")) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
@ -322,9 +322,9 @@ public class OpenstreetmapRemoteUtil implements OpenstreetmapUtil {
ser.attribute(null, "version", "0.6"); //$NON-NLS-1$ //$NON-NLS-2$
ser.attribute(null, "generator", Version.getAppName(ctx)); //$NON-NLS-1$
if (n instanceof Node) {
writeNode((Node) n, info, ser, changeSetId, settings.USER_NAME.get());
writeNode((Node) n, info, ser, changeSetId, settings.OSM_USER_NAME.get());
} else if (n instanceof Way) {
writeWay((Way) n, info, ser, changeSetId, settings.USER_NAME.get());
writeWay((Way) n, info, ser, changeSetId, settings.OSM_USER_NAME.get());
}
ser.endTag(null, OsmPoint.stringAction.get(action));
ser.endTag(null, "osmChange"); //$NON-NLS-1$

View file

@ -141,7 +141,7 @@ public class OsmBugsRemoteUtil implements OsmBugsUtil {
connection.setRequestMethod(requestMethod);
connection.setRequestProperty("User-Agent", Version.getFullVersion(app));
if (!anonymous) {
String token = settings.USER_NAME.get() + ":" + settings.USER_PASSWORD.get();
String token = settings.OSM_USER_NAME.get() + ":" + settings.OSM_USER_PASSWORD.get();
connection.addRequestProperty("Authorization", "Basic " + Base64.encode(token.getBytes(StandardCharsets.UTF_8)));
}
connection.setDoInput(true);

View file

@ -112,7 +112,7 @@ public class OsmEditingFragment extends BaseSettingsFragment implements OnPrefer
boolean validToken = isValidToken();
Preference nameAndPasswordPref = findPreference(OSM_LOGOUT);
if (validToken || isLoginExists()) {
String userName = validToken ? settings.USER_DISPLAY_NAME.get() : settings.USER_NAME.get();
String userName = validToken ? settings.OSM_USER_DISPLAY_NAME.get() : settings.OSM_USER_NAME.get();
nameAndPasswordPref.setVisible(true);
nameAndPasswordPref.setSummary(userName);
nameAndPasswordPref.setIcon(getContentIcon(R.drawable.ic_action_user_account));
@ -126,7 +126,7 @@ public class OsmEditingFragment extends BaseSettingsFragment implements OnPrefer
}
private boolean isLoginExists() {
return !Algorithms.isEmpty(settings.USER_NAME.get()) && !Algorithms.isEmpty(settings.USER_PASSWORD.get());
return !Algorithms.isEmpty(settings.OSM_USER_NAME.get()) && !Algorithms.isEmpty(settings.OSM_USER_PASSWORD.get());
}
private void setupOfflineEditingPref() {
@ -140,7 +140,7 @@ public class OsmEditingFragment extends BaseSettingsFragment implements OnPrefer
}
private void setupUseDevUrlPref() {
SwitchPreferenceEx useDevUrlPref = findPreference(settings.USE_DEV_URL.getId());
SwitchPreferenceEx useDevUrlPref = findPreference(settings.OSM_USE_DEV_URL.getId());
if (OsmandPlugin.isDevelopment()) {
Drawable icon = getPersistentPrefIcon(R.drawable.ic_action_laptop);
useDevUrlPref.setDescription(getString(R.string.use_dev_url_descr));
@ -176,8 +176,8 @@ public class OsmEditingFragment extends BaseSettingsFragment implements OnPrefer
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
String prefId = preference.getKey();
if (settings.USE_DEV_URL.getId().equals(prefId) && newValue instanceof Boolean) {
settings.USE_DEV_URL.set((Boolean) newValue);
if (settings.OSM_USE_DEV_URL.getId().equals(prefId) && newValue instanceof Boolean) {
settings.OSM_USE_DEV_URL.set((Boolean) newValue);
osmLogout();
return true;
}
@ -220,7 +220,7 @@ public class OsmEditingFragment extends BaseSettingsFragment implements OnPrefer
@Override
public void onPreferenceChanged(String prefId) {
if (settings.USE_DEV_URL.getId().equals(prefId)) {
if (settings.OSM_USE_DEV_URL.getId().equals(prefId)) {
osmLogout();
}
updateAllSettings();

View file

@ -457,9 +457,9 @@ public class OsmEditingPlugin extends OsmandPlugin {
}
public boolean sendGPXFiles(final FragmentActivity activity, Fragment fragment, final GpxInfo... info) {
String name = settings.USER_NAME.get();
String pwd = settings.USER_PASSWORD.get();
String authToken = settings.USER_ACCESS_TOKEN.get();
String name = settings.OSM_USER_NAME.get();
String pwd = settings.OSM_USER_PASSWORD.get();
String authToken = settings.OSM_USER_ACCESS_TOKEN.get();
if ((Algorithms.isEmpty(name) || Algorithms.isEmpty(pwd)) && Algorithms.isEmpty(authToken)) {
LoginBottomSheetFragment.showInstance(activity.getSupportFragmentManager(), fragment);
return false;

View file

@ -30,8 +30,8 @@ public class ValidateOsmLoginDetailsTask extends AsyncTask<Void, Void, OsmBugRes
@Override
protected void onPostExecute(OsmBugResult osmBugResult) {
if (osmBugResult.warning != null) {
app.getSettings().USER_NAME.resetToDefault();
app.getSettings().USER_PASSWORD.resetToDefault();
app.getSettings().OSM_USER_NAME.resetToDefault();
app.getSettings().OSM_USER_PASSWORD.resetToDefault();
app.showToastMessage(osmBugResult.warning);
} else {
app.showToastMessage(R.string.osm_authorization_success);

View file

@ -69,10 +69,10 @@ public class SendGpxBottomSheetFragment extends MenuBottomSheetDialogFragment {
messageField = sendGpxView.findViewById(R.id.message_field);
TextView accountName = sendGpxView.findViewById(R.id.user_name);
if (!Algorithms.isEmpty(settings.USER_DISPLAY_NAME.get())) {
accountName.setText(settings.USER_DISPLAY_NAME.get());
if (!Algorithms.isEmpty(settings.OSM_USER_DISPLAY_NAME.get())) {
accountName.setText(settings.OSM_USER_DISPLAY_NAME.get());
} else {
accountName.setText(settings.USER_NAME.get());
accountName.setText(settings.OSM_USER_NAME.get());
}
String fileName = gpxInfos[0].getFileName();

View file

@ -61,7 +61,7 @@ public class SendOsmNoteBottomSheetFragment extends MenuBottomSheetDialogFragmen
private EditText noteText;
private boolean isLoginOAuth() {
return !Algorithms.isEmpty(settings.USER_DISPLAY_NAME.get());
return !Algorithms.isEmpty(settings.OSM_USER_DISPLAY_NAME.get());
}
@Override
@ -150,8 +150,8 @@ public class SendOsmNoteBottomSheetFragment extends MenuBottomSheetDialogFragmen
}
private void updateAccountName() {
String userNameOAuth = settings.USER_DISPLAY_NAME.get();
String userNameOpenID = settings.USER_NAME.get();
String userNameOAuth = settings.OSM_USER_DISPLAY_NAME.get();
String userNameOpenID = settings.OSM_USER_NAME.get();
String userName = isLoginOAuth() ? userNameOAuth : userNameOpenID;
accountName.setText(userName);
updateSignIn(uploadAnonymously.isChecked());
@ -230,7 +230,7 @@ public class SendOsmNoteBottomSheetFragment extends MenuBottomSheetDialogFragmen
private boolean isLogged() {
OsmOAuthAuthorizationAdapter adapter = app.getOsmOAuthHelper().getAuthorizationAdapter();
return adapter.isValidToken()
|| !Algorithms.isEmpty(settings.USER_NAME.get())
&& !Algorithms.isEmpty(settings.USER_PASSWORD.get());
|| !Algorithms.isEmpty(settings.OSM_USER_NAME.get())
&& !Algorithms.isEmpty(settings.OSM_USER_PASSWORD.get());
}
}

View file

@ -47,7 +47,7 @@ public class SendPoiBottomSheetFragment extends MenuBottomSheetDialogFragment {
private boolean isLoginOAuth(OsmandSettings settings) {
return !Algorithms.isEmpty(settings.USER_DISPLAY_NAME.get());
return !Algorithms.isEmpty(settings.OSM_USER_DISPLAY_NAME.get());
}
@Override
@ -68,8 +68,8 @@ public class SendPoiBottomSheetFragment extends MenuBottomSheetDialogFragment {
messageEditText.setSelection(messageEditText.getText().length());
final TextView accountName = sendOsmPoiView.findViewById(R.id.user_name);
OsmandSettings settings = app.getSettings();
String userNameOAuth = settings.USER_DISPLAY_NAME.get();
String userNameOpenID = settings.USER_NAME.get();
String userNameOAuth = settings.OSM_USER_DISPLAY_NAME.get();
String userNameOpenID = settings.OSM_USER_NAME.get();
String userName = isLoginOAuth(settings) ? userNameOAuth : userNameOpenID;
accountName.setText(userName);
final int paddingSmall = app.getResources().getDimensionPixelSize(R.dimen.content_padding_small);

View file

@ -1,19 +1,10 @@
package net.osmand.plus.osmedit.oauth;
import android.content.Context;
import android.content.Intent;
import android.net.TrafficStats;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import androidx.annotation.NonNull;
import androidx.browser.customtabs.CustomTabsIntent;
import androidx.core.content.ContextCompat;
import com.github.scribejava.core.builder.api.DefaultApi10a;
import com.github.scribejava.core.model.OAuth1AccessToken;
@ -24,7 +15,6 @@ import com.github.scribejava.core.model.Verb;
import net.osmand.PlatformUtil;
import net.osmand.osm.oauth.OsmOAuthAuthorizationClient;
import net.osmand.plus.OsmAndConstants;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.wikipedia.WikipediaDialogFragment;
@ -52,7 +42,7 @@ public class OsmOAuthAuthorizationAdapter {
DefaultApi10a api10a;
String key;
String secret;
if (app.getSettings().USE_DEV_URL.get()) {
if (app.getSettings().OSM_USE_DEV_URL.get()) {
api10a = new OsmOAuthAuthorizationClient.OsmDevApi();
key = app.getString(R.string.osm_oauth_developer_key);
secret = app.getString(R.string.osm_oauth_developer_secret);
@ -78,8 +68,8 @@ public class OsmOAuthAuthorizationAdapter {
}
public void restoreToken() {
String token = app.getSettings().USER_ACCESS_TOKEN.get();
String tokenSecret = app.getSettings().USER_ACCESS_TOKEN_SECRET.get();
String token = app.getSettings().OSM_USER_ACCESS_TOKEN.get();
String tokenSecret = app.getSettings().OSM_USER_ACCESS_TOKEN_SECRET.get();
if (!(token.isEmpty() || tokenSecret.isEmpty())) {
client.setAccessToken(new OAuth1AccessToken(token, tokenSecret));
} else {
@ -93,8 +83,8 @@ public class OsmOAuthAuthorizationAdapter {
private void saveToken() {
OAuth1AccessToken accessToken = client.getAccessToken();
app.getSettings().USER_ACCESS_TOKEN.set(accessToken.getToken());
app.getSettings().USER_ACCESS_TOKEN_SECRET.set(accessToken.getTokenSecret());
app.getSettings().OSM_USER_ACCESS_TOKEN.set(accessToken.getToken());
app.getSettings().OSM_USER_ACCESS_TOKEN_SECRET.set(accessToken.getTokenSecret());
}
private void loadWebView(ViewGroup root, boolean nightMode, String url) {
@ -137,7 +127,7 @@ public class OsmOAuthAuthorizationAdapter {
}
@Override
protected void onPostExecute(@NonNull OAuth1RequestToken requestToken) {
protected void onPostExecute(OAuth1RequestToken requestToken) {
if (requestToken != null) {
loadWebView(rootLayout, nightMode, client.getService().getAuthorizationUrl(requestToken));
} else {
@ -156,9 +146,11 @@ public class OsmOAuthAuthorizationAdapter {
@Override
protected Void doInBackground(String... oauthVerifier) {
client.authorize(oauthVerifier[0]);
saveToken();
updateUserName();
if (client.getRequestToken() != null) {
client.authorize(oauthVerifier[0]);
saveToken();
updateUserName();
}
return null;
}
@ -180,7 +172,7 @@ public class OsmOAuthAuthorizationAdapter {
} catch (XmlPullParserException e) {
log.error(e);
}
app.getSettings().USER_DISPLAY_NAME.set(userName);
app.getSettings().OSM_USER_DISPLAY_NAME.set(userName);
}
public String getUserName() throws InterruptedException, ExecutionException, IOException, XmlPullParserException {

View file

@ -54,18 +54,18 @@ public class OsmOAuthHelper {
public void resetAuthorization() {
if (isValidToken()) {
settings.USER_ACCESS_TOKEN.resetToDefault();
settings.USER_ACCESS_TOKEN_SECRET.resetToDefault();
settings.OSM_USER_ACCESS_TOKEN.resetToDefault();
settings.OSM_USER_ACCESS_TOKEN_SECRET.resetToDefault();
authorizationAdapter.resetToken();
} else if (isLoginExists()) {
settings.USER_NAME.resetToDefault();
settings.USER_PASSWORD.resetToDefault();
settings.OSM_USER_NAME.resetToDefault();
settings.OSM_USER_PASSWORD.resetToDefault();
}
updateAdapter();
}
private boolean isLoginExists() {
return !Algorithms.isEmpty(settings.USER_NAME.get()) && !Algorithms.isEmpty(settings.USER_PASSWORD.get());
return !Algorithms.isEmpty(settings.OSM_USER_NAME.get()) && !Algorithms.isEmpty(settings.OSM_USER_PASSWORD.get());
}
public void notifyAndRemoveListeners() {

View file

@ -1,7 +1,11 @@
package net.osmand.plus.profiles;
import net.osmand.plus.settings.backend.ApplicationMode;
import androidx.annotation.NonNull;
import androidx.fragment.app.FragmentManager;
import net.osmand.plus.R;
import net.osmand.plus.profiles.ConfigureProfileMenuAdapter.ProfileSelectedListener;
import net.osmand.plus.settings.backend.ApplicationMode;
import java.util.ArrayList;
import java.util.HashSet;
@ -9,8 +13,8 @@ import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
public class ConfigureAppModesBottomSheetDialogFragment extends AppModesBottomSheetDialogFragment<ConfigureProfileMenuAdapter>
implements ConfigureProfileMenuAdapter.ProfileSelectedListener {
public class ConfigureAppModesBottomSheetDialogFragment extends AppModesBottomSheetDialogFragment<ConfigureProfileMenuAdapter>
implements ProfileSelectedListener {
public static final String TAG = "ConfigureAppModesBottomSheetDialogFragment";
@ -56,4 +60,15 @@ public class ConfigureAppModesBottomSheetDialogFragment extends AppModesBottomSh
}
ApplicationMode.changeProfileAvailability(item, isChecked, getMyApplication());
}
public static void showInstance(@NonNull FragmentManager fragmentManager, boolean usedOnMap, UpdateMapRouteMenuListener listener) {
if (fragmentManager.findFragmentByTag(TAG) == null) {
ConfigureAppModesBottomSheetDialogFragment fragment = new ConfigureAppModesBottomSheetDialogFragment();
fragment.setUsedOnMap(usedOnMap);
fragment.setUpdateMapRouteMenuListener(listener);
fragmentManager.beginTransaction()
.add(fragment, TAG)
.commitAllowingStateLoss();
}
}
}

View file

@ -29,6 +29,8 @@ import androidx.appcompat.content.res.AppCompatResources;
import androidx.appcompat.widget.AppCompatImageView;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;
import androidx.transition.AutoTransition;
import androidx.transition.Scene;
import androidx.transition.Transition;
@ -71,7 +73,7 @@ import net.osmand.plus.mapcontextmenu.other.TrackDetailsMenuFragment;
import net.osmand.plus.mapmarkers.MapMarker;
import net.osmand.plus.mapmarkers.MapMarkerSelectionFragment;
import net.osmand.plus.poi.PoiUIFilter;
import net.osmand.plus.profiles.AppModesBottomSheetDialogFragment;
import net.osmand.plus.profiles.AppModesBottomSheetDialogFragment.UpdateMapRouteMenuListener;
import net.osmand.plus.profiles.ConfigureAppModesBottomSheetDialogFragment;
import net.osmand.plus.routepreparationmenu.RoutingOptionsHelper.AvoidPTTypesRoutingParameter;
import net.osmand.plus.routepreparationmenu.RoutingOptionsHelper.AvoidRoadsRoutingParameter;
@ -870,16 +872,16 @@ public class MapRouteInfoMenu implements IRouteInformationListener, CardListener
}
private void showProfileBottomSheetDialog() {
final AppModesBottomSheetDialogFragment fragment = new ConfigureAppModesBottomSheetDialogFragment();
fragment.setUsedOnMap(true);
fragment.setUpdateMapRouteMenuListener(new AppModesBottomSheetDialogFragment.UpdateMapRouteMenuListener() {
@Override
public void updateAppModeMenu() {
updateApplicationModes();
}
});
getMapActivity().getSupportFragmentManager().beginTransaction()
.add(fragment, ConfigureAppModesBottomSheetDialogFragment.TAG).commitAllowingStateLoss();
FragmentActivity activity = getMapActivity();
if (activity != null) {
FragmentManager manager = activity.getSupportFragmentManager();
ConfigureAppModesBottomSheetDialogFragment.showInstance(manager, true, new UpdateMapRouteMenuListener() {
@Override
public void updateAppModeMenu() {
updateApplicationModes();
}
});
}
}
private void updateApplicationMode(ApplicationMode mode, ApplicationMode next) {

View file

@ -625,11 +625,14 @@ public class RouteOptionsBottomSheet extends MenuBottomSheetDialogFragment {
private List<RoutingParameter> getReliefParameters() {
List<RoutingParameter> reliefFactorParameters = new ArrayList<>();
Map<String, RoutingParameter> parameters = app.getRouter(applicationMode).getParameters();
for (Map.Entry<String, RoutingParameter> entry : parameters.entrySet()) {
RoutingParameter routingParameter = entry.getValue();
if (RELIEF_SMOOTHNESS_FACTOR.equals(routingParameter.getGroup())) {
reliefFactorParameters.add(routingParameter);
GeneralRouter router = app.getRouter(applicationMode);
if (router != null) {
Map<String, RoutingParameter> parameters = router.getParameters();
for (Map.Entry<String, RoutingParameter> entry : parameters.entrySet()) {
RoutingParameter routingParameter = entry.getValue();
if (RELIEF_SMOOTHNESS_FACTOR.equals(routingParameter.getGroup())) {
reliefFactorParameters.add(routingParameter);
}
}
}
return reliefFactorParameters;

View file

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

View file

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

View file

@ -301,7 +301,12 @@ public class ApplicationMode {
}
public boolean isCustomProfile() {
return !defaultValues.contains(this);
for (ApplicationMode mode : defaultValues) {
if (Algorithms.stringsEqual(mode.getStringKey(), getStringKey())) {
return false;
}
}
return true;
}
public boolean isDerivedRoutingFrom(ApplicationMode mode) {

View file

@ -1121,8 +1121,8 @@ public class OsmandSettings {
}
// this value string is synchronized with settings_pref.xml preference name
public final OsmandPreference<String> USER_NAME = new StringPreference(this, "user_name", "").makeGlobal().makeShared();
public final OsmandPreference<String> USER_DISPLAY_NAME = new StringPreference(this, "user_display_name", "").makeGlobal().makeShared();
public final OsmandPreference<String> OSM_USER_NAME = new StringPreference(this, "user_name", "").makeGlobal().makeShared();
public final OsmandPreference<String> OSM_USER_DISPLAY_NAME = new StringPreference(this, "user_display_name", "").makeGlobal().makeShared();
public static final String BILLING_USER_DONATION_WORLD_PARAMETER = "";
public static final String BILLING_USER_DONATION_NONE_PARAMETER = "none";
@ -1156,13 +1156,13 @@ public class OsmandSettings {
new StringPreference(this, "user_osm_bug_name", "NoName/OsmAnd").makeGlobal().makeShared();
// this value string is synchronized with settings_pref.xml preference name
public final OsmandPreference<String> USER_PASSWORD =
public final OsmandPreference<String> OSM_USER_PASSWORD =
new StringPreference(this, "user_password", "").makeGlobal().makeShared();
public final OsmandPreference<String> USER_ACCESS_TOKEN =
public final OsmandPreference<String> OSM_USER_ACCESS_TOKEN =
new StringPreference(this, "user_access_token", "").makeGlobal();
public final OsmandPreference<String> USER_ACCESS_TOKEN_SECRET =
public final OsmandPreference<String> OSM_USER_ACCESS_TOKEN_SECRET =
new StringPreference(this, "user_access_token_secret", "").makeGlobal();
public final OsmandPreference<String> OPR_ACCESS_TOKEN =
@ -1174,13 +1174,15 @@ public class OsmandSettings {
public final OsmandPreference<String> OPR_BLOCKCHAIN_NAME =
new StringPreference(this, "opr_blockchain_name", "").makeGlobal();
public final OsmandPreference<Boolean> OPR_USE_DEV_URL = new BooleanPreference(this, "opr_use_dev_url", false).makeGlobal().makeShared();
// this value boolean is synchronized with settings_pref.xml preference offline POI/Bugs edition
public final OsmandPreference<Boolean> OFFLINE_EDITION = new BooleanPreference(this, "offline_osm_editing", true).makeGlobal().makeShared();
public final OsmandPreference<Boolean> USE_DEV_URL = new BooleanPreference(this, "use_dev_url", false).makeGlobal().makeShared();
public final OsmandPreference<Boolean> OSM_USE_DEV_URL = new BooleanPreference(this, "use_dev_url", false).makeGlobal().makeShared();
public String getOsmUrl() {
String osmUrl;
if (USE_DEV_URL.get()) {
if (OSM_USE_DEV_URL.get()) {
osmUrl = "https://master.apis.dev.openstreetmap.org/";
} else {
osmUrl = "https://api.openstreetmap.org/";
@ -1188,6 +1190,10 @@ public class OsmandSettings {
return osmUrl;
}
public String getOprUrl() {
return ctx.getString(OPR_USE_DEV_URL.get() ? R.string.dev_opr_base_url : R.string.opr_base_url);
}
// this value string is synchronized with settings_pref.xml preference name
public final CommonPreference<DayNightMode> DAYNIGHT_MODE =
new EnumStringPreference<DayNightMode>(this, "daynight_mode", DayNightMode.DAY, DayNightMode.values());

View file

@ -124,7 +124,7 @@ public class ProfileSettingsItem extends OsmandSettingsItem {
if (Algorithms.isEmpty(modeBean.userProfileName)) {
ApplicationMode appMode = ApplicationMode.valueOfStringKey(modeBean.stringKey, null);
if (appMode != null) {
modeBean.userProfileName = app.getString(appMode.getNameKeyResource());
modeBean.userProfileName = appMode.toHumanString();
}
}
int number = 0;

View file

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

View file

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

View file

@ -6,7 +6,6 @@ import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.EditText;
import android.widget.ScrollView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@ -49,8 +48,8 @@ public class OsmLoginDataBottomSheet extends BasePreferenceBottomSheet {
userNameEditText = view.findViewById(R.id.name_edit_text);
passwordEditText = view.findViewById(R.id.password_edit_text);
String name = app.getSettings().USER_NAME.get();
String password = app.getSettings().USER_PASSWORD.get();
String name = app.getSettings().OSM_USER_NAME.get();
String password = app.getSettings().OSM_USER_PASSWORD.get();
if (savedInstanceState != null) {
name = savedInstanceState.getString(USER_NAME_KEY, null);
@ -96,8 +95,8 @@ public class OsmLoginDataBottomSheet extends BasePreferenceBottomSheet {
protected void onRightBottomButtonClick() {
OsmandApplication app = requiredMyApplication();
app.getSettings().USER_NAME.set(userNameEditText.getText().toString());
app.getSettings().USER_PASSWORD.set(passwordEditText.getText().toString());
app.getSettings().OSM_USER_NAME.set(userNameEditText.getText().toString());
app.getSettings().OSM_USER_PASSWORD.set(passwordEditText.getText().toString());
Fragment targetFragment = getTargetFragment();
if (targetFragment instanceof ValidateOsmLoginListener) {

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -61,6 +61,7 @@ import net.osmand.plus.activities.OsmandInAppPurchaseActivity;
import net.osmand.plus.audionotes.MultimediaNotesFragment;
import net.osmand.plus.development.DevelopmentSettingsFragment;
import net.osmand.plus.monitoring.MonitoringSettingsFragment;
import net.osmand.plus.openplacereviews.OprSettingsFragment;
import net.osmand.plus.osmedit.OsmEditingFragment;
import net.osmand.plus.profiles.SelectAppModesBottomSheetDialogFragment;
import net.osmand.plus.profiles.SelectAppModesBottomSheetDialogFragment.AppModeChangedListener;
@ -73,6 +74,7 @@ import net.osmand.plus.settings.bottomsheets.ChangeGeneralProfilesPrefBottomShee
import net.osmand.plus.settings.bottomsheets.EditTextPreferenceBottomSheet;
import net.osmand.plus.settings.bottomsheets.MultiSelectPreferencesBottomSheet;
import net.osmand.plus.settings.bottomsheets.SingleSelectPreferenceBottomSheet;
import net.osmand.plus.settings.datastorage.DataStorageFragment;
import net.osmand.plus.settings.preferences.ListPreferenceEx;
import net.osmand.plus.settings.preferences.MultiSelectBooleanPreference;
import net.osmand.plus.settings.preferences.SwitchPreferenceEx;
@ -132,6 +134,7 @@ public abstract class BaseSettingsFragment extends PreferenceFragmentCompat impl
MONITORING_SETTINGS(MonitoringSettingsFragment.class.getName(), true, ApplyQueryType.SNACK_BAR, R.xml.monitoring_settings, R.layout.profile_preference_toolbar),
LIVE_MONITORING(LiveMonitoringFragment.class.getName(), false, ApplyQueryType.SNACK_BAR, R.xml.live_monitoring, R.layout.global_preferences_toolbar_with_switch),
ACCESSIBILITY_SETTINGS(AccessibilitySettingsFragment.class.getName(), true, ApplyQueryType.SNACK_BAR, R.xml.accessibility_settings, R.layout.profile_preference_toolbar),
OPEN_PLACE_REVIEWS(OprSettingsFragment.class.getName(), false, null, R.xml.open_place_reviews, R.layout.global_preference_toolbar),
DEVELOPMENT_SETTINGS(DevelopmentSettingsFragment.class.getName(), false, null, R.xml.development_settings, R.layout.global_preference_toolbar);
public final String fragmentName;

View file

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

View file

@ -34,6 +34,7 @@ import net.osmand.plus.settings.backend.ApplicationMode.ApplicationModeBean;
import net.osmand.util.Algorithms;
import org.apache.commons.logging.Log;
import org.apache.commons.lang3.StringUtils;
import java.io.File;
import java.util.List;
@ -91,7 +92,11 @@ public class DuplicatesSettingsAdapter extends RecyclerView.Adapter<RecyclerView
String profileName = modeBean.userProfileName;
if (Algorithms.isEmpty(profileName)) {
ApplicationMode appMode = ApplicationMode.valueOfStringKey(modeBean.stringKey, null);
profileName = app.getString(appMode.getNameKeyResource());
if (appMode != null) {
profileName = appMode.toHumanString();
} else {
profileName = StringUtils.capitalize(modeBean.stringKey);
}
}
itemHolder.title.setText(profileName);
String routingProfile = "";

View file

@ -62,6 +62,7 @@ import net.osmand.util.Algorithms;
import net.osmand.view.ThreeStateCheckbox;
import org.apache.commons.logging.Log;
import org.apache.commons.lang3.StringUtils;
import java.io.File;
import java.util.ArrayList;
@ -279,7 +280,11 @@ public class ExportItemsBottomSheet extends MenuBottomSheetDialogFragment {
String profileName = modeBean.userProfileName;
if (Algorithms.isEmpty(profileName)) {
ApplicationMode appMode = ApplicationMode.valueOfStringKey(modeBean.stringKey, null);
profileName = appMode.toHumanString();
if (appMode != null) {
profileName = appMode.toHumanString();
} else {
profileName = StringUtils.capitalize(modeBean.stringKey);
}
}
builder.setTitle(profileName);

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

Some files were not shown because too many files have changed in this diff Show more