Add timeline tab and gpx statistic dialog and sync aidl
This commit is contained in:
parent
bd1709a306
commit
80eda68e01
51 changed files with 3031 additions and 204 deletions
24
OsmAnd-telegram/res/drawable/btn_round_border.xml
Normal file
24
OsmAnd-telegram/res/drawable/btn_round_border.xml
Normal file
|
@ -0,0 +1,24 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item android:state_pressed="true">
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="@color/ctrl_active_light" />
|
||||
<corners android:radius="@dimen/dialog_button_radius" />
|
||||
</shape>
|
||||
</item>
|
||||
<item android:state_enabled="false">
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="@color/ctrl_light" />
|
||||
<corners android:radius="@dimen/dialog_button_radius" />
|
||||
</shape>
|
||||
</item>
|
||||
<item>
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="@null" />
|
||||
<corners android:radius="@dimen/dialog_button_radius" />
|
||||
<stroke android:width="1dp" android:color="@color/app_bar_divider" />
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
</selector>
|
184
OsmAnd-telegram/res/layout/fragment_timeline_tab.xml
Normal file
184
OsmAnd-telegram/res/layout/fragment_timeline_tab.xml
Normal file
|
@ -0,0 +1,184 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<android.support.design.widget.AppBarLayout
|
||||
android:id="@+id/app_bar_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/card_bg_color">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/title_row"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/action_bar_height"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<net.osmand.telegram.ui.views.TextViewEx
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="@dimen/action_bar_height"
|
||||
android:layout_weight="1"
|
||||
android:ellipsize="end"
|
||||
android:gravity="center_vertical"
|
||||
android:letterSpacing="@dimen/title_letter_spacing"
|
||||
android:maxLines="1"
|
||||
android:paddingLeft="@dimen/content_padding_standard"
|
||||
android:paddingRight="@dimen/content_padding_standard"
|
||||
android:text="@string/timeline"
|
||||
android:textColor="@color/app_bar_title_light"
|
||||
android:textSize="@dimen/title_text_size"
|
||||
app:typeface="@string/font_roboto_mono_bold" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/options"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginLeft="@dimen/content_padding_standard"
|
||||
android:layout_marginRight="@dimen/content_padding_standard"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:paddingLeft="@dimen/content_padding_half"
|
||||
android:paddingRight="@dimen/content_padding_half"
|
||||
tools:src="@drawable/ic_action_other_menu"
|
||||
tools:tint="@color/icon_light"
|
||||
tools:visibility="visible" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="@dimen/action_bar_descr_bottom_margin"
|
||||
android:paddingLeft="@dimen/content_padding_standard"
|
||||
android:paddingRight="@dimen/content_padding_standard"
|
||||
android:text="@string/timeline_description"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textSize="@dimen/descr_text_size" />
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/monitoring_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/action_bar_height"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:orientation="horizontal"
|
||||
android:paddingLeft="@dimen/content_padding_standard"
|
||||
android:paddingRight="@dimen/content_padding_standard">
|
||||
|
||||
<net.osmand.telegram.ui.views.TextViewEx
|
||||
android:id="@+id/monitoring_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center_vertical|start"
|
||||
android:ellipsize="end"
|
||||
android:gravity="center_vertical"
|
||||
android:maxLines="1"
|
||||
android:text="@string/monitoring_is_enabled"
|
||||
android:textColor="@color/ctrl_active_light"
|
||||
android:textSize="@dimen/descr_text_size"
|
||||
app:typeface="@string/font_roboto_medium" />
|
||||
|
||||
<Switch
|
||||
android:id="@+id/monitoring_switcher"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end|center_vertical"
|
||||
android:background="@null"
|
||||
android:clickable="false"
|
||||
android:focusable="false" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="@color/app_bar_divider" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/date_row"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/list_header_height"
|
||||
android:background="@color/screen_bg_light"
|
||||
android:orientation="horizontal"
|
||||
android:paddingLeft="@dimen/content_padding_standard"
|
||||
android:paddingRight="@dimen/content_padding_standard">
|
||||
|
||||
<net.osmand.telegram.ui.views.TextViewEx
|
||||
android:id="@+id/date_start_btn"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="@dimen/dialog_button_height"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginEnd="@dimen/content_padding_half"
|
||||
android:layout_marginRight="@dimen/content_padding_half"
|
||||
android:layout_weight="1"
|
||||
android:background="@drawable/btn_round_border"
|
||||
android:drawablePadding="@dimen/content_padding_half"
|
||||
android:ellipsize="end"
|
||||
android:gravity="start|center_vertical"
|
||||
android:maxLines="1"
|
||||
android:paddingLeft="@dimen/image_button_padding"
|
||||
android:paddingRight="@dimen/image_button_padding"
|
||||
android:text="@string/start_date"
|
||||
android:textColor="?attr/ctrl_active_color"
|
||||
android:textSize="@dimen/text_button_text_size"
|
||||
app:typeface="@string/font_roboto_medium" />
|
||||
|
||||
<View
|
||||
android:layout_width="16dp"
|
||||
android:layout_height="1dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:background="@color/app_bar_divider" />
|
||||
|
||||
<net.osmand.telegram.ui.views.TextViewEx
|
||||
android:id="@+id/date_end_btn"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="@dimen/dialog_button_height"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginLeft="@dimen/content_padding_half"
|
||||
android:layout_marginStart="@dimen/content_padding_half"
|
||||
android:layout_weight="1"
|
||||
android:background="@drawable/btn_round_border"
|
||||
android:drawablePadding="@dimen/content_padding_half"
|
||||
android:ellipsize="end"
|
||||
android:gravity="start|center_vertical"
|
||||
android:maxLines="1"
|
||||
android:paddingLeft="@dimen/image_button_padding"
|
||||
android:paddingRight="@dimen/image_button_padding"
|
||||
android:text="@string/end_date"
|
||||
android:textColor="?attr/ctrl_active_color"
|
||||
android:textSize="@dimen/text_button_text_size"
|
||||
app:typeface="@string/font_roboto_medium" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</android.support.design.widget.AppBarLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<net.osmand.telegram.ui.views.TextViewEx
|
||||
android:id="@+id/last_telegram_update_time"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="top|center_horizontal"
|
||||
android:gravity="center"
|
||||
android:paddingTop="@dimen/content_padding_half"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textSize="@dimen/list_item_description_text_size"
|
||||
android:visibility="gone"
|
||||
app:typeface="@string/font_roboto_regular" />
|
||||
|
||||
<android.support.v7.widget.RecyclerView
|
||||
android:id="@+id/recycler_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:clipToPadding="false"
|
||||
android:paddingBottom="@dimen/list_item_content_margin"
|
||||
android:scrollbars="vertical" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
</LinearLayout>
|
509
OsmAnd-telegram/res/layout/fragment_user_gpx_info.xml
Normal file
509
OsmAnd-telegram/res/layout/fragment_user_gpx_info.xml
Normal file
|
@ -0,0 +1,509 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?attr/card_bg_color">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/image_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="120dp"
|
||||
app:layout_scrollFlags="scroll">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/back_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="start"
|
||||
android:layout_marginTop="@dimen/content_padding_standard"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:contentDescription="@string/shared_string_back"
|
||||
android:padding="@dimen/content_padding_standard"
|
||||
tools:src="@drawable/ic_arrow_back"
|
||||
tools:tint="@color/icon_light" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/user_icon"
|
||||
android:layout_width="@dimen/my_location_user_icon_size"
|
||||
android:layout_height="@dimen/my_location_user_icon_size"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginTop="@dimen/content_padding_standard"
|
||||
tools:src="@drawable/img_user_picture" />
|
||||
|
||||
<net.osmand.telegram.ui.views.TextViewEx
|
||||
android:id="@+id/title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|center_horizontal"
|
||||
android:ellipsize="end"
|
||||
android:gravity="center"
|
||||
android:maxLines="1"
|
||||
android:text="@string/start_location_sharing"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
android:textSize="@dimen/title_text_size"
|
||||
app:typeface="@string/font_roboto_mono_bold" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/interval_row"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:paddingLeft="@dimen/content_padding_standard"
|
||||
android:paddingRight="@dimen/content_padding_standard">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<net.osmand.telegram.ui.views.TextViewEx
|
||||
android:id="@+id/start_descr"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/content_padding_standard"
|
||||
android:layout_marginRight="@dimen/content_padding_standard"
|
||||
android:layout_weight="1"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:text="@string/start_date"
|
||||
android:textColor="?attr/android:textColorSecondary"
|
||||
android:textSize="@dimen/list_item_description_text_size"
|
||||
app:firstBaselineToTopHeight="@dimen/list_item_baseline_to_top_height"
|
||||
app:typeface="@string/font_roboto_regular" />
|
||||
|
||||
<net.osmand.telegram.ui.views.TextViewEx
|
||||
android:id="@+id/end_descr"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginLeft="@dimen/content_padding_standard"
|
||||
android:layout_marginStart="@dimen/content_padding_standard"
|
||||
android:layout_weight="1"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:text="@string/end_date"
|
||||
android:textColor="?attr/android:textColorSecondary"
|
||||
android:textSize="@dimen/list_item_description_text_size"
|
||||
app:firstBaselineToTopHeight="@dimen/list_item_baseline_to_top_height"
|
||||
app:typeface="@string/font_roboto_regular" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/list_header_height"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<net.osmand.telegram.ui.views.TextViewEx
|
||||
android:id="@+id/date_start_btn"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="@dimen/dialog_button_height"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginEnd="@dimen/content_padding_half"
|
||||
android:layout_marginRight="@dimen/content_padding_half"
|
||||
android:layout_weight="1"
|
||||
android:background="@drawable/btn_round"
|
||||
android:ellipsize="end"
|
||||
android:gravity="center"
|
||||
android:maxLines="1"
|
||||
android:paddingLeft="@dimen/image_button_padding"
|
||||
android:paddingRight="@dimen/image_button_padding"
|
||||
android:textSize="@dimen/text_button_text_size"
|
||||
app:typeface="@string/font_roboto_medium"
|
||||
tools:textColor="?attr/ctrl_active_color"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<net.osmand.telegram.ui.views.TextViewEx
|
||||
android:id="@+id/time_start_btn"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="@dimen/dialog_button_height"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:background="@drawable/btn_round"
|
||||
android:ellipsize="end"
|
||||
android:gravity="center"
|
||||
android:maxLines="1"
|
||||
android:paddingLeft="@dimen/image_button_padding"
|
||||
android:paddingRight="@dimen/image_button_padding"
|
||||
android:textSize="@dimen/text_button_text_size"
|
||||
app:typeface="@string/font_roboto_medium"
|
||||
tools:textColor="?attr/ctrl_active_color"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<View
|
||||
android:layout_width="16dp"
|
||||
android:layout_height="1dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginLeft="@dimen/content_padding_half"
|
||||
android:layout_marginRight="@dimen/content_padding_half"
|
||||
android:background="@color/card_divider_light" />
|
||||
|
||||
<net.osmand.telegram.ui.views.TextViewEx
|
||||
android:id="@+id/date_end_btn"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="@dimen/dialog_button_height"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginEnd="@dimen/content_padding_half"
|
||||
android:layout_marginRight="@dimen/content_padding_half"
|
||||
android:layout_weight="1"
|
||||
android:background="@drawable/btn_round"
|
||||
android:ellipsize="end"
|
||||
android:gravity="center"
|
||||
android:maxLines="1"
|
||||
android:paddingLeft="@dimen/image_button_padding"
|
||||
android:paddingRight="@dimen/image_button_padding"
|
||||
android:textSize="@dimen/text_button_text_size"
|
||||
app:typeface="@string/font_roboto_medium"
|
||||
tools:textColor="?attr/ctrl_active_color"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<net.osmand.telegram.ui.views.TextViewEx
|
||||
android:id="@+id/time_end_btn"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="@dimen/dialog_button_height"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:background="@drawable/btn_round"
|
||||
android:ellipsize="end"
|
||||
android:gravity="center"
|
||||
android:maxLines="1"
|
||||
android:paddingLeft="@dimen/image_button_padding"
|
||||
android:paddingRight="@dimen/image_button_padding"
|
||||
android:textSize="@dimen/text_button_text_size"
|
||||
app:typeface="@string/font_roboto_medium"
|
||||
tools:textColor="?attr/ctrl_active_color"
|
||||
tools:visibility="visible" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/map_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="152dp"
|
||||
android:layout_marginLeft="@dimen/content_padding_standard"
|
||||
android:layout_marginRight="@dimen/content_padding_standard">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/gpx_map"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:contentDescription="@string/shared_string_map" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/gpx_statistic"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/distance_time_span"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:paddingBottom="11dp"
|
||||
android:paddingTop="13dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:orientation="horizontal"
|
||||
android:paddingLeft="16dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/distance_icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="5dp"
|
||||
android:src="@drawable/ic_action_polygom_dark" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="18dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/distance_desc"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="3dp"
|
||||
android:background="@null"
|
||||
android:text="@string/shared_string_distance"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textSize="@dimen/list_item_description_text_size" />
|
||||
|
||||
<net.osmand.telegram.ui.views.TextViewEx
|
||||
android:id="@+id/distance_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@null"
|
||||
android:text="40 km"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="@dimen/hint_text_size"
|
||||
app:typeface="@string/font_roboto_medium" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:orientation="horizontal"
|
||||
android:paddingLeft="16dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/duration_icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="5dp"
|
||||
android:src="@drawable/ic_action_share_location" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="18dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/duration_desc"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="3dp"
|
||||
android:background="@null"
|
||||
android:text="@string/time_on_the_move"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textSize="@dimen/list_item_description_text_size" />
|
||||
|
||||
<net.osmand.telegram.ui.views.TextViewEx
|
||||
android:id="@+id/duration_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@null"
|
||||
android:text="3:32:44"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="@dimen/hint_text_size"
|
||||
app:typeface="@string/font_roboto_medium" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/list_divider"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:orientation="horizontal"
|
||||
android:paddingLeft="16dp"
|
||||
android:paddingRight="8dp">
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="@color/card_divider_light" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:orientation="horizontal"
|
||||
android:paddingLeft="8dp"
|
||||
android:paddingRight="16dp">
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="@color/card_divider_light" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/start_end_time"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:paddingBottom="11dp"
|
||||
android:paddingTop="13dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:orientation="horizontal"
|
||||
android:paddingLeft="16dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/average_speed_icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="5dp"
|
||||
android:src="@drawable/ic_action_speed_average" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="18dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/average_speed_desc"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:background="@null"
|
||||
android:text="@string/average_speed"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textSize="@dimen/list_item_description_text_size" />
|
||||
|
||||
<net.osmand.telegram.ui.views.TextViewEx
|
||||
android:id="@+id/average_speed_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@null"
|
||||
android:text="15:04:58"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="@dimen/hint_text_size"
|
||||
app:typeface="@string/font_roboto_medium" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:orientation="horizontal"
|
||||
android:paddingLeft="16dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/average_altitude_icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="5dp"
|
||||
android:src="@drawable/ic_action_share_location" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="18dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/average_altitude_desc"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:background="@null"
|
||||
android:text="@string/average_altitude"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textSize="@dimen/list_item_description_text_size" />
|
||||
|
||||
<net.osmand.telegram.ui.views.TextViewEx
|
||||
android:id="@+id/average_altitude_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@null"
|
||||
android:text="20:58:00"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="@dimen/hint_text_size"
|
||||
app:typeface="@string/font_roboto_medium" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/open_in_osmand_btn"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/list_item_height_min"
|
||||
android:layout_marginBottom="@dimen/content_padding_standard"
|
||||
android:layout_marginLeft="@dimen/content_padding_half"
|
||||
android:layout_marginRight="@dimen/content_padding_half"
|
||||
android:background="@drawable/btn_round"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingLeft="@dimen/content_padding_half"
|
||||
android:paddingRight="@dimen/content_padding_half">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/open_in_osmand_icon"
|
||||
android:layout_width="@dimen/list_item_icon_size"
|
||||
android:layout_height="@dimen/list_item_icon_size"
|
||||
android:src="@drawable/ic_logo_osmand_free" />
|
||||
|
||||
<net.osmand.telegram.ui.views.TextViewEx
|
||||
android:id="@+id/open_in_osmand_title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/content_padding_big"
|
||||
android:layout_marginRight="@dimen/content_padding_big"
|
||||
android:text="@string/open_in_osmand"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
android:textSize="@dimen/list_item_title_text_size"
|
||||
app:typeface="@string/font_roboto_medium" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/share_gpx_btn"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/list_item_height_min"
|
||||
android:layout_marginBottom="@dimen/content_padding_standard"
|
||||
android:layout_marginLeft="@dimen/content_padding_half"
|
||||
android:layout_marginRight="@dimen/content_padding_half"
|
||||
android:background="@drawable/btn_round"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingLeft="@dimen/content_padding_half"
|
||||
android:paddingRight="@dimen/content_padding_half">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/share_gpx_icon"
|
||||
android:layout_width="@dimen/list_item_icon_size"
|
||||
android:layout_height="@dimen/list_item_icon_size"
|
||||
android:src="@drawable/ic_action_share"
|
||||
android:tint="@color/ctrl_active_light" />
|
||||
|
||||
<net.osmand.telegram.ui.views.TextViewEx
|
||||
android:id="@+id/share_gpx_title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/content_padding_big"
|
||||
android:layout_marginRight="@dimen/content_padding_big"
|
||||
android:text="@string/shared_string_share"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
android:textSize="@dimen/list_item_title_text_size"
|
||||
app:typeface="@string/font_roboto_medium" />
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
</ScrollView>
|
|
@ -9,4 +9,9 @@
|
|||
android:id="@+id/action_live_now"
|
||||
android:icon="@drawable/ic_action_live_now"
|
||||
android:title="@string/live_now"/>
|
||||
|
||||
<item
|
||||
android:id="@+id/action_timeline"
|
||||
android:icon="@drawable/ic_action_timeline"
|
||||
android:title="@string/timeline"/>
|
||||
</menu>
|
|
@ -1,5 +1,6 @@
|
|||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<resources>
|
||||
<string name="timeline_description">Включите мониторинг, для сбора данных о перемещении в фоновом режиме.</string>
|
||||
<string name="last_update_from_telegram">Последнее обновление в Telegram</string>
|
||||
<string name="device_name">Имя устройства</string>
|
||||
<string name="shared_string_hide">Спрятать</string>
|
||||
|
|
|
@ -1,4 +1,13 @@
|
|||
<resources>
|
||||
<string name="monitoring_is_enabled">Monitoring is enabled</string>
|
||||
<string name="monitoring_is_disabled">Monitoring is disabled</string>
|
||||
<string name="time_on_the_move">time on the move</string>
|
||||
<string name="average_altitude">Average altitude</string>
|
||||
<string name="average_speed">Average speed</string>
|
||||
<string name="open_in_osmand">Open in OsmAnd</string>
|
||||
<string name="end_date">End date</string>
|
||||
<string name="start_date">Start date</string>
|
||||
<string name="timeline_description">Enable monitoring to collect movement data in the background.</string>
|
||||
<string name="send_location_as">Send location as</string>
|
||||
<string name="send_location_as_descr">Choose how messages with your location will look like.</string>
|
||||
<string name="shared_string_map">Map</string>
|
||||
|
@ -176,6 +185,7 @@
|
|||
<string name="welcome_descr"><![CDATA[<b>OsmAnd Location Sharing</b> lets you share your location and see that of others in the OsmAnd.<br/><br/>The app uses Telegram API and you need a Telegram account.]]></string>
|
||||
<string name="my_location">My location</string>
|
||||
<string name="live_now">Live now</string>
|
||||
<string name="timeline">Timeline</string>
|
||||
|
||||
|
||||
</resources>
|
||||
|
|
|
@ -1,9 +1,14 @@
|
|||
package net.osmand.aidl;
|
||||
|
||||
import net.osmand.aidl.search.SearchResult;
|
||||
import net.osmand.aidl.gpx.AGpxBitmap;
|
||||
|
||||
interface IOsmAndAidlCallback {
|
||||
void onSearchComplete(in List<SearchResult> resultSet);
|
||||
|
||||
void onUpdate();
|
||||
|
||||
void onAppInitialized();
|
||||
|
||||
void onGpxBitmapCreated(in AGpxBitmap bitmap);
|
||||
}
|
|
@ -55,6 +55,9 @@ import net.osmand.aidl.maplayer.point.ShowMapPointParams;
|
|||
|
||||
import net.osmand.aidl.navdrawer.SetNavDrawerItemsParams;
|
||||
|
||||
import net.osmand.aidl.navdrawer.NavDrawerFooterParams;
|
||||
import net.osmand.aidl.navdrawer.NavDrawerHeaderParams;
|
||||
|
||||
import net.osmand.aidl.navigation.PauseNavigationParams;
|
||||
import net.osmand.aidl.navigation.ResumeNavigationParams;
|
||||
import net.osmand.aidl.navigation.StopNavigationParams;
|
||||
|
@ -67,6 +70,16 @@ import net.osmand.aidl.search.SearchResult;
|
|||
import net.osmand.aidl.search.SearchParams;
|
||||
import net.osmand.aidl.navigation.NavigateSearchParams;
|
||||
|
||||
import net.osmand.aidl.customization.SetWidgetsParams;
|
||||
import net.osmand.aidl.customization.OsmandSettingsParams;
|
||||
|
||||
import net.osmand.aidl.gpx.AGpxFile;
|
||||
import net.osmand.aidl.gpx.AGpxFileDetails;
|
||||
import net.osmand.aidl.gpx.CreateGpxBitmapParams;
|
||||
import net.osmand.aidl.tiles.ASqliteDbFile;
|
||||
|
||||
import net.osmand.aidl.plugins.PluginParams;
|
||||
|
||||
// NOTE: Add new methods at the end of file!!!
|
||||
|
||||
interface IOsmAndAidlInterface {
|
||||
|
@ -133,4 +146,34 @@ interface IOsmAndAidlInterface {
|
|||
|
||||
long registerForUpdates(in long updateTimeMS, IOsmAndAidlCallback callback);
|
||||
boolean unregisterFromUpdates(in long callbackId);
|
||||
|
||||
boolean setNavDrawerLogo(in String imageUri);
|
||||
|
||||
boolean setEnabledIds(in List<String> ids);
|
||||
boolean setDisabledIds(in List<String> ids);
|
||||
boolean setEnabledPatterns(in List<String> patterns);
|
||||
boolean setDisabledPatterns(in List<String> patterns);
|
||||
|
||||
boolean regWidgetVisibility(in SetWidgetsParams params);
|
||||
boolean regWidgetAvailability(in SetWidgetsParams params);
|
||||
|
||||
boolean customizeOsmandSettings(in OsmandSettingsParams params);
|
||||
|
||||
boolean getImportedGpx(out List<AGpxFile> files);
|
||||
|
||||
boolean getSqliteDbFiles(out List<ASqliteDbFile> files);
|
||||
boolean getActiveSqliteDbFiles(out List<ASqliteDbFile> files);
|
||||
boolean showSqliteDbFile(String fileName);
|
||||
boolean hideSqliteDbFile(String fileName);
|
||||
|
||||
boolean setNavDrawerLogoWithParams(in NavDrawerHeaderParams params);
|
||||
boolean setNavDrawerFooterWithParams(in NavDrawerFooterParams params);
|
||||
|
||||
boolean restoreOsmand();
|
||||
|
||||
boolean changePluginState(in PluginParams params);
|
||||
|
||||
boolean registerForOsmandInitListener(in IOsmAndAidlCallback callback);
|
||||
|
||||
boolean getBitmapForGpx(in CreateGpxBitmapParams file, IOsmAndAidlCallback callback);
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
package net.osmand.aidl.customization;
|
||||
|
||||
parcelable OsmandSettingsParams;
|
|
@ -0,0 +1,60 @@
|
|||
package net.osmand.aidl.customization;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
public class OsmandSettingsParams implements Parcelable {
|
||||
|
||||
private String sharedPreferencesName;
|
||||
private Bundle bundle;
|
||||
|
||||
public OsmandSettingsParams(@NonNull String sharedPreferencesName, @Nullable Bundle bundle) {
|
||||
this.sharedPreferencesName = sharedPreferencesName;
|
||||
this.bundle = bundle;
|
||||
}
|
||||
|
||||
public OsmandSettingsParams(Parcel in) {
|
||||
readFromParcel(in);
|
||||
}
|
||||
|
||||
public static final Creator<OsmandSettingsParams> CREATOR = new Creator<OsmandSettingsParams>() {
|
||||
@Override
|
||||
public OsmandSettingsParams createFromParcel(Parcel in) {
|
||||
return new OsmandSettingsParams(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OsmandSettingsParams[] newArray(int size) {
|
||||
return new OsmandSettingsParams[size];
|
||||
}
|
||||
};
|
||||
|
||||
public String getSharedPreferencesName() {
|
||||
return sharedPreferencesName;
|
||||
}
|
||||
|
||||
public Bundle getBundle() {
|
||||
return bundle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel out, int flags) {
|
||||
out.writeString(sharedPreferencesName);
|
||||
out.writeBundle(bundle);
|
||||
}
|
||||
|
||||
@SuppressLint("ParcelClassLoader")
|
||||
private void readFromParcel(Parcel in) {
|
||||
sharedPreferencesName = in.readString();
|
||||
bundle = in.readBundle();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
package net.osmand.aidl.customization;
|
||||
|
||||
parcelable SetWidgetsParams;
|
|
@ -0,0 +1,93 @@
|
|||
package net.osmand.aidl.customization;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class SetWidgetsParams implements Parcelable {
|
||||
|
||||
private String widgetKey;
|
||||
private List<String> appModesKeys;
|
||||
|
||||
public SetWidgetsParams(String widgetKey, @Nullable List<String> appModesKeys) {
|
||||
this.widgetKey = widgetKey;
|
||||
this.appModesKeys = appModesKeys;
|
||||
}
|
||||
|
||||
public SetWidgetsParams(Parcel in) {
|
||||
readFromParcel(in);
|
||||
}
|
||||
|
||||
public static final Creator<SetWidgetsParams> CREATOR = new Creator<SetWidgetsParams>() {
|
||||
@Override
|
||||
public SetWidgetsParams createFromParcel(Parcel in) {
|
||||
return new SetWidgetsParams(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SetWidgetsParams[] newArray(int size) {
|
||||
return new SetWidgetsParams[size];
|
||||
}
|
||||
};
|
||||
|
||||
public String getWidgetKey() {
|
||||
return widgetKey;
|
||||
}
|
||||
|
||||
public List<String> getAppModesKeys() {
|
||||
return appModesKeys;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel out, int flags) {
|
||||
out.writeString(widgetKey);
|
||||
writeStringList(out, appModesKeys);
|
||||
}
|
||||
|
||||
private void readFromParcel(Parcel in) {
|
||||
widgetKey = in.readString();
|
||||
appModesKeys = readStringList(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
private void writeStringList(Parcel out, List<String> val) {
|
||||
if (val == null) {
|
||||
out.writeInt(-1);
|
||||
return;
|
||||
}
|
||||
int N = val.size();
|
||||
int i = 0;
|
||||
out.writeInt(N);
|
||||
while (i < N) {
|
||||
out.writeString(val.get(i));
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
private List<String> readStringList(Parcel in) {
|
||||
List<String> list = new ArrayList<>();
|
||||
int M = list.size();
|
||||
int N = in.readInt();
|
||||
if (N == -1) {
|
||||
return null;
|
||||
}
|
||||
int i = 0;
|
||||
for (; i < M && i < N; i++) {
|
||||
list.set(i, in.readString());
|
||||
}
|
||||
for (; i < N; i++) {
|
||||
list.add(in.readString());
|
||||
}
|
||||
for (; i < M; i++) {
|
||||
list.remove(N);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
4
OsmAnd-telegram/src/net/osmand/aidl/gpx/AGpxBitmap.aidl
Normal file
4
OsmAnd-telegram/src/net/osmand/aidl/gpx/AGpxBitmap.aidl
Normal file
|
@ -0,0 +1,4 @@
|
|||
package net.osmand.aidl.gpx;
|
||||
|
||||
parcelable AGpxBitmap;
|
||||
|
50
OsmAnd-telegram/src/net/osmand/aidl/gpx/AGpxBitmap.java
Normal file
50
OsmAnd-telegram/src/net/osmand/aidl/gpx/AGpxBitmap.java
Normal file
|
@ -0,0 +1,50 @@
|
|||
package net.osmand.aidl.gpx;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
public class AGpxBitmap implements Parcelable {
|
||||
|
||||
private Bitmap bitmap;
|
||||
|
||||
public AGpxBitmap(@NonNull Bitmap bitmap) {
|
||||
this.bitmap = bitmap;
|
||||
}
|
||||
|
||||
public AGpxBitmap(Parcel in) {
|
||||
readFromParcel(in);
|
||||
}
|
||||
|
||||
public Bitmap getBitmap() {
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
public void setBitmap(Bitmap bitmap) {
|
||||
this.bitmap = bitmap;
|
||||
}
|
||||
|
||||
public static final Creator<AGpxBitmap> CREATOR = new
|
||||
Creator<AGpxBitmap>() {
|
||||
public AGpxBitmap createFromParcel(Parcel in) {
|
||||
return new AGpxBitmap(in);
|
||||
}
|
||||
|
||||
public AGpxBitmap[] newArray(int size) {
|
||||
return new AGpxBitmap[size];
|
||||
}
|
||||
};
|
||||
|
||||
public void writeToParcel(Parcel out, int flags) {
|
||||
out.writeParcelable(bitmap, flags);
|
||||
}
|
||||
|
||||
private void readFromParcel(Parcel in) {
|
||||
bitmap = in.readParcelable(Bitmap.class.getClassLoader());
|
||||
}
|
||||
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
}
|
3
OsmAnd-telegram/src/net/osmand/aidl/gpx/AGpxFile.aidl
Normal file
3
OsmAnd-telegram/src/net/osmand/aidl/gpx/AGpxFile.aidl
Normal file
|
@ -0,0 +1,3 @@
|
|||
package net.osmand.aidl.gpx;
|
||||
|
||||
parcelable AGpxFile;
|
89
OsmAnd-telegram/src/net/osmand/aidl/gpx/AGpxFile.java
Normal file
89
OsmAnd-telegram/src/net/osmand/aidl/gpx/AGpxFile.java
Normal file
|
@ -0,0 +1,89 @@
|
|||
package net.osmand.aidl.gpx;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
public class AGpxFile implements Parcelable {
|
||||
|
||||
private String fileName;
|
||||
private long modifiedTime;
|
||||
private long fileSize;
|
||||
private boolean active;
|
||||
private AGpxFileDetails details;
|
||||
|
||||
public AGpxFile(@NonNull String fileName, long modifiedTime, long fileSize, boolean active, @Nullable AGpxFileDetails details) {
|
||||
this.fileName = fileName;
|
||||
this.modifiedTime = modifiedTime;
|
||||
this.fileSize = fileSize;
|
||||
this.active = active;
|
||||
this.details = details;
|
||||
}
|
||||
|
||||
public AGpxFile(Parcel in) {
|
||||
readFromParcel(in);
|
||||
}
|
||||
|
||||
public static final Creator<AGpxFile> CREATOR = new
|
||||
Creator<AGpxFile>() {
|
||||
public AGpxFile createFromParcel(Parcel in) {
|
||||
return new AGpxFile(in);
|
||||
}
|
||||
|
||||
public AGpxFile[] newArray(int size) {
|
||||
return new AGpxFile[size];
|
||||
}
|
||||
};
|
||||
|
||||
public String getFileName() {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
public long getModifiedTime() {
|
||||
return modifiedTime;
|
||||
}
|
||||
|
||||
public long getFileSize() {
|
||||
return fileSize;
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
return active;
|
||||
}
|
||||
|
||||
public AGpxFileDetails getDetails() {
|
||||
return details;
|
||||
}
|
||||
|
||||
public void writeToParcel(Parcel out, int flags) {
|
||||
out.writeString(fileName);
|
||||
out.writeLong(modifiedTime);
|
||||
out.writeLong(fileSize);
|
||||
out.writeByte((byte) (active ? 1 : 0));
|
||||
|
||||
out.writeByte((byte) (details != null ? 1 : 0));
|
||||
if (details != null) {
|
||||
out.writeParcelable(details, flags);
|
||||
}
|
||||
}
|
||||
|
||||
private void readFromParcel(Parcel in) {
|
||||
fileName = in.readString();
|
||||
modifiedTime = in.readLong();
|
||||
fileSize = in.readLong();
|
||||
active = in.readByte() != 0;
|
||||
|
||||
boolean hasDetails= in.readByte() != 0;
|
||||
if (hasDetails) {
|
||||
details = in.readParcelable(AGpxFileDetails.class.getClassLoader());
|
||||
} else {
|
||||
details = null;
|
||||
}
|
||||
}
|
||||
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
package net.osmand.aidl.gpx;
|
||||
|
||||
parcelable AGpxFileDetails;
|
196
OsmAnd-telegram/src/net/osmand/aidl/gpx/AGpxFileDetails.java
Normal file
196
OsmAnd-telegram/src/net/osmand/aidl/gpx/AGpxFileDetails.java
Normal file
|
@ -0,0 +1,196 @@
|
|||
package net.osmand.aidl.gpx;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class AGpxFileDetails implements Parcelable {
|
||||
|
||||
private float totalDistance = 0;
|
||||
private int totalTracks = 0;
|
||||
private long startTime = Long.MAX_VALUE;
|
||||
private long endTime = Long.MIN_VALUE;
|
||||
private long timeSpan = 0;
|
||||
private long timeMoving = 0;
|
||||
private float totalDistanceMoving = 0;
|
||||
|
||||
private double diffElevationUp = 0;
|
||||
private double diffElevationDown = 0;
|
||||
private double avgElevation = 0;
|
||||
private double minElevation = 99999;
|
||||
private double maxElevation = -100;
|
||||
|
||||
private float minSpeed = Float.MAX_VALUE;
|
||||
private float maxSpeed = 0;
|
||||
private float avgSpeed;
|
||||
|
||||
private int points;
|
||||
private int wptPoints = 0;
|
||||
|
||||
private List<String> wptCategoryNames = new ArrayList<>();
|
||||
|
||||
public AGpxFileDetails(float totalDistance, int totalTracks,
|
||||
long startTime, long endTime,
|
||||
long timeSpan, long timeMoving, float totalDistanceMoving,
|
||||
double diffElevationUp, double diffElevationDown,
|
||||
double avgElevation, double minElevation, double maxElevation,
|
||||
float minSpeed, float maxSpeed, float avgSpeed,
|
||||
int points, int wptPoints, Set<String> wptCategoryNames) {
|
||||
this.totalDistance = totalDistance;
|
||||
this.totalTracks = totalTracks;
|
||||
this.startTime = startTime;
|
||||
this.endTime = endTime;
|
||||
this.timeSpan = timeSpan;
|
||||
this.timeMoving = timeMoving;
|
||||
this.totalDistanceMoving = totalDistanceMoving;
|
||||
this.diffElevationUp = diffElevationUp;
|
||||
this.diffElevationDown = diffElevationDown;
|
||||
this.avgElevation = avgElevation;
|
||||
this.minElevation = minElevation;
|
||||
this.maxElevation = maxElevation;
|
||||
this.minSpeed = minSpeed;
|
||||
this.maxSpeed = maxSpeed;
|
||||
this.avgSpeed = avgSpeed;
|
||||
this.points = points;
|
||||
this.wptPoints = wptPoints;
|
||||
if (wptCategoryNames != null) {
|
||||
this.wptCategoryNames = new ArrayList<>(wptCategoryNames);
|
||||
}
|
||||
}
|
||||
|
||||
public AGpxFileDetails(Parcel in) {
|
||||
readFromParcel(in);
|
||||
}
|
||||
|
||||
public static final Creator<AGpxFileDetails> CREATOR = new
|
||||
Creator<AGpxFileDetails>() {
|
||||
public AGpxFileDetails createFromParcel(Parcel in) {
|
||||
return new AGpxFileDetails(in);
|
||||
}
|
||||
|
||||
public AGpxFileDetails[] newArray(int size) {
|
||||
return new AGpxFileDetails[size];
|
||||
}
|
||||
};
|
||||
|
||||
public float getTotalDistance() {
|
||||
return totalDistance;
|
||||
}
|
||||
|
||||
public int getTotalTracks() {
|
||||
return totalTracks;
|
||||
}
|
||||
|
||||
public long getStartTime() {
|
||||
return startTime;
|
||||
}
|
||||
|
||||
public long getEndTime() {
|
||||
return endTime;
|
||||
}
|
||||
|
||||
public long getTimeSpan() {
|
||||
return timeSpan;
|
||||
}
|
||||
|
||||
public long getTimeMoving() {
|
||||
return timeMoving;
|
||||
}
|
||||
|
||||
public float getTotalDistanceMoving() {
|
||||
return totalDistanceMoving;
|
||||
}
|
||||
|
||||
public double getDiffElevationUp() {
|
||||
return diffElevationUp;
|
||||
}
|
||||
|
||||
public double getDiffElevationDown() {
|
||||
return diffElevationDown;
|
||||
}
|
||||
|
||||
public double getAvgElevation() {
|
||||
return avgElevation;
|
||||
}
|
||||
|
||||
public double getMinElevation() {
|
||||
return minElevation;
|
||||
}
|
||||
|
||||
public double getMaxElevation() {
|
||||
return maxElevation;
|
||||
}
|
||||
|
||||
public float getMinSpeed() {
|
||||
return minSpeed;
|
||||
}
|
||||
|
||||
public float getMaxSpeed() {
|
||||
return maxSpeed;
|
||||
}
|
||||
|
||||
public float getAvgSpeed() {
|
||||
return avgSpeed;
|
||||
}
|
||||
|
||||
public int getPoints() {
|
||||
return points;
|
||||
}
|
||||
|
||||
public int getWptPoints() {
|
||||
return wptPoints;
|
||||
}
|
||||
|
||||
public List<String> getWptCategoryNames() {
|
||||
return wptCategoryNames;
|
||||
}
|
||||
|
||||
public void writeToParcel(Parcel out, int flags) {
|
||||
out.writeFloat(totalDistance);
|
||||
out.writeInt(totalTracks);
|
||||
out.writeLong(startTime);
|
||||
out.writeLong(endTime);
|
||||
out.writeLong(timeSpan);
|
||||
out.writeLong(timeMoving);
|
||||
out.writeFloat(totalDistanceMoving);
|
||||
out.writeDouble(diffElevationUp);
|
||||
out.writeDouble(diffElevationDown);
|
||||
out.writeDouble(avgElevation);
|
||||
out.writeDouble(minElevation);
|
||||
out.writeDouble(maxElevation);
|
||||
out.writeFloat(minSpeed);
|
||||
out.writeFloat(maxSpeed);
|
||||
out.writeFloat(avgSpeed);
|
||||
out.writeInt(points);
|
||||
out.writeInt(wptPoints);
|
||||
out.writeStringList(wptCategoryNames);
|
||||
}
|
||||
|
||||
private void readFromParcel(Parcel in) {
|
||||
totalDistance = in.readFloat();
|
||||
totalTracks = in.readInt();
|
||||
startTime = in.readLong();
|
||||
endTime = in.readLong();
|
||||
timeSpan = in.readLong();
|
||||
timeMoving = in.readLong();
|
||||
totalDistanceMoving = in.readFloat();
|
||||
diffElevationUp = in.readDouble();
|
||||
diffElevationDown = in.readDouble();
|
||||
avgElevation = in.readDouble();
|
||||
minElevation = in.readDouble();
|
||||
maxElevation = in.readDouble();
|
||||
minSpeed = in.readFloat();
|
||||
maxSpeed = in.readFloat();
|
||||
avgSpeed = in.readFloat();
|
||||
points = in.readInt();
|
||||
wptPoints = in.readInt();
|
||||
in.readStringList(wptCategoryNames);
|
||||
}
|
||||
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
package net.osmand.aidl.gpx;
|
||||
|
||||
parcelable CreateGpxBitmapParams;
|
|
@ -0,0 +1,101 @@
|
|||
package net.osmand.aidl.gpx;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class CreateGpxBitmapParams implements Parcelable {
|
||||
|
||||
private File gpxFile;
|
||||
private Uri gpxUri;
|
||||
private float density;
|
||||
private int widthPixels;
|
||||
private int heightPixels;
|
||||
private int color; //ARGB color int
|
||||
|
||||
public CreateGpxBitmapParams(File gpxFile, float density, int widthPixels, int heightPixels, int color) {
|
||||
this.gpxFile = gpxFile;
|
||||
this.density = density;
|
||||
this.widthPixels = widthPixels;
|
||||
this.heightPixels = heightPixels;
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
public CreateGpxBitmapParams(Uri gpxUri, float density, int widthPixels, int heightPixels, int color) {
|
||||
this.gpxUri = gpxUri;
|
||||
this.density = density;
|
||||
this.widthPixels = widthPixels;
|
||||
this.heightPixels = heightPixels;
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
public CreateGpxBitmapParams(Parcel in) {
|
||||
readFromParcel(in);
|
||||
}
|
||||
|
||||
public static final Creator<CreateGpxBitmapParams> CREATOR = new
|
||||
Creator<CreateGpxBitmapParams>() {
|
||||
public CreateGpxBitmapParams createFromParcel(Parcel in) {
|
||||
return new CreateGpxBitmapParams(in);
|
||||
}
|
||||
|
||||
public CreateGpxBitmapParams[] newArray(int size) {
|
||||
return new CreateGpxBitmapParams[size];
|
||||
}
|
||||
};
|
||||
|
||||
public File getGpxFile() {
|
||||
return gpxFile;
|
||||
}
|
||||
|
||||
public Uri getGpxUri() {
|
||||
return gpxUri;
|
||||
}
|
||||
|
||||
public int getWidthPixels() {
|
||||
return widthPixels;
|
||||
}
|
||||
|
||||
public int getHeightPixels() {
|
||||
return heightPixels;
|
||||
}
|
||||
|
||||
public float getDensity() {
|
||||
return density;
|
||||
}
|
||||
|
||||
public int getColor() {
|
||||
return color;
|
||||
}
|
||||
|
||||
public void writeToParcel(Parcel out, int flags) {
|
||||
if (gpxFile != null) {
|
||||
out.writeString(gpxFile.getAbsolutePath());
|
||||
} else {
|
||||
out.writeString(null);
|
||||
}
|
||||
out.writeParcelable(gpxUri, flags);
|
||||
out.writeFloat(density);
|
||||
out.writeInt(widthPixels);
|
||||
out.writeInt(heightPixels);
|
||||
out.writeInt(color);
|
||||
}
|
||||
|
||||
private void readFromParcel(Parcel in) {
|
||||
String gpxAbsolutePath = in.readString();
|
||||
if (gpxAbsolutePath != null) {
|
||||
gpxFile = new File(gpxAbsolutePath);
|
||||
}
|
||||
gpxUri = in.readParcelable(Uri.class.getClassLoader());
|
||||
density = in.readFloat();
|
||||
widthPixels = in.readInt();
|
||||
heightPixels = in.readInt();
|
||||
color = in.readInt();
|
||||
}
|
||||
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
package net.osmand.aidl.navdrawer;
|
||||
|
||||
parcelable NavDrawerFooterParams;
|
|
@ -0,0 +1,68 @@
|
|||
package net.osmand.aidl.navdrawer;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
public class NavDrawerFooterParams implements Parcelable {
|
||||
|
||||
@NonNull
|
||||
private String packageName;
|
||||
@Nullable
|
||||
private String intent;
|
||||
@Nullable
|
||||
private String appName;
|
||||
|
||||
@NonNull
|
||||
public String getPackageName() {
|
||||
return packageName;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getIntent() {
|
||||
return intent;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getAppName() {
|
||||
return appName;
|
||||
}
|
||||
|
||||
public NavDrawerFooterParams(@NonNull String packageName, @Nullable String intent,
|
||||
@Nullable String appName) {
|
||||
this.packageName = packageName;
|
||||
this.intent = intent;
|
||||
this.appName = appName;
|
||||
}
|
||||
|
||||
protected NavDrawerFooterParams(Parcel in) {
|
||||
packageName = in.readString();
|
||||
intent = in.readString();
|
||||
appName = in.readString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeString(packageName);
|
||||
dest.writeString(intent);
|
||||
dest.writeString(appName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static final Creator<NavDrawerFooterParams> CREATOR = new Creator<NavDrawerFooterParams>() {
|
||||
@Override
|
||||
public NavDrawerFooterParams createFromParcel(Parcel in) {
|
||||
return new NavDrawerFooterParams(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NavDrawerFooterParams[] newArray(int size) {
|
||||
return new NavDrawerFooterParams[size];
|
||||
}
|
||||
};
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
package net.osmand.aidl.navdrawer;
|
||||
|
||||
parcelable NavDrawerHeaderParams;
|
|
@ -0,0 +1,68 @@
|
|||
package net.osmand.aidl.navdrawer;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
public class NavDrawerHeaderParams implements Parcelable {
|
||||
|
||||
@NonNull
|
||||
private String imageUri;
|
||||
@NonNull
|
||||
private String packageName;
|
||||
@Nullable
|
||||
private String intent;
|
||||
|
||||
@NonNull
|
||||
public String getImageUri() {
|
||||
return imageUri;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public String getPackageName() {
|
||||
return packageName;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getIntent() {
|
||||
return intent;
|
||||
}
|
||||
|
||||
public NavDrawerHeaderParams(@NonNull String imageUri, @NonNull String packageName,
|
||||
@Nullable String intent) {
|
||||
this.imageUri = imageUri;
|
||||
this.packageName = packageName;
|
||||
this.intent = intent;
|
||||
}
|
||||
|
||||
public NavDrawerHeaderParams(Parcel in) {
|
||||
imageUri = in.readString();
|
||||
packageName = in.readString();
|
||||
intent = in.readString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeString(imageUri);
|
||||
dest.writeString(packageName);
|
||||
dest.writeString(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static final Creator<NavDrawerHeaderParams> CREATOR = new Creator<NavDrawerHeaderParams>() {
|
||||
@Override
|
||||
public NavDrawerHeaderParams createFromParcel(Parcel in) {
|
||||
return new NavDrawerHeaderParams(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NavDrawerHeaderParams[] newArray(int size) {
|
||||
return new NavDrawerHeaderParams[size];
|
||||
}
|
||||
};
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
// PluginParams.aidl
|
||||
package net.osmand.aidl.plugins;
|
||||
|
||||
parcelable PluginParams;
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
package net.osmand.aidl.plugins;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
public class PluginParams implements Parcelable {
|
||||
|
||||
private String pluginId;
|
||||
private int newState; //0- off, 1 - on
|
||||
|
||||
public PluginParams(String pluginId, int newState) {
|
||||
this.pluginId = pluginId;
|
||||
this.newState = newState;
|
||||
}
|
||||
|
||||
public String getPluginId() {
|
||||
return pluginId;
|
||||
}
|
||||
|
||||
public int getNewState() {
|
||||
return newState;
|
||||
}
|
||||
|
||||
protected PluginParams(Parcel in) {
|
||||
pluginId = in.readString();
|
||||
newState = in.readInt();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeString(pluginId);
|
||||
dest.writeInt(newState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static final Creator<PluginParams> CREATOR = new Creator<PluginParams>() {
|
||||
@Override
|
||||
public PluginParams createFromParcel(Parcel in) {
|
||||
return new PluginParams(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PluginParams[] newArray(int size) {
|
||||
return new PluginParams[size];
|
||||
}
|
||||
};
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
package net.osmand.aidl.tiles;
|
||||
|
||||
parcelable ASqliteDbFile;
|
69
OsmAnd-telegram/src/net/osmand/aidl/tiles/ASqliteDbFile.java
Normal file
69
OsmAnd-telegram/src/net/osmand/aidl/tiles/ASqliteDbFile.java
Normal file
|
@ -0,0 +1,69 @@
|
|||
package net.osmand.aidl.tiles;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
public class ASqliteDbFile implements Parcelable {
|
||||
|
||||
private String fileName;
|
||||
private long modifiedTime;
|
||||
private long fileSize;
|
||||
private boolean active;
|
||||
|
||||
public ASqliteDbFile(@NonNull String fileName, long modifiedTime, long fileSize, boolean active) {
|
||||
this.fileName = fileName;
|
||||
this.modifiedTime = modifiedTime;
|
||||
this.fileSize = fileSize;
|
||||
this.active = active;
|
||||
}
|
||||
|
||||
public ASqliteDbFile(Parcel in) {
|
||||
readFromParcel(in);
|
||||
}
|
||||
|
||||
public static final Creator<ASqliteDbFile> CREATOR = new
|
||||
Creator<ASqliteDbFile>() {
|
||||
public ASqliteDbFile createFromParcel(Parcel in) {
|
||||
return new ASqliteDbFile(in);
|
||||
}
|
||||
|
||||
public ASqliteDbFile[] newArray(int size) {
|
||||
return new ASqliteDbFile[size];
|
||||
}
|
||||
};
|
||||
|
||||
public String getFileName() {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
public long getModifiedTime() {
|
||||
return modifiedTime;
|
||||
}
|
||||
|
||||
public long getFileSize() {
|
||||
return fileSize;
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
return active;
|
||||
}
|
||||
|
||||
public void writeToParcel(Parcel out, int flags) {
|
||||
out.writeString(fileName);
|
||||
out.writeLong(modifiedTime);
|
||||
out.writeLong(fileSize);
|
||||
out.writeByte((byte) (active ? 1 : 0));
|
||||
}
|
||||
|
||||
private void readFromParcel(Parcel in) {
|
||||
fileName = in.readString();
|
||||
modifiedTime = in.readLong();
|
||||
fileSize = in.readLong();
|
||||
active = in.readByte() != 0;
|
||||
}
|
||||
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
}
|
|
@ -79,6 +79,8 @@ private const val SHARE_CHATS_INFO_KEY = "share_chats_info"
|
|||
|
||||
private const val BATTERY_OPTIMISATION_ASKED = "battery_optimisation_asked"
|
||||
|
||||
private const val MONITORING_ENABLED = "monitoring_enabled"
|
||||
|
||||
private const val SHARING_INITIALIZATION_TIME = 60 * 2L // 2 minutes
|
||||
|
||||
private const val GPS_UPDATE_EXPIRED_TIME = 60 * 3L // 3 minutes
|
||||
|
@ -111,6 +113,8 @@ class TelegramSettings(private val app: TelegramApplication) {
|
|||
|
||||
var batteryOptimisationAsked = false
|
||||
|
||||
var monitoringEnabled = false
|
||||
|
||||
init {
|
||||
updatePrefs()
|
||||
read()
|
||||
|
@ -435,6 +439,8 @@ class TelegramSettings(private val app: TelegramApplication) {
|
|||
|
||||
edit.putBoolean(BATTERY_OPTIMISATION_ASKED, batteryOptimisationAsked)
|
||||
|
||||
edit.putBoolean(MONITORING_ENABLED, monitoringEnabled)
|
||||
|
||||
val jArray = convertShareChatsInfoToJson()
|
||||
if (jArray != null) {
|
||||
edit.putString(SHARE_CHATS_INFO_KEY, jArray.toString())
|
||||
|
@ -491,6 +497,8 @@ class TelegramSettings(private val app: TelegramApplication) {
|
|||
)
|
||||
|
||||
batteryOptimisationAsked = prefs.getBoolean(BATTERY_OPTIMISATION_ASKED,false)
|
||||
|
||||
monitoringEnabled = prefs.getBoolean(MONITORING_ENABLED,false)
|
||||
}
|
||||
|
||||
private fun convertShareDevicesToJson():JSONObject?{
|
||||
|
|
|
@ -75,6 +75,12 @@ class OsmandAidlHelper(private val app: TelegramApplication) {
|
|||
fun onSearchComplete(resultSet: List<SearchResult>)
|
||||
}
|
||||
|
||||
private var gpxBitmapCreatedListener: GpxBitmapCreatedListener? = null
|
||||
|
||||
interface GpxBitmapCreatedListener {
|
||||
fun onGpxBitmapCreated(bitmap: AGpxBitmap)
|
||||
}
|
||||
|
||||
private val mIOsmAndAidlCallback = object : IOsmAndAidlCallback.Stub() {
|
||||
|
||||
@Throws(RemoteException::class)
|
||||
|
@ -90,12 +96,26 @@ class OsmandAidlHelper(private val app: TelegramApplication) {
|
|||
mUpdatesListener!!.update()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onAppInitialized() {
|
||||
|
||||
}
|
||||
|
||||
override fun onGpxBitmapCreated(bitmap: AGpxBitmap) {
|
||||
if (gpxBitmapCreatedListener != null) {
|
||||
gpxBitmapCreatedListener!!.onGpxBitmapCreated(bitmap)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun setSearchCompleteListener(mSearchCompleteListener: SearchCompleteListener) {
|
||||
this.mSearchCompleteListener = mSearchCompleteListener
|
||||
}
|
||||
|
||||
fun setGpxBitmapCreatedListener(gpxBitmapCreatedListener: GpxBitmapCreatedListener) {
|
||||
this.gpxBitmapCreatedListener = gpxBitmapCreatedListener
|
||||
}
|
||||
|
||||
private var mUpdatesListener: UpdatesListener? = null
|
||||
|
||||
interface UpdatesListener {
|
||||
|
@ -1059,4 +1079,16 @@ class OsmandAidlHelper(private val app: TelegramApplication) {
|
|||
}
|
||||
return false
|
||||
}
|
||||
|
||||
fun getBitmapForGpx(gpxUri: Uri, density: Float, widthPixels: Int, heightPixels: Int, color: Int): Boolean {
|
||||
if (mIOsmAndAidlInterface != null) {
|
||||
try {
|
||||
app.grantUriPermission(app.settings.appToConnectPackage, gpxUri, Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||
return mIOsmAndAidlInterface!!.getBitmapForGpx(CreateGpxBitmapParams(gpxUri, density, widthPixels, heightPixels, color), mIOsmAndAidlCallback)
|
||||
} catch (e: RemoteException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@ import android.os.AsyncTask;
|
|||
|
||||
import net.osmand.PlatformUtil;
|
||||
import net.osmand.telegram.TelegramApplication;
|
||||
import net.osmand.telegram.ui.LiveNowTabFragment;
|
||||
import net.osmand.telegram.utils.GPXUtilities;
|
||||
import net.osmand.telegram.utils.GPXUtilities.GPXFile;
|
||||
import net.osmand.telegram.utils.GPXUtilities.Track;
|
||||
|
@ -19,7 +18,6 @@ import org.drinkless.td.libcore.telegram.TdApi;
|
|||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
|
@ -50,7 +48,7 @@ public class SavingTracksDbHelper extends SQLiteOpenHelper {
|
|||
+ TRACK_COL_ALTITUDE + " double, " + TRACK_COL_SPEED + " double, " //$NON-NLS-1$ //$NON-NLS-2$
|
||||
+ TRACK_COL_HDOP + " double, " + TRACK_COL_DATE + " long, " + TRACK_COL_TEXT_INFO + " int )";
|
||||
|
||||
public final static Log log = PlatformUtil.getLog(SavingTracksDbHelper.class);
|
||||
private final static Log log = PlatformUtil.getLog(SavingTracksDbHelper.class);
|
||||
|
||||
private final TelegramApplication app;
|
||||
|
||||
|
@ -110,23 +108,32 @@ public class SavingTracksDbHelper extends SQLiteOpenHelper {
|
|||
}
|
||||
}
|
||||
|
||||
public void saveAsyncUserDataToGpx(LiveNowTabFragment fragment, File dir, int userId, long interval) {
|
||||
GPXFile gpxFile = app.getSavingTracksDbHelper().collectRecordedDataForUser(userId, interval);
|
||||
public void saveUserDataToGpx(SaveGpxListener listener, File dir, int userId, long chatId, long start, long end) {
|
||||
GPXFile gpxFile = collectRecordedDataForUserAndChat(userId, chatId, start, end);
|
||||
if (gpxFile != null && !gpxFile.isEmpty()) {
|
||||
SaveGPXTrackToFileTask task = new SaveGPXTrackToFileTask(fragment, gpxFile, dir, userId);
|
||||
SaveGPXTrackToFileTask task = new SaveGPXTrackToFileTask(app, listener, gpxFile, dir, userId);
|
||||
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
}
|
||||
|
||||
public void saveGpx(SaveGpxListener listener, File dir, GPXFile gpxFile) {
|
||||
if (gpxFile != null && !gpxFile.isEmpty()) {
|
||||
SaveGPXTrackToFileTask task = new SaveGPXTrackToFileTask(app, listener, gpxFile, dir, 0);
|
||||
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateLocationMessage(TdApi.Message message) {
|
||||
log.debug(message);
|
||||
TdApi.MessageContent content = message.content;
|
||||
int senderId = app.getTelegramHelper().getSenderMessageId(message);
|
||||
if (content instanceof TdApi.MessageLocation) {
|
||||
long lastTextMessageUpdate = getLastTextTrackPointTimeForUser(message.senderUserId);
|
||||
long currentTime = System.currentTimeMillis();
|
||||
if (lastTextMessageUpdate == 0 || currentTime - lastTextMessageUpdate < 10 * 1000) {
|
||||
log.debug("Add map message" + message.senderUserId);
|
||||
log.debug("Add map message " + message.senderUserId);
|
||||
TdApi.MessageLocation messageLocation = (TdApi.MessageLocation) content;
|
||||
insertData(message.senderUserId, message.chatId, messageLocation.location.latitude,
|
||||
insertData(senderId, message.chatId, messageLocation.location.latitude,
|
||||
messageLocation.location.longitude, 0.0, 0.0, 0.0,
|
||||
Math.max(message.date, message.editDate), 0);
|
||||
} else {
|
||||
|
@ -135,7 +142,7 @@ public class SavingTracksDbHelper extends SQLiteOpenHelper {
|
|||
} else if (content instanceof TelegramHelper.MessageLocation) {
|
||||
log.debug("Add text message " + message.senderUserId);
|
||||
TelegramHelper.MessageLocation messageLocation = (TelegramHelper.MessageLocation) content;
|
||||
insertData(message.senderUserId, message.chatId, messageLocation.getLat(), messageLocation.getLon(),
|
||||
insertData(senderId, message.chatId, messageLocation.getLat(), messageLocation.getLon(),
|
||||
messageLocation.getAltitude(), messageLocation.getSpeed(), messageLocation.getHdop(),
|
||||
messageLocation.getLastUpdated() * 1000L, 1);
|
||||
}
|
||||
|
@ -181,12 +188,12 @@ public class SavingTracksDbHelper extends SQLiteOpenHelper {
|
|||
return res;
|
||||
}
|
||||
|
||||
private GPXFile collectRecordedDataForUser(int userId, long interval) {
|
||||
public GPXFile collectRecordedDataForUserAndChat(int userId, long chatId, long start, long end) {
|
||||
GPXFile gpxFile = null;
|
||||
SQLiteDatabase db = getReadableDatabase();
|
||||
if (db != null && db.isOpen()) {
|
||||
try {
|
||||
gpxFile = collectDBTracksForUser(db, userId, interval);
|
||||
gpxFile = collectDBTracksForUser(db, userId, chatId, start, end);
|
||||
} finally {
|
||||
db.close();
|
||||
}
|
||||
|
@ -194,21 +201,52 @@ public class SavingTracksDbHelper extends SQLiteOpenHelper {
|
|||
return gpxFile;
|
||||
}
|
||||
|
||||
private GPXFile collectDBTracksForUser(SQLiteDatabase db, int userId, long interval) {
|
||||
Cursor query = db.rawQuery("SELECT " + TRACK_COL_USER_ID + "," + TRACK_COL_CHAT_ID + "," + TRACK_COL_LAT + "," + TRACK_COL_LON + "," + TRACK_COL_ALTITUDE + "," //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$
|
||||
+ TRACK_COL_SPEED + "," + TRACK_COL_HDOP + "," + TRACK_COL_DATE + " FROM " + TRACK_NAME +
|
||||
" WHERE " + TRACK_COL_USER_ID + " = ? ORDER BY " + TRACK_COL_DATE + " ASC ", new String[]{String.valueOf(userId)}); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
|
||||
public GPXFile collectRecordedDataForUser(int userId, long chatId, long start, long end) {
|
||||
GPXFile gpxFile = null;
|
||||
SQLiteDatabase db = getReadableDatabase();
|
||||
if (db != null && db.isOpen()) {
|
||||
try {
|
||||
if (chatId == 0) {
|
||||
gpxFile = collectDBTracksForUser(db, userId, start, end);
|
||||
} else {
|
||||
gpxFile = collectDBTracksForUser(db, userId, chatId, start, end);
|
||||
}
|
||||
} finally {
|
||||
db.close();
|
||||
}
|
||||
}
|
||||
return gpxFile;
|
||||
}
|
||||
|
||||
public ArrayList<GPXFile> collectRecordedDataForUsers(long start, long end, ArrayList<Integer> ignoredUsersIds) {
|
||||
ArrayList<GPXFile> data = new ArrayList<>();
|
||||
SQLiteDatabase db = getReadableDatabase();
|
||||
if (db != null && db.isOpen()) {
|
||||
try {
|
||||
collectDBTracksForUsers(db, data, start, end, ignoredUsersIds);
|
||||
} finally {
|
||||
db.close();
|
||||
}
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
private GPXFile collectDBTracksForUser(SQLiteDatabase db, int userId, long chatId, long start, long end) {
|
||||
Cursor query = db.rawQuery("SELECT " + TRACK_COL_USER_ID + "," + TRACK_COL_CHAT_ID + ","
|
||||
+ TRACK_COL_LAT + "," + TRACK_COL_LON + "," + TRACK_COL_ALTITUDE + "," + TRACK_COL_SPEED + ","
|
||||
+ TRACK_COL_HDOP + "," + TRACK_COL_DATE + " FROM " + TRACK_NAME + " WHERE " + TRACK_COL_USER_ID + " = ?"
|
||||
+ " AND " + TRACK_COL_CHAT_ID + " = ?" + " AND " + TRACK_COL_DATE + " BETWEEN " + start + " AND " + end
|
||||
+ " ORDER BY " + TRACK_COL_DATE + " ASC ", new String[]{String.valueOf(userId), String.valueOf(chatId)});
|
||||
|
||||
GPXFile gpxFile = new GPXFile();
|
||||
gpxFile.chatId = chatId;
|
||||
gpxFile.userId = userId;
|
||||
long previousTime = 0;
|
||||
TrkSegment segment = null;
|
||||
Track track = null;
|
||||
if (query.moveToFirst()) {
|
||||
do {
|
||||
long time = query.getLong(7);
|
||||
long curTime = System.currentTimeMillis();
|
||||
if (curTime - time > interval) {
|
||||
continue;
|
||||
}
|
||||
WptPt pt = new WptPt();
|
||||
pt.userId = query.getInt(0);
|
||||
pt.chatId = query.getLong(1);
|
||||
|
@ -244,19 +282,135 @@ public class SavingTracksDbHelper extends SQLiteOpenHelper {
|
|||
return gpxFile;
|
||||
}
|
||||
|
||||
private GPXFile collectDBTracksForUser(SQLiteDatabase db, int userId, long start, long end) {
|
||||
Cursor query = db.rawQuery("SELECT " + TRACK_COL_USER_ID + "," + TRACK_COL_CHAT_ID + ","
|
||||
+ TRACK_COL_LAT + "," + TRACK_COL_LON + "," + TRACK_COL_ALTITUDE + "," + TRACK_COL_SPEED + ","
|
||||
+ TRACK_COL_HDOP + "," + TRACK_COL_DATE + " FROM " + TRACK_NAME + " WHERE " + TRACK_COL_USER_ID + " = ?"
|
||||
+ " AND " + TRACK_COL_DATE + " BETWEEN " + start + " AND " + end
|
||||
+ " ORDER BY " + TRACK_COL_DATE + " ASC ", new String[]{String.valueOf(userId)});
|
||||
|
||||
GPXFile gpxFile = new GPXFile();
|
||||
gpxFile.userId = userId;
|
||||
long previousTime = 0;
|
||||
TrkSegment segment = null;
|
||||
Track track = null;
|
||||
if (query.moveToFirst()) {
|
||||
do {
|
||||
long time = query.getLong(7);
|
||||
WptPt pt = new WptPt();
|
||||
pt.userId = query.getInt(0);
|
||||
pt.chatId = query.getLong(1);
|
||||
pt.lat = query.getDouble(2);
|
||||
pt.lon = query.getDouble(3);
|
||||
pt.ele = query.getDouble(4);
|
||||
pt.speed = query.getDouble(5);
|
||||
pt.hdop = query.getDouble(6);
|
||||
pt.time = time;
|
||||
long currentInterval = Math.abs(time - previousTime);
|
||||
|
||||
if (track != null) {
|
||||
if (currentInterval < 30 * 60 * 1000) {
|
||||
// 30 minute - same segment
|
||||
segment.points.add(pt);
|
||||
} else {
|
||||
segment = new TrkSegment();
|
||||
segment.points.add(pt);
|
||||
track.segments.add(segment);
|
||||
}
|
||||
} else {
|
||||
track = new Track();
|
||||
segment = new TrkSegment();
|
||||
track.segments.add(segment);
|
||||
segment.points.add(pt);
|
||||
|
||||
gpxFile.tracks.add(track);
|
||||
}
|
||||
previousTime = time;
|
||||
} while (query.moveToNext());
|
||||
}
|
||||
query.close();
|
||||
return gpxFile;
|
||||
}
|
||||
|
||||
private void collectDBTracksForUsers(SQLiteDatabase db, ArrayList<GPXFile> dataTracks, long start, long end, ArrayList<Integer> ignoredUsersIds) {
|
||||
Cursor query = db.rawQuery("SELECT " + TRACK_COL_USER_ID + "," + TRACK_COL_CHAT_ID + ","
|
||||
+ TRACK_COL_LAT + "," + TRACK_COL_LON + "," + TRACK_COL_ALTITUDE + "," + TRACK_COL_SPEED + ","
|
||||
+ TRACK_COL_HDOP + "," + TRACK_COL_DATE + " FROM " + TRACK_NAME + " WHERE " + TRACK_COL_DATE
|
||||
+ " BETWEEN " + start + " AND " + end + " ORDER BY " + TRACK_COL_USER_ID + " ASC, "
|
||||
+ TRACK_COL_CHAT_ID + " ASC, " + TRACK_COL_DATE + " ASC ", null);
|
||||
|
||||
long previousTime = 0;
|
||||
long previousChatId = 0;
|
||||
int previousUserId = 0;
|
||||
TrkSegment segment = null;
|
||||
Track track = null;
|
||||
GPXFile gpx = new GPXFile();
|
||||
if (query.moveToFirst()) {
|
||||
do {
|
||||
int userId = query.getInt(0);
|
||||
if (ignoredUsersIds.contains(userId)) {
|
||||
continue;
|
||||
}
|
||||
int chatId = query.getInt(1);
|
||||
long time = query.getLong(7);
|
||||
if (previousUserId != userId || previousChatId != chatId) {
|
||||
gpx = new GPXFile();
|
||||
gpx.chatId = chatId;
|
||||
gpx.userId = userId;
|
||||
previousTime = 0;
|
||||
track = null;
|
||||
segment = null;
|
||||
dataTracks.add(gpx);
|
||||
}
|
||||
|
||||
WptPt pt = new WptPt();
|
||||
pt.userId = userId;
|
||||
pt.chatId = chatId;
|
||||
pt.lat = query.getDouble(2);
|
||||
pt.lon = query.getDouble(3);
|
||||
pt.ele = query.getDouble(4);
|
||||
pt.speed = query.getDouble(5);
|
||||
pt.hdop = query.getDouble(6);
|
||||
pt.time = time;
|
||||
long currentInterval = Math.abs(time - previousTime);
|
||||
if (track != null) {
|
||||
if (currentInterval < 30 * 60 * 1000) {
|
||||
// 30 minute - same segment
|
||||
segment.points.add(pt);
|
||||
} else {
|
||||
segment = new TrkSegment();
|
||||
segment.points.add(pt);
|
||||
track.segments.add(segment);
|
||||
}
|
||||
} else {
|
||||
track = new Track();
|
||||
segment = new TrkSegment();
|
||||
track.segments.add(segment);
|
||||
segment.points.add(pt);
|
||||
|
||||
gpx.tracks.add(track);
|
||||
}
|
||||
previousTime = time;
|
||||
previousUserId = userId;
|
||||
previousChatId = chatId;
|
||||
} while (query.moveToNext());
|
||||
}
|
||||
query.close();
|
||||
}
|
||||
|
||||
private static class SaveGPXTrackToFileTask extends AsyncTask<Void, Void, List<String>> {
|
||||
|
||||
private TelegramApplication app;
|
||||
private WeakReference<LiveNowTabFragment> fragmentRef;
|
||||
private SaveGpxListener listener;
|
||||
|
||||
private final GPXFile gpxFile;
|
||||
private File dir;
|
||||
private int userId;
|
||||
|
||||
SaveGPXTrackToFileTask(LiveNowTabFragment fragment, GPXFile gpxFile, File dir, int userId) {
|
||||
SaveGPXTrackToFileTask(TelegramApplication app, SaveGpxListener listener, GPXFile gpxFile, File dir, int userId) {
|
||||
this.gpxFile = gpxFile;
|
||||
this.fragmentRef = new WeakReference<>(fragment);
|
||||
this.app = (TelegramApplication) fragment.getActivity().getApplication();
|
||||
this.listener = listener;
|
||||
this.app = app;
|
||||
this.dir = dir;
|
||||
this.userId = userId;
|
||||
}
|
||||
|
@ -300,12 +454,21 @@ public class SavingTracksDbHelper extends SQLiteOpenHelper {
|
|||
|
||||
@Override
|
||||
protected void onPostExecute(List<String> warnings) {
|
||||
if (warnings != null && warnings.isEmpty()) {
|
||||
LiveNowTabFragment fragment = fragmentRef.get();
|
||||
if (fragment != null && fragment.isResumed()) {
|
||||
fragment.shareGpx(gpxFile.path);
|
||||
if (listener != null) {
|
||||
if (warnings != null && warnings.isEmpty()) {
|
||||
listener.onSavingGpxFinish(gpxFile.path);
|
||||
} else {
|
||||
listener.onSavingGpxError(warnings);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public interface SaveGpxListener {
|
||||
|
||||
void onSavingGpxFinish(String path);
|
||||
|
||||
void onSavingGpxError(List<String> warnings);
|
||||
}
|
||||
}
|
|
@ -391,6 +391,15 @@ class TelegramHelper private constructor() {
|
|||
|
||||
fun isBot(userId: Int) = users[userId]?.type is TdApi.UserTypeBot
|
||||
|
||||
fun getSenderMessageId(message: TdApi.Message): Int {
|
||||
val forwardInfo = message.forwardInfo
|
||||
return if (forwardInfo != null && forwardInfo is TdApi.MessageForwardedFromUser) {
|
||||
forwardInfo.senderUserId
|
||||
} else {
|
||||
message.senderUserId
|
||||
}
|
||||
}
|
||||
|
||||
fun startLiveMessagesUpdates(interval: Long) {
|
||||
stopLiveMessagesUpdates()
|
||||
|
||||
|
@ -738,10 +747,13 @@ class TelegramHelper private constructor() {
|
|||
}
|
||||
} else {
|
||||
removeOldMessages(message, fromBot, viaBot)
|
||||
val oldMessage = usersLocationMessages.values.firstOrNull { it.senderUserId == message.senderUserId && !fromBot && !viaBot }
|
||||
if (oldMessage == null || (Math.max(message.editDate, message.date) > Math.max(oldMessage.editDate, oldMessage.date))) {
|
||||
val oldMessage = usersLocationMessages.values.firstOrNull { getSenderMessageId(it) == getSenderMessageId(message) && !fromBot && !viaBot }
|
||||
val hasNewerMessage = oldMessage != null && (Math.max(message.editDate, message.date) < Math.max(oldMessage.editDate, oldMessage.date))
|
||||
if (!hasNewerMessage) {
|
||||
usersLocationMessages[message.id] = message
|
||||
incomingMessagesListeners.forEach {
|
||||
}
|
||||
incomingMessagesListeners.forEach {
|
||||
if (!hasNewerMessage || it is SavingTracksDbHelper) {
|
||||
it.onReceiveChatLocationMessages(message.chatId, message)
|
||||
}
|
||||
}
|
||||
|
@ -754,7 +766,7 @@ class TelegramHelper private constructor() {
|
|||
while (iterator.hasNext()) {
|
||||
val message = iterator.next().value
|
||||
if (newMessage.chatId == message.chatId) {
|
||||
val sameSender = newMessage.senderUserId == message.senderUserId
|
||||
val sameSender = getSenderMessageId(newMessage) == getSenderMessageId(message)
|
||||
val viaSameBot = newMessage.viaBotUserId == message.viaBotUserId
|
||||
if (fromBot || viaBot) {
|
||||
if ((fromBot && sameSender) || (viaBot && viaSameBot)) {
|
||||
|
@ -1075,23 +1087,6 @@ class TelegramHelper private constructor() {
|
|||
return TdApi.InputMessageText(TdApi.FormattedText(textMessage, entities.toTypedArray()), true, true)
|
||||
}
|
||||
|
||||
/**
|
||||
* @chatId Id of the chat
|
||||
* @message Text of the message
|
||||
*/
|
||||
fun sendTextMessage(chatId: Long, message: String): Boolean {
|
||||
// initialize reply markup just for testing
|
||||
//val row = arrayOf(TdApi.InlineKeyboardButton("https://telegram.org?1", TdApi.InlineKeyboardButtonTypeUrl()), TdApi.InlineKeyboardButton("https://telegram.org?2", TdApi.InlineKeyboardButtonTypeUrl()), TdApi.InlineKeyboardButton("https://telegram.org?3", TdApi.InlineKeyboardButtonTypeUrl()))
|
||||
//val replyMarkup = TdApi.ReplyMarkupInlineKeyboard(arrayOf(row, row, row))
|
||||
|
||||
if (haveAuthorization) {
|
||||
val content = TdApi.InputMessageText(TdApi.FormattedText(message, null), false, true)
|
||||
client?.send(TdApi.SendMessage(chatId, 0, false, true, null, content), defaultHandler)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
fun logout(): Boolean {
|
||||
return if (libraryLoaded) {
|
||||
haveAuthorization = false
|
||||
|
|
|
@ -8,6 +8,7 @@ import net.osmand.telegram.R
|
|||
import net.osmand.telegram.TelegramApplication
|
||||
import net.osmand.telegram.helpers.TelegramHelper.MessageOsmAndBotLocation
|
||||
import net.osmand.telegram.helpers.TelegramHelper.MessageUserTextLocation
|
||||
import net.osmand.telegram.utils.GPXUtilities
|
||||
import org.drinkless.td.libcore.telegram.TdApi
|
||||
|
||||
object TelegramUiHelper {
|
||||
|
@ -129,6 +130,10 @@ object TelegramUiHelper {
|
|||
}
|
||||
}
|
||||
|
||||
fun gpxToChatItem(helper: TelegramHelper, gpx: GPXUtilities.GPXFile, simpleUserItem: Boolean): GpxChatItem? {
|
||||
return if (simpleUserItem) gpxToUserGpxChatItem(helper, gpx) else gpxToGpxChatItem(helper, gpx)
|
||||
}
|
||||
|
||||
private fun botMessageToLocationItem(
|
||||
chat: TdApi.Chat,
|
||||
content: MessageOsmAndBotLocation
|
||||
|
@ -224,6 +229,49 @@ object TelegramUiHelper {
|
|||
}
|
||||
}
|
||||
|
||||
private fun gpxToGpxChatItem(
|
||||
helper: TelegramHelper,
|
||||
gpx: GPXUtilities.GPXFile
|
||||
): GpxChatItem? {
|
||||
val user = helper.getUser(gpx.userId) ?: return null
|
||||
val chat = helper.getChat(gpx.chatId) ?: return null
|
||||
return GpxChatItem().apply {
|
||||
chatId = chat.id
|
||||
chatTitle = chat.title
|
||||
gpxFile = gpx
|
||||
name = TelegramUiHelper.getUserName(user)
|
||||
if (helper.isGroup(chat)) {
|
||||
photoPath = helper.getUserPhotoPath(user)
|
||||
groupPhotoPath = chat.photo?.small?.local?.path
|
||||
} else {
|
||||
photoPath = user.profilePhoto?.small?.local?.path
|
||||
}
|
||||
grayscalePhotoPath = helper.getUserGreyPhotoPath(user)
|
||||
placeholderId = R.drawable.img_user_picture
|
||||
userId = user.id
|
||||
privateChat = helper.isPrivateChat(chat) || helper.isSecretChat(chat)
|
||||
chatWithBot = helper.isBot(userId)
|
||||
lastUpdated = (gpx.modifiedTime / 1000).toInt()
|
||||
}
|
||||
}
|
||||
|
||||
private fun gpxToUserGpxChatItem(
|
||||
helper: TelegramHelper,
|
||||
gpx: GPXUtilities.GPXFile
|
||||
): GpxChatItem? {
|
||||
val user = helper.getUser(gpx.userId) ?: return null
|
||||
return GpxChatItem().apply {
|
||||
gpxFile = gpx
|
||||
name = TelegramUiHelper.getUserName(user)
|
||||
photoPath = user.profilePhoto?.small?.local?.path
|
||||
grayscalePhotoPath = helper.getUserGreyPhotoPath(user)
|
||||
placeholderId = R.drawable.img_user_picture
|
||||
userId = user.id
|
||||
chatWithBot = helper.isBot(userId)
|
||||
lastUpdated = (gpx.modifiedTime / 1000).toInt()
|
||||
}
|
||||
}
|
||||
|
||||
abstract class ListItem {
|
||||
|
||||
var chatId: Long = 0
|
||||
|
@ -272,6 +320,24 @@ object TelegramUiHelper {
|
|||
override fun getVisibleName() = chatTitle
|
||||
}
|
||||
|
||||
class GpxChatItem : ListItem() {
|
||||
|
||||
var gpxFile: GPXUtilities.GPXFile? = null
|
||||
internal set
|
||||
var groupPhotoPath: String? = null
|
||||
internal set
|
||||
var privateChat: Boolean = false
|
||||
internal set
|
||||
var chatWithBot: Boolean = false
|
||||
internal set
|
||||
|
||||
override fun canBeOpenedOnMap() = latLon != null
|
||||
|
||||
override fun getMapPointId() = "${chatId}_$userId"
|
||||
|
||||
override fun getVisibleName() = chatTitle
|
||||
}
|
||||
|
||||
class LocationItem : ListItem() {
|
||||
|
||||
override fun canBeOpenedOnMap() = latLon != null
|
||||
|
|
|
@ -11,10 +11,7 @@ import android.view.LayoutInflater
|
|||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.animation.LinearInterpolator
|
||||
import android.widget.ArrayAdapter
|
||||
import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import android.widget.*
|
||||
import net.osmand.Location
|
||||
import net.osmand.data.LatLon
|
||||
import net.osmand.telegram.R
|
||||
|
@ -22,6 +19,7 @@ import net.osmand.telegram.TelegramApplication
|
|||
import net.osmand.telegram.TelegramLocationProvider.TelegramCompassListener
|
||||
import net.osmand.telegram.TelegramLocationProvider.TelegramLocationListener
|
||||
import net.osmand.telegram.TelegramSettings
|
||||
import net.osmand.telegram.helpers.SavingTracksDbHelper
|
||||
import net.osmand.telegram.helpers.TelegramHelper.*
|
||||
import net.osmand.telegram.helpers.TelegramUiHelper
|
||||
import net.osmand.telegram.helpers.TelegramUiHelper.ChatItem
|
||||
|
@ -33,7 +31,7 @@ import net.osmand.telegram.utils.OsmandFormatter
|
|||
import net.osmand.telegram.utils.UiUtils.UpdateLocationViewCache
|
||||
import net.osmand.util.MapUtils
|
||||
import org.drinkless.td.libcore.telegram.TdApi
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
|
||||
private const val CHAT_VIEW_TYPE = 0
|
||||
private const val LOCATION_ITEM_VIEW_TYPE = 1
|
||||
|
@ -233,15 +231,6 @@ class LiveNowTabFragment : Fragment(), TelegramListener, TelegramIncomingMessage
|
|||
stopLocationUpdate()
|
||||
}
|
||||
|
||||
fun shareGpx(path: String) {
|
||||
val fileUri = AndroidUtils.getUriForFile(app, File(path))
|
||||
val sendIntent = Intent(Intent.ACTION_SEND)
|
||||
sendIntent.putExtra(Intent.EXTRA_STREAM, fileUri)
|
||||
sendIntent.type = "application/gpx+xml"
|
||||
sendIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||
startActivity(sendIntent)
|
||||
}
|
||||
|
||||
private fun chooseOsmAnd() {
|
||||
val ctx = context ?: return
|
||||
val installedApps = TelegramSettings.AppConnect.getInstalledApps(ctx)
|
||||
|
@ -456,15 +445,6 @@ class LiveNowTabFragment : Fragment(), TelegramListener, TelegramIncomingMessage
|
|||
app.showLocationHelper.showLocationOnMap(item, staleLocation)
|
||||
}
|
||||
}
|
||||
openOnMapView?.setOnLongClickListener {
|
||||
app.savingTracksDbHelper.saveAsyncUserDataToGpx(
|
||||
this@LiveNowTabFragment,
|
||||
app.getExternalFilesDir(null),
|
||||
item.userId,
|
||||
60 * 60 * 24 * 1000
|
||||
)
|
||||
true
|
||||
}
|
||||
} else {
|
||||
openOnMapView?.setOnClickListener(null)
|
||||
}
|
||||
|
@ -485,17 +465,6 @@ class LiveNowTabFragment : Fragment(), TelegramListener, TelegramIncomingMessage
|
|||
if (lastItem) {
|
||||
holder.lastTelegramUpdateTime?.visibility = View.VISIBLE
|
||||
holder.lastTelegramUpdateTime?.text = OsmandFormatter.getListItemLiveTimeDescr(app, telegramHelper.lastTelegramUpdateTime, lastTelegramUpdateStr)
|
||||
holder.lastTelegramUpdateTime?.setOnClickListener {
|
||||
val currentUserId = telegramHelper.getCurrentUser()?.id
|
||||
if (currentUserId != null) {
|
||||
app.savingTracksDbHelper.saveAsyncUserDataToGpx(
|
||||
this@LiveNowTabFragment,
|
||||
app.getExternalFilesDir(null),
|
||||
currentUserId,
|
||||
60 * 60 * 24 * 1000
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
holder.lastTelegramUpdateTime?.visibility = View.GONE
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ import net.osmand.telegram.ui.MyLocationTabFragment.ActionButtonsListener
|
|||
import net.osmand.telegram.ui.views.LockableViewPager
|
||||
import net.osmand.telegram.utils.*
|
||||
import org.drinkless.td.libcore.telegram.TdApi
|
||||
import java.io.File
|
||||
import java.lang.ref.WeakReference
|
||||
|
||||
const val OPEN_MY_LOCATION_TAB_KEY = "open_my_location_tab"
|
||||
|
@ -35,6 +36,7 @@ private const val PERMISSION_REQUEST_LOCATION = 1
|
|||
|
||||
private const val MY_LOCATION_TAB_POS = 0
|
||||
private const val LIVE_NOW_TAB_POS = 1
|
||||
private const val TIMELINE_TAB_POS = 2
|
||||
|
||||
class MainActivity : AppCompatActivity(), TelegramListener, ActionButtonsListener, TelegramIncomingMessagesListener {
|
||||
|
||||
|
@ -54,6 +56,7 @@ class MainActivity : AppCompatActivity(), TelegramListener, ActionButtonsListene
|
|||
|
||||
private var myLocationTabFragment: MyLocationTabFragment? = null
|
||||
private var liveNowTabFragment: LiveNowTabFragment? = null
|
||||
private var timelineTabFragment: TimelineTabFragment? = null
|
||||
|
||||
private lateinit var buttonsBar: LinearLayout
|
||||
private lateinit var bottomNav: BottomNavigationView
|
||||
|
@ -72,7 +75,7 @@ class MainActivity : AppCompatActivity(), TelegramListener, ActionButtonsListene
|
|||
|
||||
val viewPager = findViewById<LockableViewPager>(R.id.view_pager).apply {
|
||||
swipeLocked = true
|
||||
offscreenPageLimit = 2
|
||||
offscreenPageLimit = 3
|
||||
adapter = ViewPagerAdapter(supportFragmentManager)
|
||||
}
|
||||
|
||||
|
@ -82,11 +85,13 @@ class MainActivity : AppCompatActivity(), TelegramListener, ActionButtonsListene
|
|||
when (it.itemId) {
|
||||
R.id.action_my_location -> pos = MY_LOCATION_TAB_POS
|
||||
R.id.action_live_now -> pos = LIVE_NOW_TAB_POS
|
||||
R.id.action_timeline -> pos = TIMELINE_TAB_POS
|
||||
}
|
||||
if (pos != -1 && pos != viewPager.currentItem) {
|
||||
when (pos) {
|
||||
MY_LOCATION_TAB_POS -> liveNowTabFragment?.tabClosed()
|
||||
LIVE_NOW_TAB_POS -> liveNowTabFragment?.tabOpened()
|
||||
TIMELINE_TAB_POS -> liveNowTabFragment?.tabClosed()
|
||||
}
|
||||
viewPager.currentItem = pos
|
||||
return@setOnNavigationItemSelectedListener true
|
||||
|
@ -139,10 +144,10 @@ class MainActivity : AppCompatActivity(), TelegramListener, ActionButtonsListene
|
|||
if (fragment is TelegramListener) {
|
||||
listeners.add(WeakReference(fragment))
|
||||
}
|
||||
if (fragment is MyLocationTabFragment) {
|
||||
myLocationTabFragment = fragment
|
||||
} else if (fragment is LiveNowTabFragment) {
|
||||
liveNowTabFragment = fragment
|
||||
when (fragment) {
|
||||
is MyLocationTabFragment -> myLocationTabFragment = fragment
|
||||
is LiveNowTabFragment -> liveNowTabFragment = fragment
|
||||
is TimelineTabFragment -> timelineTabFragment = fragment
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -317,6 +322,15 @@ class MainActivity : AppCompatActivity(), TelegramListener, ActionButtonsListene
|
|||
android.os.Process.killProcess(android.os.Process.myPid())
|
||||
}
|
||||
|
||||
fun shareGpx(path: String) {
|
||||
val fileUri = AndroidUtils.getUriForFile(app, File(path))
|
||||
val sendIntent = Intent(Intent.ACTION_SEND)
|
||||
sendIntent.putExtra(Intent.EXTRA_STREAM, fileUri)
|
||||
sendIntent.type = "application/gpx+xml"
|
||||
sendIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||
startActivity(sendIntent)
|
||||
}
|
||||
|
||||
fun loginTelegram() {
|
||||
if (telegramHelper.getTelegramAuthorizationState() != TelegramAuthorizationState.CLOSED) {
|
||||
telegramHelper.logout()
|
||||
|
@ -463,7 +477,7 @@ class MainActivity : AppCompatActivity(), TelegramListener, ActionButtonsListene
|
|||
|
||||
class ViewPagerAdapter(fm: FragmentManager) : FragmentPagerAdapter(fm) {
|
||||
|
||||
private val fragments = listOf<Fragment>(MyLocationTabFragment(), LiveNowTabFragment())
|
||||
private val fragments = listOf<Fragment>(MyLocationTabFragment(), LiveNowTabFragment(), TimelineTabFragment())
|
||||
|
||||
override fun getItem(position: Int) = fragments[position]
|
||||
|
||||
|
|
|
@ -599,12 +599,6 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
|
|||
}
|
||||
|
||||
holder.title?.text = title
|
||||
holder.icon?.setOnClickListener {
|
||||
app.forceUpdateMyLocation()
|
||||
val curUser = telegramHelper.getCurrentUser()
|
||||
val text = "${curUser?.id} ${curUser?.firstName} ${curUser?.lastName}"
|
||||
Toast.makeText(app, text, Toast.LENGTH_LONG).show()
|
||||
}
|
||||
if (holder is ChatViewHolder) {
|
||||
holder.description?.visibility = View.GONE
|
||||
if (live) {
|
||||
|
|
|
@ -0,0 +1,261 @@
|
|||
package net.osmand.telegram.ui
|
||||
|
||||
import android.app.DatePickerDialog
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.support.annotation.DrawableRes
|
||||
import android.support.v4.app.Fragment
|
||||
import android.support.v7.widget.LinearLayoutManager
|
||||
import android.support.v7.widget.RecyclerView
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import android.widget.Switch
|
||||
import android.widget.TextView
|
||||
import net.osmand.PlatformUtil
|
||||
import net.osmand.telegram.R
|
||||
import net.osmand.telegram.TelegramApplication
|
||||
import net.osmand.telegram.helpers.TelegramUiHelper
|
||||
import net.osmand.telegram.helpers.TelegramUiHelper.ListItem
|
||||
import net.osmand.telegram.ui.TimelineTabFragment.LiveNowListAdapter.BaseViewHolder
|
||||
import net.osmand.telegram.utils.AndroidUtils
|
||||
import net.osmand.telegram.utils.OsmandFormatter
|
||||
import java.util.*
|
||||
|
||||
|
||||
class TimelineTabFragment : Fragment() {
|
||||
|
||||
private val log = PlatformUtil.getLog(TimelineTabFragment::class.java)
|
||||
|
||||
private val app: TelegramApplication
|
||||
get() = activity?.application as TelegramApplication
|
||||
|
||||
private val telegramHelper get() = app.telegramHelper
|
||||
private val settings get() = app.settings
|
||||
|
||||
private lateinit var adapter: LiveNowListAdapter
|
||||
|
||||
private lateinit var dateStartBtn: TextView
|
||||
private lateinit var dateEndBtn: TextView
|
||||
private lateinit var mainView: View
|
||||
|
||||
private var start = 0L
|
||||
private var end = 0L
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
mainView = inflater.inflate(R.layout.fragment_timeline_tab, container, false)
|
||||
val appBarLayout = mainView.findViewById<View>(R.id.app_bar_layout)
|
||||
|
||||
start = System.currentTimeMillis()
|
||||
end = System.currentTimeMillis()
|
||||
|
||||
AndroidUtils.addStatusBarPadding19v(context!!, appBarLayout)
|
||||
adapter = LiveNowListAdapter()
|
||||
mainView.findViewById<RecyclerView>(R.id.recycler_view).apply {
|
||||
layoutManager = LinearLayoutManager(context)
|
||||
adapter = this@TimelineTabFragment.adapter
|
||||
}
|
||||
|
||||
val switcher = mainView.findViewById<Switch>(R.id.monitoring_switcher)
|
||||
val monitoringTv = mainView.findViewById<TextView>(R.id.monitoring_title)
|
||||
monitoringTv.setText(if (settings.monitoringEnabled) R.string.monitoring_is_enabled else R.string.monitoring_is_disabled)
|
||||
|
||||
mainView.findViewById<View>(R.id.monitoring_container).setOnClickListener {
|
||||
val monitoringEnabled = !settings.monitoringEnabled
|
||||
settings.monitoringEnabled = monitoringEnabled
|
||||
switcher.isChecked = monitoringEnabled
|
||||
monitoringTv.setText(if (monitoringEnabled) R.string.monitoring_is_enabled else R.string.monitoring_is_disabled)
|
||||
}
|
||||
|
||||
dateStartBtn = mainView.findViewById<TextView>(R.id.date_start_btn).apply {
|
||||
setOnClickListener {
|
||||
selectStartDate()
|
||||
}
|
||||
setCompoundDrawablesWithIntrinsicBounds(getPressedStateIcon(R.drawable.ic_action_date_start), null, null, null)
|
||||
}
|
||||
dateEndBtn = mainView.findViewById<TextView>(R.id.date_end_btn).apply {
|
||||
setOnClickListener {
|
||||
selectEndDate()
|
||||
}
|
||||
setCompoundDrawablesWithIntrinsicBounds(getPressedStateIcon(R.drawable.ic_action_date_add), null, null, null)
|
||||
}
|
||||
|
||||
setupBtnTextColor(dateStartBtn)
|
||||
setupBtnTextColor(dateEndBtn)
|
||||
|
||||
return mainView
|
||||
}
|
||||
|
||||
private fun setupBtnTextColor(textView: TextView) {
|
||||
textView.setTextColor(AndroidUtils.createPressedColorStateList(app, true, R.color.ctrl_active_light, R.color.ctrl_light))
|
||||
}
|
||||
|
||||
private fun selectStartDate() {
|
||||
val dateFromDialog =
|
||||
DatePickerDialog.OnDateSetListener { _, year, monthOfYear, dayOfMonth ->
|
||||
val from = Calendar.getInstance()
|
||||
from.set(Calendar.YEAR, year)
|
||||
from.set(Calendar.MONTH, monthOfYear)
|
||||
from.set(Calendar.DAY_OF_MONTH, dayOfMonth)
|
||||
start = from.timeInMillis
|
||||
updateList()
|
||||
updateDateButtons()
|
||||
}
|
||||
val startCalendar = Calendar.getInstance()
|
||||
startCalendar.timeInMillis = start
|
||||
DatePickerDialog(context, dateFromDialog,
|
||||
startCalendar.get(Calendar.YEAR),
|
||||
startCalendar.get(Calendar.MONTH),
|
||||
startCalendar.get(Calendar.DAY_OF_MONTH)
|
||||
).show()
|
||||
}
|
||||
|
||||
private fun selectEndDate() {
|
||||
val dateFromDialog =
|
||||
DatePickerDialog.OnDateSetListener { _, year, monthOfYear, dayOfMonth ->
|
||||
val from = Calendar.getInstance()
|
||||
from.set(Calendar.YEAR, year)
|
||||
from.set(Calendar.MONTH, monthOfYear)
|
||||
from.set(Calendar.DAY_OF_MONTH, dayOfMonth)
|
||||
end = from.timeInMillis
|
||||
updateList()
|
||||
updateDateButtons()
|
||||
}
|
||||
val endCalendar = Calendar.getInstance()
|
||||
endCalendar.timeInMillis = end
|
||||
DatePickerDialog(context, dateFromDialog,
|
||||
endCalendar.get(Calendar.YEAR),
|
||||
endCalendar.get(Calendar.MONTH),
|
||||
endCalendar.get(Calendar.DAY_OF_MONTH)
|
||||
).show()
|
||||
}
|
||||
|
||||
private fun updateDateButtons() {
|
||||
dateStartBtn.text = OsmandFormatter.getFormattedDate(start / 1000)
|
||||
dateEndBtn.text = OsmandFormatter.getFormattedDate(end / 1000)
|
||||
dateEndBtn.setCompoundDrawablesWithIntrinsicBounds(getPressedStateIcon(R.drawable.ic_action_date_end), null, null, null)
|
||||
}
|
||||
|
||||
private fun getPressedStateIcon(@DrawableRes iconId: Int): Drawable? {
|
||||
val normal = app.uiUtils.getActiveIcon(iconId)
|
||||
if (Build.VERSION.SDK_INT >= 21) {
|
||||
val active = app.uiUtils.getIcon(iconId, R.color.ctrl_light)
|
||||
if (normal != null && active != null) {
|
||||
return AndroidUtils.createPressedStateListDrawable(normal, active)
|
||||
}
|
||||
}
|
||||
return normal
|
||||
}
|
||||
|
||||
private fun updateList() {
|
||||
val res = mutableListOf<ListItem>()
|
||||
val s = System.currentTimeMillis()
|
||||
log.debug("updateList $start")
|
||||
val ignoredUsersIds = ArrayList<Int>()
|
||||
val currentUserId = telegramHelper.getCurrentUser()?.id
|
||||
if (currentUserId != null) {
|
||||
val currentUserGpx = app.savingTracksDbHelper.collectRecordedDataForUser(currentUserId, 0, start, end)
|
||||
TelegramUiHelper.gpxToChatItem(telegramHelper, currentUserGpx, true)?.also {
|
||||
res.add(it)
|
||||
}
|
||||
ignoredUsersIds.add(currentUserId)
|
||||
}
|
||||
val gpxFiles = app.savingTracksDbHelper.collectRecordedDataForUsers(start, end, ignoredUsersIds)
|
||||
val e = System.currentTimeMillis()
|
||||
|
||||
gpxFiles.forEach {
|
||||
TelegramUiHelper.gpxToChatItem(telegramHelper, it,false)?.also { chatItem ->
|
||||
res.add(chatItem)
|
||||
}
|
||||
}
|
||||
|
||||
adapter.items = sortAdapterItems(res)
|
||||
log.debug("updateList $s dif: ${e - s}")
|
||||
}
|
||||
|
||||
private fun sortAdapterItems(list: MutableList<ListItem>): MutableList<ListItem> {
|
||||
val currentUserId = telegramHelper.getCurrentUser()?.id ?: 0
|
||||
list.sortWith(java.util.Comparator { lhs, rhs ->
|
||||
when (currentUserId) {
|
||||
lhs.userId -> return@Comparator 1
|
||||
rhs.userId -> return@Comparator 1
|
||||
else -> return@Comparator lhs.name.compareTo(rhs.name)
|
||||
}
|
||||
})
|
||||
return list
|
||||
}
|
||||
|
||||
inner class LiveNowListAdapter : RecyclerView.Adapter<BaseViewHolder>() {
|
||||
|
||||
var items: List<ListItem> = emptyList()
|
||||
set(value) {
|
||||
field = value
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseViewHolder {
|
||||
val inflater = LayoutInflater.from(parent.context)
|
||||
return BaseViewHolder(inflater.inflate(R.layout.live_now_chat_card, parent, false))
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: BaseViewHolder, position: Int) {
|
||||
val lastItem = position == itemCount - 1
|
||||
val item = items[position]
|
||||
val currentUserId = telegramHelper.getCurrentUser()?.id ?: 0
|
||||
|
||||
TelegramUiHelper.setupPhoto(app, holder.icon, item.photoPath, R.drawable.img_user_picture_active, false)
|
||||
holder.title?.text = item.name
|
||||
holder.bottomShadow?.visibility = if (lastItem) View.VISIBLE else View.GONE
|
||||
holder.lastTelegramUpdateTime?.visibility = View.GONE
|
||||
|
||||
if (item is TelegramUiHelper.GpxChatItem) {
|
||||
val gpx = item.gpxFile
|
||||
val groupDescrRowVisible = (!item.privateChat || item.chatWithBot) && item.userId != currentUserId
|
||||
if (groupDescrRowVisible) {
|
||||
holder.groupDescrContainer?.visibility = View.VISIBLE
|
||||
holder.groupTitle?.text = item.getVisibleName()
|
||||
TelegramUiHelper.setupPhoto(app, holder.groupImage, item.groupPhotoPath, item.placeholderId, false)
|
||||
} else {
|
||||
holder.groupDescrContainer?.visibility = View.GONE
|
||||
}
|
||||
holder.userRow?.setOnClickListener {
|
||||
if (gpx != null) {
|
||||
childFragmentManager.also {
|
||||
UserGpxInfoFragment.showInstance(it, gpx, start, end)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
holder.imageButton?.visibility = View.GONE
|
||||
holder.showOnMapRow?.visibility = View.GONE
|
||||
holder.bottomDivider?.visibility = if (lastItem) View.GONE else View.VISIBLE
|
||||
holder.topDivider?.visibility = if (position != 0) View.GONE else View.VISIBLE
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemCount() = items.size
|
||||
|
||||
inner class BaseViewHolder(view: View) : RecyclerView.ViewHolder(view) {
|
||||
val icon: ImageView? = view.findViewById(R.id.icon)
|
||||
val title: TextView? = view.findViewById(R.id.title)
|
||||
val description: TextView? = view.findViewById(R.id.description)
|
||||
val bottomShadow: View? = view.findViewById(R.id.bottom_shadow)
|
||||
val lastTelegramUpdateTime: TextView? = view.findViewById(R.id.last_telegram_update_time)
|
||||
|
||||
val userRow: View? = view.findViewById(R.id.user_row)
|
||||
val groupDescrContainer: View? = view.findViewById(R.id.group_container)
|
||||
val groupImage: ImageView? = view.findViewById(R.id.group_icon)
|
||||
val groupTitle: TextView? = view.findViewById(R.id.group_title)
|
||||
val imageButton: ImageView? = view.findViewById(R.id.image_button)
|
||||
val showOnMapRow: View? = view.findViewById(R.id.show_on_map_row)
|
||||
val topDivider: View? = view.findViewById(R.id.top_divider)
|
||||
val bottomDivider: View? = view.findViewById(R.id.bottom_divider)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,322 @@
|
|||
package net.osmand.telegram.ui
|
||||
|
||||
import android.app.DatePickerDialog
|
||||
import android.app.TimePickerDialog
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.graphics.drawable.BitmapDrawable
|
||||
import android.os.Bundle
|
||||
import android.support.v4.app.FragmentManager
|
||||
import android.util.DisplayMetrics
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.WindowManager
|
||||
import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import net.osmand.PlatformUtil
|
||||
import net.osmand.aidl.gpx.AGpxBitmap
|
||||
import net.osmand.telegram.R
|
||||
import net.osmand.telegram.helpers.OsmandAidlHelper
|
||||
import net.osmand.telegram.helpers.SavingTracksDbHelper
|
||||
import net.osmand.telegram.helpers.TelegramUiHelper
|
||||
import net.osmand.telegram.utils.AndroidUtils
|
||||
import net.osmand.telegram.utils.GPXUtilities
|
||||
import net.osmand.telegram.utils.OsmandFormatter
|
||||
import net.osmand.util.Algorithms
|
||||
import java.io.File
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
class UserGpxInfoFragment : BaseDialogFragment() {
|
||||
|
||||
private val log = PlatformUtil.getLog(UserGpxInfoFragment::class.java)
|
||||
|
||||
private val uiUtils get() = app.uiUtils
|
||||
|
||||
private lateinit var gpxFile: GPXUtilities.GPXFile
|
||||
|
||||
private lateinit var dateStartBtn: TextView
|
||||
private lateinit var timeStartBtn: TextView
|
||||
private lateinit var dateEndBtn: TextView
|
||||
private lateinit var timeEndBtn: TextView
|
||||
|
||||
private lateinit var avgElevationTv: TextView
|
||||
private lateinit var avgSpeedTv: TextView
|
||||
private lateinit var totalDistanceTv: TextView
|
||||
private lateinit var timeSpanTv: TextView
|
||||
|
||||
private var startCalendar = Calendar.getInstance()
|
||||
private var endCalendar = Calendar.getInstance()
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
parent: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
val mainView = inflater.inflate(R.layout.fragment_user_gpx_info, parent)
|
||||
AndroidUtils.addStatusBarPadding19v(context!!, mainView)
|
||||
|
||||
readFromBundle(savedInstanceState ?: arguments)
|
||||
|
||||
val userId = gpxFile.userId
|
||||
val chatId = gpxFile.chatId
|
||||
|
||||
val user = app.telegramHelper.getUser(userId)
|
||||
if (user != null) {
|
||||
mainView.findViewById<TextView>(R.id.title).text = TelegramUiHelper.getUserName(user)
|
||||
TelegramUiHelper.setupPhoto(app, mainView.findViewById<ImageView>(R.id.user_icon),
|
||||
telegramHelper.getUserPhotoPath(user), R.drawable.img_user_placeholder, false)
|
||||
}
|
||||
app.osmandAidlHelper.setGpxBitmapCreatedListener(
|
||||
object : OsmandAidlHelper.GpxBitmapCreatedListener {
|
||||
override fun onGpxBitmapCreated(bitmap: AGpxBitmap) {
|
||||
activity?.runOnUiThread {
|
||||
mainView.findViewById<ImageView>(R.id.gpx_map).setImageDrawable(BitmapDrawable(app.resources, bitmap.bitmap))
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
updateGPXMap()
|
||||
|
||||
val backBtn = mainView.findViewById<ImageView>(R.id.back_button)
|
||||
backBtn.setImageDrawable(uiUtils.getThemedIcon(R.drawable.ic_arrow_back))
|
||||
backBtn.setOnClickListener {
|
||||
dismiss()
|
||||
}
|
||||
|
||||
dateStartBtn = mainView.findViewById<TextView>(R.id.date_start_btn)
|
||||
timeStartBtn = mainView.findViewById<TextView>(R.id.time_start_btn)
|
||||
dateEndBtn = mainView.findViewById<TextView>(R.id.date_end_btn)
|
||||
timeEndBtn = mainView.findViewById<TextView>(R.id.time_end_btn)
|
||||
|
||||
dateStartBtn.setOnClickListener { selectStartDate() }
|
||||
timeStartBtn.setOnClickListener { selectStartTime() }
|
||||
dateEndBtn.setOnClickListener { selectEndDate() }
|
||||
timeEndBtn.setOnClickListener { selectEndTime() }
|
||||
|
||||
setupBtnTextColor(dateStartBtn)
|
||||
setupBtnTextColor(timeStartBtn)
|
||||
setupBtnTextColor(dateEndBtn)
|
||||
setupBtnTextColor(timeEndBtn)
|
||||
|
||||
updateDateAndTimeButtons()
|
||||
|
||||
avgElevationTv = mainView.findViewById<TextView>(R.id.average_altitude_text)
|
||||
avgSpeedTv = mainView.findViewById<TextView>(R.id.average_speed_text)
|
||||
totalDistanceTv = mainView.findViewById<TextView>(R.id.distance_text)
|
||||
timeSpanTv = mainView.findViewById<TextView>(R.id.duration_text)
|
||||
|
||||
mainView.findViewById<ImageView>(R.id.average_altitude_icon).apply {
|
||||
setImageDrawable(uiUtils.getThemedIcon(R.drawable.ic_action_altitude_range))
|
||||
}
|
||||
mainView.findViewById<ImageView>(R.id.average_speed_icon).apply {
|
||||
setImageDrawable(uiUtils.getThemedIcon(R.drawable.ic_action_speed_average))
|
||||
}
|
||||
mainView.findViewById<ImageView>(R.id.distance_icon).apply {
|
||||
setImageDrawable(uiUtils.getThemedIcon(R.drawable.ic_action_altitude_range))
|
||||
}
|
||||
mainView.findViewById<ImageView>(R.id.duration_icon).apply {
|
||||
setImageDrawable(uiUtils.getThemedIcon(R.drawable.ic_action_altitude_range))
|
||||
}
|
||||
|
||||
updateGPXStatisticRow()
|
||||
|
||||
mainView.findViewById<ImageView>(R.id.open_in_osmand_icon).setImageResource(R.drawable.ic_logo_osmand_free)
|
||||
|
||||
mainView.findViewById<LinearLayout>(R.id.open_in_osmand_btn).apply {
|
||||
setOnClickListener {
|
||||
val gpx = gpxFile
|
||||
if (gpx.path.isNotEmpty()) {
|
||||
openGpx(gpx.path)
|
||||
} else {
|
||||
saveCurrentGpxToFile(object :
|
||||
SavingTracksDbHelper.SaveGpxListener {
|
||||
override fun onSavingGpxFinish(path: String) {
|
||||
openGpx(path)
|
||||
}
|
||||
|
||||
override fun onSavingGpxError(warnings: MutableList<String>?) {
|
||||
Toast.makeText(app, warnings?.firstOrNull(), Toast.LENGTH_LONG).show()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mainView.findViewById<ImageView>(R.id.share_gpx_icon).setImageDrawable(uiUtils.getActiveIcon(R.drawable.ic_action_share))
|
||||
|
||||
mainView.findViewById<LinearLayout>(R.id.share_gpx_btn).apply {
|
||||
setOnClickListener {
|
||||
val gpx = gpxFile
|
||||
if (gpx.path.isNotEmpty()) {
|
||||
(activity as MainActivity).shareGpx(gpx.path)
|
||||
} else {
|
||||
saveCurrentGpxToFile(object :
|
||||
SavingTracksDbHelper.SaveGpxListener {
|
||||
override fun onSavingGpxFinish(path: String) {
|
||||
(activity as MainActivity).shareGpx(path)
|
||||
}
|
||||
|
||||
override fun onSavingGpxError(warnings: MutableList<String>?) {
|
||||
Toast.makeText(app, warnings?.firstOrNull(), Toast.LENGTH_LONG).show()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return mainView
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
super.onSaveInstanceState(outState)
|
||||
outState.putLong(START_KEY, startCalendar.timeInMillis)
|
||||
outState.putLong(END_KEY, endCalendar.timeInMillis)
|
||||
}
|
||||
|
||||
private fun openGpx(path: String) {
|
||||
val fileUri = AndroidUtils.getUriForFile(app, File(path))
|
||||
val openGpxIntent = Intent(Intent.ACTION_VIEW)
|
||||
openGpxIntent.setDataAndType(fileUri, "application/gpx+xml")
|
||||
// openGpxIntent.type = "application/gpx+xml"
|
||||
openGpxIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||
val resolved = activity?.packageManager?.resolveActivity(openGpxIntent, PackageManager.MATCH_DEFAULT_ONLY)
|
||||
if (resolved != null) {
|
||||
startActivity(openGpxIntent)
|
||||
}
|
||||
}
|
||||
|
||||
private fun saveCurrentGpxToFile(listener: SavingTracksDbHelper.SaveGpxListener) {
|
||||
app.savingTracksDbHelper.saveGpx(listener, app.getExternalFilesDir(null), gpxFile)
|
||||
}
|
||||
|
||||
private fun readFromBundle(bundle: Bundle?) {
|
||||
bundle?.also {
|
||||
startCalendar.timeInMillis = it.getLong(START_KEY)
|
||||
endCalendar.timeInMillis = it.getLong(END_KEY)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupBtnTextColor(textView: TextView) {
|
||||
textView.setTextColor(AndroidUtils.createPressedColorStateList(app, true, R.color.ctrl_active_light, R.color.ctrl_light))
|
||||
}
|
||||
|
||||
private fun updateGpxInfo() {
|
||||
gpxFile = app.savingTracksDbHelper.collectRecordedDataForUser(gpxFile.userId, gpxFile.chatId, startCalendar.timeInMillis, endCalendar.timeInMillis)
|
||||
updateGPXStatisticRow()
|
||||
updateDateAndTimeButtons()
|
||||
updateGPXMap()
|
||||
}
|
||||
|
||||
private fun updateDateAndTimeButtons() {
|
||||
dateStartBtn.text = SimpleDateFormat("dd MMM", Locale.getDefault()).format(startCalendar.timeInMillis)
|
||||
dateEndBtn.text = SimpleDateFormat("dd MMM", Locale.getDefault()).format(endCalendar.timeInMillis)
|
||||
|
||||
timeStartBtn.text = SimpleDateFormat("HH:mm", Locale.getDefault()).format(startCalendar.timeInMillis)
|
||||
timeEndBtn.text = SimpleDateFormat("HH:mm", Locale.getDefault()).format(endCalendar.timeInMillis)
|
||||
}
|
||||
|
||||
private fun updateGPXStatisticRow() {
|
||||
val analysis: GPXUtilities.GPXTrackAnalysis = gpxFile.getAnalysis(0)
|
||||
avgElevationTv.text = OsmandFormatter.getFormattedAlt(analysis.avgElevation, app)
|
||||
avgSpeedTv.text = if (analysis.isSpeedSpecified) OsmandFormatter.getFormattedSpeed(analysis.avgSpeed, app) else ""
|
||||
totalDistanceTv.text = OsmandFormatter.getFormattedDistance(analysis.totalDistance, app)
|
||||
timeSpanTv.text = Algorithms.formatDuration((analysis.timeSpan / 1000).toInt(), true)
|
||||
}
|
||||
|
||||
private fun updateGPXMap() {
|
||||
saveCurrentGpxToFile(object :
|
||||
SavingTracksDbHelper.SaveGpxListener {
|
||||
override fun onSavingGpxFinish(path: String) {
|
||||
val mgr = activity?.getSystemService(Context.WINDOW_SERVICE)
|
||||
if (mgr != null) {
|
||||
val dm = DisplayMetrics()
|
||||
(mgr as WindowManager).defaultDisplay.getMetrics(dm)
|
||||
val widthPixels = dm.widthPixels - (2 * app.resources.getDimensionPixelSize(R.dimen.content_padding_standard))
|
||||
val heightPixels = AndroidUtils.dpToPx(app, 152f)
|
||||
val gpxUri = AndroidUtils.getUriForFile(app, File(path))
|
||||
app.osmandAidlHelper.getBitmapForGpx(gpxUri, dm.density , widthPixels, heightPixels, GPX_TRACK_COLOR)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onSavingGpxError(warnings: MutableList<String>?) {
|
||||
log.debug("onSavingGpxError ${warnings?.firstOrNull()}")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun selectStartDate() {
|
||||
val dateFromDialog =
|
||||
DatePickerDialog.OnDateSetListener { _, year, monthOfYear, dayOfMonth ->
|
||||
startCalendar.set(Calendar.YEAR, year)
|
||||
startCalendar.set(Calendar.MONTH, monthOfYear)
|
||||
startCalendar.set(Calendar.DAY_OF_MONTH, dayOfMonth)
|
||||
updateGpxInfo()
|
||||
}
|
||||
DatePickerDialog(context, dateFromDialog,
|
||||
startCalendar.get(Calendar.YEAR),
|
||||
startCalendar.get(Calendar.MONTH),
|
||||
startCalendar.get(Calendar.DAY_OF_MONTH)).show()
|
||||
}
|
||||
|
||||
private fun selectStartTime() {
|
||||
TimePickerDialog(context,
|
||||
TimePickerDialog.OnTimeSetListener { _, hours, minutes ->
|
||||
startCalendar.set(Calendar.HOUR_OF_DAY, hours)
|
||||
startCalendar.set(Calendar.MINUTE, minutes)
|
||||
updateGpxInfo()
|
||||
}, 0, 0, true).show()
|
||||
}
|
||||
|
||||
private fun selectEndDate() {
|
||||
val dateFromDialog =
|
||||
DatePickerDialog.OnDateSetListener { _, year, monthOfYear, dayOfMonth ->
|
||||
endCalendar.set(Calendar.YEAR, year)
|
||||
endCalendar.set(Calendar.MONTH, monthOfYear)
|
||||
endCalendar.set(Calendar.DAY_OF_MONTH, dayOfMonth)
|
||||
updateGpxInfo()
|
||||
}
|
||||
DatePickerDialog(context, dateFromDialog,
|
||||
endCalendar.get(Calendar.YEAR),
|
||||
endCalendar.get(Calendar.MONTH),
|
||||
endCalendar.get(Calendar.DAY_OF_MONTH)).show()
|
||||
}
|
||||
|
||||
private fun selectEndTime() {
|
||||
TimePickerDialog(context,
|
||||
TimePickerDialog.OnTimeSetListener { _, hours, minutes ->
|
||||
endCalendar.set(Calendar.HOUR_OF_DAY, hours)
|
||||
endCalendar.set(Calendar.MINUTE, minutes)
|
||||
updateGpxInfo()
|
||||
}, 0, 0, true).show()
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
private const val TAG = "UserGpxInfoFragment"
|
||||
private const val START_KEY = "start_key"
|
||||
private const val END_KEY = "end_key"
|
||||
|
||||
private const val GPX_TRACK_COLOR = -65536
|
||||
|
||||
fun showInstance(fm: FragmentManager, gpxFile: GPXUtilities.GPXFile, start: Long, end: Long): Boolean {
|
||||
return try {
|
||||
val fragment = UserGpxInfoFragment().apply {
|
||||
arguments = Bundle().apply {
|
||||
putLong(START_KEY, start)
|
||||
putLong(END_KEY, end)
|
||||
}
|
||||
}
|
||||
fragment.gpxFile = gpxFile
|
||||
fragment.show(fm, TAG)
|
||||
true
|
||||
} catch (e: RuntimeException) {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -10,6 +10,7 @@ import android.text.TextUtils;
|
|||
|
||||
import net.osmand.Location;
|
||||
import net.osmand.PlatformUtil;
|
||||
import net.osmand.data.QuadRect;
|
||||
import net.osmand.data.RotatedTileBox;
|
||||
import net.osmand.telegram.TelegramApplication;
|
||||
import net.osmand.util.Algorithms;
|
||||
|
@ -49,7 +50,7 @@ import java.util.Set;
|
|||
import java.util.Stack;
|
||||
import java.util.TimeZone;
|
||||
|
||||
// copy from net.osmand.plus.GPXUtilities and changes done to WptPt (userId,chatId)
|
||||
// copy from net.osmand.plus.GPXUtilities and changes done to WptPt and GPXFile (userId,chatId)
|
||||
|
||||
public class GPXUtilities {
|
||||
public final static Log log = PlatformUtil.getLog(GPXUtilities.class);
|
||||
|
@ -815,6 +816,8 @@ public class GPXUtilities {
|
|||
public String path = "";
|
||||
public boolean showCurrentTrack;
|
||||
public long modifiedTime = 0;
|
||||
public int userId;
|
||||
public long chatId;
|
||||
|
||||
private Track generalTrack;
|
||||
private TrkSegment generalSegment;
|
||||
|
@ -1248,6 +1251,57 @@ public class GPXUtilities {
|
|||
}
|
||||
return categories;
|
||||
}
|
||||
|
||||
public QuadRect getRect() {
|
||||
double left = 0, right = 0;
|
||||
double top = 0, bottom = 0;
|
||||
for (Track track : tracks) {
|
||||
for (TrkSegment segment : track.segments) {
|
||||
for (WptPt p : segment.points) {
|
||||
if (left == 0 && right == 0) {
|
||||
left = p.getLongitude();
|
||||
right = p.getLongitude();
|
||||
top = p.getLatitude();
|
||||
bottom = p.getLatitude();
|
||||
} else {
|
||||
left = Math.min(left, p.getLongitude());
|
||||
right = Math.max(right, p.getLongitude());
|
||||
top = Math.max(top, p.getLatitude());
|
||||
bottom = Math.min(bottom, p.getLatitude());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (WptPt p : points) {
|
||||
if (left == 0 && right == 0) {
|
||||
left = p.getLongitude();
|
||||
right = p.getLongitude();
|
||||
top = p.getLatitude();
|
||||
bottom = p.getLatitude();
|
||||
} else {
|
||||
left = Math.min(left, p.getLongitude());
|
||||
right = Math.max(right, p.getLongitude());
|
||||
top = Math.max(top, p.getLatitude());
|
||||
bottom = Math.min(bottom, p.getLatitude());
|
||||
}
|
||||
}
|
||||
for (GPXUtilities.Route route : routes) {
|
||||
for (WptPt p : route.points) {
|
||||
if (left == 0 && right == 0) {
|
||||
left = p.getLongitude();
|
||||
right = p.getLongitude();
|
||||
top = p.getLatitude();
|
||||
bottom = p.getLatitude();
|
||||
} else {
|
||||
left = Math.min(left, p.getLongitude());
|
||||
right = Math.max(right, p.getLongitude());
|
||||
top = Math.max(top, p.getLatitude());
|
||||
bottom = Math.min(bottom, p.getLatitude());
|
||||
}
|
||||
}
|
||||
}
|
||||
return new QuadRect(left, top, right, bottom);
|
||||
}
|
||||
}
|
||||
|
||||
public static String asString(GPXFile file, TelegramApplication ctx) {
|
||||
|
|
|
@ -23,6 +23,7 @@ object OsmandFormatter {
|
|||
private const val SHORT_TIME_FORMAT = "%02d:%02d"
|
||||
private const val SIMPLE_TIME_OF_DAY_FORMAT = "HH:mm"
|
||||
private const val SIMPLE_DATE_FORMAT = "dd MMM HH:mm:ss"
|
||||
private const val SHORT_DATE_FORMAT = "dd MMM yyyy"
|
||||
|
||||
private const val MIN_DURATION_FOR_DATE_FORMAT = 48 * 60 * 60
|
||||
|
||||
|
@ -77,8 +78,13 @@ object OsmandFormatter {
|
|||
}
|
||||
}
|
||||
|
||||
fun getFormattedDate(seconds: Long): String =
|
||||
SimpleDateFormat(SIMPLE_DATE_FORMAT, Locale.getDefault()).format(seconds * 1000L)
|
||||
fun getFormattedDate(seconds: Long, shortFormat: Boolean = false): String {
|
||||
return if (shortFormat) {
|
||||
SimpleDateFormat(SIMPLE_DATE_FORMAT, Locale.getDefault()).format(seconds * 1000L)
|
||||
} else {
|
||||
SimpleDateFormat(SHORT_DATE_FORMAT, Locale.getDefault()).format(seconds * 1000L)
|
||||
}
|
||||
}
|
||||
|
||||
fun getListItemLiveTimeDescr(ctx: TelegramApplication, lastUpdated: Int, prefix: String = ""): String {
|
||||
return if (lastUpdated > 0) {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package net.osmand.aidl;
|
||||
|
||||
import net.osmand.aidl.search.SearchResult;
|
||||
import net.osmand.aidl.gpx.AGpxBitmap;
|
||||
|
||||
interface IOsmAndAidlCallback {
|
||||
void onSearchComplete(in List<SearchResult> resultSet);
|
||||
|
@ -8,4 +9,6 @@ interface IOsmAndAidlCallback {
|
|||
void onUpdate();
|
||||
|
||||
void onAppInitialized();
|
||||
|
||||
void onGpxBitmapCreated(in AGpxBitmap bitmap);
|
||||
}
|
|
@ -74,6 +74,8 @@ import net.osmand.aidl.customization.OsmandSettingsParams;
|
|||
|
||||
import net.osmand.aidl.gpx.AGpxFile;
|
||||
import net.osmand.aidl.gpx.AGpxFileDetails;
|
||||
import net.osmand.aidl.gpx.CreateGpxBitmapParams;
|
||||
|
||||
import net.osmand.aidl.tiles.ASqliteDbFile;
|
||||
|
||||
import net.osmand.aidl.plugins.PluginParams;
|
||||
|
@ -175,4 +177,6 @@ interface IOsmAndAidlInterface {
|
|||
boolean changePluginState(in PluginParams params);
|
||||
|
||||
boolean registerForOsmandInitListener(in IOsmAndAidlCallback callback);
|
||||
|
||||
boolean getBitmapForGpx(in CreateGpxBitmapParams file, IOsmAndAidlCallback callback);
|
||||
}
|
|
@ -10,6 +10,7 @@ import android.content.Intent;
|
|||
import android.content.IntentFilter;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
|
@ -24,10 +25,12 @@ import android.text.TextUtils;
|
|||
import android.view.View;
|
||||
import android.widget.ArrayAdapter;
|
||||
|
||||
import net.osmand.CallbackWithObject;
|
||||
import net.osmand.IndexConstants;
|
||||
import net.osmand.PlatformUtil;
|
||||
import net.osmand.aidl.favorite.AFavorite;
|
||||
import net.osmand.aidl.favorite.group.AFavoriteGroup;
|
||||
import net.osmand.aidl.gpx.AGpxBitmap;
|
||||
import net.osmand.aidl.gpx.AGpxFile;
|
||||
import net.osmand.aidl.gpx.AGpxFileDetails;
|
||||
import net.osmand.aidl.gpx.ASelectedGpxFile;
|
||||
|
@ -69,6 +72,7 @@ import net.osmand.plus.dialogs.ConfigureMapMenu;
|
|||
import net.osmand.plus.helpers.ColorDialogs;
|
||||
import net.osmand.plus.helpers.ExternalApiHelper;
|
||||
import net.osmand.plus.monitoring.OsmandMonitoringPlugin;
|
||||
import net.osmand.plus.myplaces.TrackBitmapDrawer;
|
||||
import net.osmand.plus.rastermaps.OsmandRasterMapsPlugin;
|
||||
import net.osmand.plus.routing.RoutingHelper;
|
||||
import net.osmand.plus.views.AidlMapLayer;
|
||||
|
@ -1907,7 +1911,96 @@ public class OsmandAidlApi {
|
|||
return app.getAppCustomization().changePluginStatus(params);
|
||||
}
|
||||
|
||||
boolean getBitmapForGpx(final Uri gpxUri, final float density, final int widthPixels, final int heightPixels, final int color, final GpxBitmapCreatedCallback callback) {
|
||||
if (gpxUri == null || callback == null) {
|
||||
return false;
|
||||
}
|
||||
final TrackBitmapDrawer.TrackBitmapDrawerListener drawerListener = new TrackBitmapDrawer.TrackBitmapDrawerListener() {
|
||||
@Override
|
||||
public void onTrackBitmapDrawing() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTrackBitmapDrawn() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTrackBitmapSelectionSupported() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawTrackBitmap(Bitmap bitmap) {
|
||||
callback.onGpxBitmapCreatedComplete(new AGpxBitmap(bitmap));
|
||||
}
|
||||
};
|
||||
|
||||
if (app.isApplicationInitializing()) {
|
||||
app.getAppInitializer().addListener(new AppInitializer.AppInitializeListener() {
|
||||
@Override
|
||||
public void onProgress(AppInitializer init, AppInitializer.InitEvents event) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFinish(AppInitializer init) {
|
||||
createGpxBitmapFromUri(gpxUri, density, widthPixels, heightPixels, color, drawerListener);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
createGpxBitmapFromUri(gpxUri, density, widthPixels, heightPixels, color, drawerListener);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void createGpxBitmapFromUri(final Uri gpxUri, final float density, final int widthPixels, final int heightPixels, final int color, final TrackBitmapDrawer.TrackBitmapDrawerListener drawerListener) {
|
||||
GpxAsyncLoaderTask gpxAsyncLoaderTask = new GpxAsyncLoaderTask(app, gpxUri, new CallbackWithObject<GPXFile>() {
|
||||
@Override
|
||||
public boolean processResult(GPXFile result) {
|
||||
TrackBitmapDrawer trackBitmapDrawer = new TrackBitmapDrawer(app, result, null, result.getRect(), density, widthPixels, heightPixels);
|
||||
trackBitmapDrawer.addListener(drawerListener);
|
||||
trackBitmapDrawer.setDrawEnabled(true);
|
||||
trackBitmapDrawer.setTrackColor(color);
|
||||
trackBitmapDrawer.initAndDraw();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
gpxAsyncLoaderTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
|
||||
private static class GpxAsyncLoaderTask extends AsyncTask<Void, Void, GPXFile> {
|
||||
|
||||
private final OsmandApplication app;
|
||||
private final CallbackWithObject<GPXFile> callback;
|
||||
private final Uri gpxUri;
|
||||
|
||||
GpxAsyncLoaderTask(@NonNull OsmandApplication app, @NonNull Uri gpxUri, final CallbackWithObject<GPXFile> callback) {
|
||||
this.app = app;
|
||||
this.gpxUri = gpxUri;
|
||||
this.callback = callback;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(GPXFile gpxFile) {
|
||||
if (gpxFile.warning == null && callback != null) {
|
||||
callback.processResult(gpxFile);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected GPXFile doInBackground(Void... voids) {
|
||||
ParcelFileDescriptor gpxParcelDescriptor = null;
|
||||
try {
|
||||
gpxParcelDescriptor = app.getContentResolver().openFileDescriptor(gpxUri, "r");
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (gpxParcelDescriptor != null) {
|
||||
final FileDescriptor fileDescriptor = gpxParcelDescriptor.getFileDescriptor();
|
||||
return GPXUtilities.loadGPXFile(app, new FileInputStream(fileDescriptor));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static AGpxFileDetails createGpxFileDetails(@NonNull GPXTrackAnalysis a) {
|
||||
return new AGpxFileDetails(a.totalDistance, a.totalTracks, a.startTime, a.endTime,
|
||||
|
@ -1980,6 +2073,10 @@ public class OsmandAidlApi {
|
|||
void onSearchComplete(List<SearchResult> resultSet);
|
||||
}
|
||||
|
||||
public interface GpxBitmapCreatedCallback {
|
||||
void onGpxBitmapCreatedComplete(AGpxBitmap aGpxBitmap);
|
||||
}
|
||||
|
||||
public interface OsmandAppInitCallback {
|
||||
void onAppInitialized();
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import android.os.RemoteException;
|
|||
import android.support.annotation.Nullable;
|
||||
|
||||
import net.osmand.PlatformUtil;
|
||||
import net.osmand.aidl.OsmandAidlApi.GpxBitmapCreatedCallback;
|
||||
import net.osmand.aidl.OsmandAidlApi.OsmandAppInitCallback;
|
||||
import net.osmand.aidl.OsmandAidlApi.SearchCompleteCallback;
|
||||
import net.osmand.aidl.calculateroute.CalculateRouteParams;
|
||||
|
@ -22,8 +23,10 @@ import net.osmand.aidl.favorite.UpdateFavoriteParams;
|
|||
import net.osmand.aidl.favorite.group.AddFavoriteGroupParams;
|
||||
import net.osmand.aidl.favorite.group.RemoveFavoriteGroupParams;
|
||||
import net.osmand.aidl.favorite.group.UpdateFavoriteGroupParams;
|
||||
import net.osmand.aidl.gpx.AGpxBitmap;
|
||||
import net.osmand.aidl.gpx.AGpxFile;
|
||||
import net.osmand.aidl.gpx.ASelectedGpxFile;
|
||||
import net.osmand.aidl.gpx.CreateGpxBitmapParams;
|
||||
import net.osmand.aidl.gpx.HideGpxParams;
|
||||
import net.osmand.aidl.gpx.ImportGpxParams;
|
||||
import net.osmand.aidl.gpx.RemoveGpxParams;
|
||||
|
@ -822,5 +825,25 @@ public class OsmandAidlService extends Service {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getBitmapForGpx(CreateGpxBitmapParams params, final IOsmAndAidlCallback callback) throws RemoteException {
|
||||
try {
|
||||
OsmandAidlApi api = getApi("getBitmapForGpx");
|
||||
return params != null && api != null && api.getBitmapForGpx(params.getGpxUri(), params.getDensity(), params.getWidthPixels(), params.getHeightPixels(), params.getColor(), new GpxBitmapCreatedCallback() {
|
||||
@Override
|
||||
public void onGpxBitmapCreatedComplete(AGpxBitmap aGpxBitmap) {
|
||||
try {
|
||||
callback.onGpxBitmapCreated(aGpxBitmap);
|
||||
} catch (RemoteException e) {
|
||||
handleException(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
handleException(e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
3
OsmAnd/src/net/osmand/aidl/gpx/AGpxBitmap.aidl
Normal file
3
OsmAnd/src/net/osmand/aidl/gpx/AGpxBitmap.aidl
Normal file
|
@ -0,0 +1,3 @@
|
|||
package net.osmand.aidl.gpx;
|
||||
|
||||
parcelable AGpxBitmap;
|
46
OsmAnd/src/net/osmand/aidl/gpx/AGpxBitmap.java
Normal file
46
OsmAnd/src/net/osmand/aidl/gpx/AGpxBitmap.java
Normal file
|
@ -0,0 +1,46 @@
|
|||
package net.osmand.aidl.gpx;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
public class AGpxBitmap implements Parcelable {
|
||||
|
||||
private Bitmap bitmap;
|
||||
|
||||
public AGpxBitmap(@NonNull Bitmap bitmap) {
|
||||
this.bitmap = bitmap;
|
||||
}
|
||||
|
||||
public AGpxBitmap(Parcel in) {
|
||||
readFromParcel(in);
|
||||
}
|
||||
|
||||
public Bitmap getBitmap() {
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
public static final Creator<AGpxBitmap> CREATOR = new
|
||||
Creator<AGpxBitmap>() {
|
||||
public AGpxBitmap createFromParcel(Parcel in) {
|
||||
return new AGpxBitmap(in);
|
||||
}
|
||||
|
||||
public AGpxBitmap[] newArray(int size) {
|
||||
return new AGpxBitmap[size];
|
||||
}
|
||||
};
|
||||
|
||||
public void writeToParcel(Parcel out, int flags) {
|
||||
out.writeParcelable(bitmap, flags);
|
||||
}
|
||||
|
||||
private void readFromParcel(Parcel in) {
|
||||
bitmap = in.readParcelable(Bitmap.class.getClassLoader());
|
||||
}
|
||||
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
package net.osmand.aidl.gpx;
|
||||
|
||||
parcelable CreateGpxBitmapParams;
|
101
OsmAnd/src/net/osmand/aidl/gpx/CreateGpxBitmapParams.java
Normal file
101
OsmAnd/src/net/osmand/aidl/gpx/CreateGpxBitmapParams.java
Normal file
|
@ -0,0 +1,101 @@
|
|||
package net.osmand.aidl.gpx;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class CreateGpxBitmapParams implements Parcelable {
|
||||
|
||||
private File gpxFile;
|
||||
private Uri gpxUri;
|
||||
private float density;
|
||||
private int widthPixels;
|
||||
private int heightPixels;
|
||||
private int color; //ARGB color int
|
||||
|
||||
public CreateGpxBitmapParams(File gpxFile, float density, int widthPixels, int heightPixels, int color) {
|
||||
this.gpxFile = gpxFile;
|
||||
this.density = density;
|
||||
this.widthPixels = widthPixels;
|
||||
this.heightPixels = heightPixels;
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
public CreateGpxBitmapParams(Uri gpxUri, float density, int widthPixels, int heightPixels, int color) {
|
||||
this.gpxUri = gpxUri;
|
||||
this.density = density;
|
||||
this.widthPixels = widthPixels;
|
||||
this.heightPixels = heightPixels;
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
public CreateGpxBitmapParams(Parcel in) {
|
||||
readFromParcel(in);
|
||||
}
|
||||
|
||||
public static final Creator<CreateGpxBitmapParams> CREATOR = new
|
||||
Creator<CreateGpxBitmapParams>() {
|
||||
public CreateGpxBitmapParams createFromParcel(Parcel in) {
|
||||
return new CreateGpxBitmapParams(in);
|
||||
}
|
||||
|
||||
public CreateGpxBitmapParams[] newArray(int size) {
|
||||
return new CreateGpxBitmapParams[size];
|
||||
}
|
||||
};
|
||||
|
||||
public File getGpxFile() {
|
||||
return gpxFile;
|
||||
}
|
||||
|
||||
public Uri getGpxUri() {
|
||||
return gpxUri;
|
||||
}
|
||||
|
||||
public int getWidthPixels() {
|
||||
return widthPixels;
|
||||
}
|
||||
|
||||
public int getHeightPixels() {
|
||||
return heightPixels;
|
||||
}
|
||||
|
||||
public float getDensity() {
|
||||
return density;
|
||||
}
|
||||
|
||||
public int getColor() {
|
||||
return color;
|
||||
}
|
||||
|
||||
public void writeToParcel(Parcel out, int flags) {
|
||||
if (gpxFile != null) {
|
||||
out.writeString(gpxFile.getAbsolutePath());
|
||||
} else {
|
||||
out.writeString(null);
|
||||
}
|
||||
out.writeParcelable(gpxUri, flags);
|
||||
out.writeFloat(density);
|
||||
out.writeInt(widthPixels);
|
||||
out.writeInt(heightPixels);
|
||||
out.writeInt(color);
|
||||
}
|
||||
|
||||
private void readFromParcel(Parcel in) {
|
||||
String gpxAbsolutePath = in.readString();
|
||||
if (gpxAbsolutePath != null) {
|
||||
gpxFile = new File(gpxAbsolutePath);
|
||||
}
|
||||
gpxUri = in.readParcelable(Uri.class.getClassLoader());
|
||||
density = in.readFloat();
|
||||
widthPixels = in.readInt();
|
||||
heightPixels = in.readInt();
|
||||
color = in.readInt();
|
||||
}
|
||||
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
}
|
|
@ -13,6 +13,7 @@ import net.osmand.Location;
|
|||
import net.osmand.PlatformUtil;
|
||||
import net.osmand.data.LocationPoint;
|
||||
import net.osmand.data.PointDescription;
|
||||
import net.osmand.data.QuadRect;
|
||||
import net.osmand.data.RotatedTileBox;
|
||||
import net.osmand.plus.views.Renderable;
|
||||
import net.osmand.util.Algorithms;
|
||||
|
@ -1247,6 +1248,57 @@ public class GPXUtilities {
|
|||
}
|
||||
return categories;
|
||||
}
|
||||
|
||||
public QuadRect getRect() {
|
||||
double left = 0, right = 0;
|
||||
double top = 0, bottom = 0;
|
||||
for (Track track : tracks) {
|
||||
for (TrkSegment segment : track.segments) {
|
||||
for (WptPt p : segment.points) {
|
||||
if (left == 0 && right == 0) {
|
||||
left = p.getLongitude();
|
||||
right = p.getLongitude();
|
||||
top = p.getLatitude();
|
||||
bottom = p.getLatitude();
|
||||
} else {
|
||||
left = Math.min(left, p.getLongitude());
|
||||
right = Math.max(right, p.getLongitude());
|
||||
top = Math.max(top, p.getLatitude());
|
||||
bottom = Math.min(bottom, p.getLatitude());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (WptPt p : points) {
|
||||
if (left == 0 && right == 0) {
|
||||
left = p.getLongitude();
|
||||
right = p.getLongitude();
|
||||
top = p.getLatitude();
|
||||
bottom = p.getLatitude();
|
||||
} else {
|
||||
left = Math.min(left, p.getLongitude());
|
||||
right = Math.max(right, p.getLongitude());
|
||||
top = Math.max(top, p.getLatitude());
|
||||
bottom = Math.min(bottom, p.getLatitude());
|
||||
}
|
||||
}
|
||||
for (GPXUtilities.Route route : routes) {
|
||||
for (WptPt p : route.points) {
|
||||
if (left == 0 && right == 0) {
|
||||
left = p.getLongitude();
|
||||
right = p.getLongitude();
|
||||
top = p.getLatitude();
|
||||
bottom = p.getLatitude();
|
||||
} else {
|
||||
left = Math.min(left, p.getLongitude());
|
||||
right = Math.max(right, p.getLongitude());
|
||||
top = Math.max(top, p.getLatitude());
|
||||
bottom = Math.min(bottom, p.getLatitude());
|
||||
}
|
||||
}
|
||||
}
|
||||
return new QuadRect(left, top, right, bottom);
|
||||
}
|
||||
}
|
||||
|
||||
public static String asString(GPXFile file, OsmandApplication ctx) {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package net.osmand.plus.activities;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.os.AsyncTask;
|
||||
|
@ -9,9 +10,11 @@ import android.support.annotation.Nullable;
|
|||
import android.support.design.widget.BottomNavigationView;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v7.app.ActionBar;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.Log;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import net.osmand.AndroidUtils;
|
||||
import net.osmand.data.LatLon;
|
||||
|
@ -20,7 +23,6 @@ import net.osmand.data.QuadRect;
|
|||
import net.osmand.plus.GPXDatabase.GpxDataItem;
|
||||
import net.osmand.plus.GPXUtilities;
|
||||
import net.osmand.plus.GPXUtilities.GPXFile;
|
||||
import net.osmand.plus.GPXUtilities.Track;
|
||||
import net.osmand.plus.GPXUtilities.TrkSegment;
|
||||
import net.osmand.plus.GPXUtilities.WptPt;
|
||||
import net.osmand.plus.GpxSelectionHelper;
|
||||
|
@ -35,7 +37,6 @@ import net.osmand.plus.mapmarkers.CoordinateInputDialogFragment;
|
|||
import net.osmand.plus.measurementtool.NewGpxData;
|
||||
import net.osmand.plus.myplaces.FavoritesActivity;
|
||||
import net.osmand.plus.myplaces.SplitSegmentDialogFragment;
|
||||
import net.osmand.plus.myplaces.TrackActivityFragmentAdapter;
|
||||
import net.osmand.plus.myplaces.TrackBitmapDrawer;
|
||||
import net.osmand.plus.myplaces.TrackBitmapDrawer.TrackBitmapDrawerListener;
|
||||
import net.osmand.plus.myplaces.TrackPointFragment;
|
||||
|
@ -156,56 +157,11 @@ public class TrackActivity extends TabActivity {
|
|||
}
|
||||
|
||||
public QuadRect getRect() {
|
||||
double left = 0, right = 0;
|
||||
double top = 0, bottom = 0;
|
||||
if (getGpx() != null) {
|
||||
for (Track track : getGpx().tracks) {
|
||||
for (TrkSegment segment : track.segments) {
|
||||
for (WptPt p : segment.points) {
|
||||
if (left == 0 && right == 0) {
|
||||
left = p.getLongitude();
|
||||
right = p.getLongitude();
|
||||
top = p.getLatitude();
|
||||
bottom = p.getLatitude();
|
||||
} else {
|
||||
left = Math.min(left, p.getLongitude());
|
||||
right = Math.max(right, p.getLongitude());
|
||||
top = Math.max(top, p.getLatitude());
|
||||
bottom = Math.min(bottom, p.getLatitude());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (WptPt p : getGpx().getPoints()) {
|
||||
if (left == 0 && right == 0) {
|
||||
left = p.getLongitude();
|
||||
right = p.getLongitude();
|
||||
top = p.getLatitude();
|
||||
bottom = p.getLatitude();
|
||||
} else {
|
||||
left = Math.min(left, p.getLongitude());
|
||||
right = Math.max(right, p.getLongitude());
|
||||
top = Math.max(top, p.getLatitude());
|
||||
bottom = Math.min(bottom, p.getLatitude());
|
||||
}
|
||||
}
|
||||
for (GPXUtilities.Route route : getGpx().routes) {
|
||||
for (WptPt p : route.points) {
|
||||
if (left == 0 && right == 0) {
|
||||
left = p.getLongitude();
|
||||
right = p.getLongitude();
|
||||
top = p.getLatitude();
|
||||
bottom = p.getLatitude();
|
||||
} else {
|
||||
left = Math.min(left, p.getLongitude());
|
||||
right = Math.max(right, p.getLongitude());
|
||||
top = Math.max(top, p.getLatitude());
|
||||
bottom = Math.min(bottom, p.getLatitude());
|
||||
}
|
||||
}
|
||||
}
|
||||
return getGpx().getRect();
|
||||
} else {
|
||||
return new QuadRect(0, 0, 0, 0);
|
||||
}
|
||||
return new QuadRect(left, top, right, bottom);
|
||||
}
|
||||
|
||||
protected void setGpxDataItem(GpxDataItem gpxDataItem) {
|
||||
|
@ -383,8 +339,11 @@ public class TrackActivity extends TabActivity {
|
|||
setGpx(gpxFile);
|
||||
setGpxDataItem(file != null ? app.getGpxDatabase().getItem(file) : null);
|
||||
|
||||
if (gpxFile != null) {
|
||||
trackBitmapDrawer = new TrackBitmapDrawer(this, gpxFile, getGpxDataItem(), getRect());
|
||||
WindowManager mgr = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
|
||||
if (gpxFile != null && mgr != null) {
|
||||
DisplayMetrics dm = new DisplayMetrics();
|
||||
mgr.getDefaultDisplay().getMetrics(dm);
|
||||
trackBitmapDrawer = new TrackBitmapDrawer(app, gpxFile, getGpxDataItem(), getRect(), dm.density, dm.widthPixels, AndroidUtils.dpToPx(app, 152f));
|
||||
}
|
||||
|
||||
for (WeakReference<Fragment> f : fragList) {
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
package net.osmand.plus.myplaces;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Canvas;
|
||||
|
@ -12,8 +10,6 @@ import android.support.annotation.ColorInt;
|
|||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import net.osmand.AndroidUtils;
|
||||
import net.osmand.data.LatLon;
|
||||
|
@ -32,15 +28,16 @@ import net.osmand.plus.resources.ResourceManager;
|
|||
import net.osmand.plus.views.OsmandMapLayer.DrawSettings;
|
||||
import net.osmand.plus.views.Renderable;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class TrackBitmapDrawer {
|
||||
|
||||
private OsmandApplication app;
|
||||
private WeakReference<Activity> activityRef;
|
||||
private QuadRect rect;
|
||||
private float density;
|
||||
private int widthPixels;
|
||||
private int heightPixels;
|
||||
|
||||
private boolean drawEnabled;
|
||||
private RotatedTileBox rotatedTileBox;
|
||||
|
@ -69,11 +66,13 @@ public class TrackBitmapDrawer {
|
|||
void drawTrackBitmap(Bitmap bitmap);
|
||||
}
|
||||
|
||||
public TrackBitmapDrawer(@NonNull Activity activity, @NonNull GPXFile gpxFile,
|
||||
@Nullable GpxDataItem gpxDataItem, @NonNull QuadRect rect) {
|
||||
this.activityRef = new WeakReference<>(activity);
|
||||
public TrackBitmapDrawer(@NonNull OsmandApplication app, @NonNull GPXFile gpxFile,
|
||||
@Nullable GpxDataItem gpxDataItem, @NonNull QuadRect rect, float density, int widthPixels, int heightPixels) {
|
||||
this.density = density;
|
||||
this.widthPixels = widthPixels;
|
||||
this.heightPixels = heightPixels;
|
||||
this.rect = rect;
|
||||
this.app = (OsmandApplication) activity.getApplication();
|
||||
this.app = app;
|
||||
this.gpxFile = gpxFile;
|
||||
this.gpxDataItem = gpxDataItem;
|
||||
|
||||
|
@ -83,8 +82,8 @@ public class TrackBitmapDrawer {
|
|||
paint.setStrokeWidth(AndroidUtils.dpToPx(app, 4f));
|
||||
defPointColor = ContextCompat.getColor(app, R.color.gpx_color_point);
|
||||
paintIcon = new Paint();
|
||||
pointSmall = BitmapFactory.decodeResource(activity.getResources(), R.drawable.map_white_shield_small);
|
||||
selectedPoint = BitmapFactory.decodeResource(activity.getResources(), R.drawable.map_default_location);
|
||||
pointSmall = BitmapFactory.decodeResource(app.getResources(), R.drawable.map_white_shield_small);
|
||||
selectedPoint = BitmapFactory.decodeResource(app.getResources(), R.drawable.map_default_location);
|
||||
}
|
||||
|
||||
public void addListener(TrackBitmapDrawerListener l) {
|
||||
|
@ -150,54 +149,48 @@ public class TrackBitmapDrawer {
|
|||
}
|
||||
|
||||
public boolean initAndDraw() {
|
||||
Activity activity = activityRef.get();
|
||||
if (activity != null) {
|
||||
WindowManager mgr = (WindowManager) activity.getSystemService(Context.WINDOW_SERVICE);
|
||||
if (mgr != null && rect != null && rect.left != 0 && rect.top != 0) {
|
||||
notifyDrawing();
|
||||
if (rect != null && rect.left != 0 && rect.top != 0) {
|
||||
notifyDrawing();
|
||||
|
||||
double clat = rect.bottom / 2 + rect.top / 2;
|
||||
double clon = rect.left / 2 + rect.right / 2;
|
||||
DisplayMetrics dm = new DisplayMetrics();
|
||||
mgr.getDefaultDisplay().getMetrics(dm);
|
||||
RotatedTileBox.RotatedTileBoxBuilder boxBuilder = new RotatedTileBox.RotatedTileBoxBuilder()
|
||||
.setLocation(clat, clon)
|
||||
.setZoom(15)
|
||||
.density(dm.density)
|
||||
.setPixelDimensions(dm.widthPixels, AndroidUtils.dpToPx(app, 152f), 0.5f, 0.5f);
|
||||
double clat = rect.bottom / 2 + rect.top / 2;
|
||||
double clon = rect.left / 2 + rect.right / 2;
|
||||
RotatedTileBox.RotatedTileBoxBuilder boxBuilder = new RotatedTileBox.RotatedTileBoxBuilder()
|
||||
.setLocation(clat, clon)
|
||||
.setZoom(15)
|
||||
.density(density)
|
||||
.setPixelDimensions(widthPixels, heightPixels, 0.5f, 0.5f);
|
||||
|
||||
rotatedTileBox = boxBuilder.build();
|
||||
while (rotatedTileBox.getZoom() < 17 && rotatedTileBox.containsLatLon(rect.top, rect.left) && rotatedTileBox.containsLatLon(rect.bottom, rect.right)) {
|
||||
rotatedTileBox.setZoom(rotatedTileBox.getZoom() + 1);
|
||||
}
|
||||
while (rotatedTileBox.getZoom() >= 7 && (!rotatedTileBox.containsLatLon(rect.top, rect.left) || !rotatedTileBox.containsLatLon(rect.bottom, rect.right))) {
|
||||
rotatedTileBox.setZoom(rotatedTileBox.getZoom() - 1);
|
||||
}
|
||||
rotatedTileBox = boxBuilder.build();
|
||||
while (rotatedTileBox.getZoom() < 17 && rotatedTileBox.containsLatLon(rect.top, rect.left) && rotatedTileBox.containsLatLon(rect.bottom, rect.right)) {
|
||||
rotatedTileBox.setZoom(rotatedTileBox.getZoom() + 1);
|
||||
}
|
||||
while (rotatedTileBox.getZoom() >= 7 && (!rotatedTileBox.containsLatLon(rect.top, rect.left) || !rotatedTileBox.containsLatLon(rect.bottom, rect.right))) {
|
||||
rotatedTileBox.setZoom(rotatedTileBox.getZoom() - 1);
|
||||
}
|
||||
|
||||
final DrawSettings drawSettings = new DrawSettings(!app.getSettings().isLightContent(), true);
|
||||
final ResourceManager resourceManager = app.getResourceManager();
|
||||
final MapRenderRepositories renderer = resourceManager.getRenderer();
|
||||
if (resourceManager.updateRenderedMapNeeded(rotatedTileBox, drawSettings)) {
|
||||
resourceManager.updateRendererMap(rotatedTileBox, new OnMapLoadedListener() {
|
||||
@Override
|
||||
public void onMapLoaded(boolean interrupted) {
|
||||
app.runInUIThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (isDrawEnabled()) {
|
||||
mapBitmap = renderer.getBitmap();
|
||||
if (mapBitmap != null) {
|
||||
notifyDrawn();
|
||||
refreshTrackBitmap();
|
||||
}
|
||||
final DrawSettings drawSettings = new DrawSettings(!app.getSettings().isLightContent(), true);
|
||||
final ResourceManager resourceManager = app.getResourceManager();
|
||||
final MapRenderRepositories renderer = resourceManager.getRenderer();
|
||||
if (resourceManager.updateRenderedMapNeeded(rotatedTileBox, drawSettings)) {
|
||||
resourceManager.updateRendererMap(rotatedTileBox, new OnMapLoadedListener() {
|
||||
@Override
|
||||
public void onMapLoaded(boolean interrupted) {
|
||||
app.runInUIThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (isDrawEnabled()) {
|
||||
mapBitmap = renderer.getBitmap();
|
||||
if (mapBitmap != null) {
|
||||
notifyDrawn();
|
||||
refreshTrackBitmap();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue