Merge pull request #11348 from osmandapp/srtmf_dialogs

Add SRTMf dialogs
This commit is contained in:
Vitaliy 2021-04-20 10:02:47 +03:00 committed by GitHub
commit 43394ce607
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
32 changed files with 1611 additions and 796 deletions

View file

@ -5,8 +5,11 @@ import net.osmand.data.QuadRect;
import net.osmand.util.Algorithms;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
public class WorldRegion implements Serializable {
@ -212,4 +215,22 @@ public class WorldRegion implements Serializable {
}
return false;
}
public static List<WorldRegion> removeDuplicates(List<WorldRegion> regions) {
List<WorldRegion> copy = new ArrayList<>(regions);
Set<WorldRegion> duplicates = new HashSet<>();
for (int i = 0; i < copy.size() - 1; i++) {
WorldRegion r1 = copy.get(i);
for (int j = i + 1; j < copy.size(); j++) {
WorldRegion r2 = copy.get(j);
if (r1.containsRegion(r2)) {
duplicates.add(r2);
} else if (r2.containsRegion(r1)) {
duplicates.add(r1);
}
}
}
copy.removeAll(duplicates);
return copy;
}
}

View file

@ -31,7 +31,7 @@
tools:text="Some title" />
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/description"
android:id="@+id/title_description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/title"
@ -60,6 +60,54 @@
</RelativeLayout>
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/primary_description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/dialog_content_margin"
android:letterSpacing="@dimen/description_letter_spacing"
android:orientation="vertical"
android:paddingStart="@dimen/content_padding"
android:paddingLeft="@dimen/content_padding"
android:paddingEnd="@dimen/content_padding"
android:paddingRight="@dimen/content_padding"
android:textColor="?android:textColorPrimary"
android:textSize="@dimen/default_list_text_size"
android:visibility="gone"
app:typeface="@string/font_roboto_regular"
tools:text="@string/srtm_download_single_help_message"
tools:visibility="visible" />
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/secondary_description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/content_padding_small"
android:letterSpacing="@dimen/description_letter_spacing"
android:orientation="vertical"
android:paddingStart="@dimen/content_padding"
android:paddingLeft="@dimen/content_padding"
android:paddingEnd="@dimen/content_padding"
android:paddingRight="@dimen/content_padding"
android:textColor="?android:textColorSecondary"
android:textSize="@dimen/default_desc_text_size"
android:visibility="gone"
app:typeface="@string/font_roboto_regular"
tools:text="@string/srtm_download_list_help_message"
tools:visibility="visible" />
<include
layout="@layout/custom_radio_buttons"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/content_padding"
android:layout_marginLeft="@dimen/content_padding"
android:layout_marginEnd="@dimen/content_padding"
android:layout_marginRight="@dimen/content_padding"
android:layout_marginBottom="@dimen/content_padding_half"
android:visibility="gone"
tools:visibility="visible" />
<LinearLayout
android:id="@+id/select_all_button"
android:layout_width="match_parent"
@ -67,12 +115,12 @@
android:background="?attr/selectableItemBackground"
android:gravity="center_vertical"
android:minHeight="@dimen/bottom_sheet_list_item_height"
android:paddingStart="@dimen/content_padding"
android:paddingLeft="@dimen/content_padding"
android:paddingTop="@dimen/content_padding_small"
android:paddingEnd="@dimen/content_padding"
android:paddingRight="@dimen/content_padding"
android:paddingBottom="@dimen/content_padding_small"
android:paddingStart="@dimen/content_padding"
android:paddingEnd="@dimen/content_padding">
android:paddingBottom="@dimen/content_padding_small">
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/check_box_title"

View file

@ -16,6 +16,10 @@
<string name="user_points">User points</string>
<string name="announce_when_exceeded">Announce when exceeded</string>
<string name="exit_number">Exit number</string>
<string name="srtm_download_single_help_message">Please select the needed format. You will need to re-download the file to change the format.</string>
<string name="srtm_download_list_help_message">OsmAnd provides contour lines data in meters and feet. You will need to re-download the file to change the format.</string>
<string name="srtm_unit_format">Contour lines unit format</string>
<string name="shared_string_feet">feet</string>
<string name="update_all_maps_added">Update all maps added to %1$s?</string>
<string name="release_4_0_beta">
• OsmAnd Live updates moved to \"Downloads > Updates\"\n\n

View file

@ -13,6 +13,7 @@ import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.SQLiteTileSource;
import net.osmand.plus.Version;
import net.osmand.plus.download.SrtmDownloadItem;
import net.osmand.plus.download.ui.AbstractLoadLocalIndexTask;
import net.osmand.plus.voice.JSMediaCommandPlayerImpl;
import net.osmand.plus.voice.JSTTSCommandPlayerImpl;
@ -143,8 +144,6 @@ public class LocalIndexHelper {
return null;
}
public List<LocalIndexInfo> getLocalIndexInfos(String downloadName) {
List<LocalIndexInfo> list = new ArrayList<>();
LocalIndexInfo info = getLocalIndexInfo(LocalIndexType.MAP_DATA, downloadName, false, false);
@ -313,7 +312,7 @@ public class LocalIndexHelper {
}
}
}
private void loadTravelData(File mapPath, List<LocalIndexInfo> result, AbstractLoadLocalIndexTask loadTask) {
if (mapPath.canRead()) {
for (File mapFile : listFilesSorted(mapPath)) {
@ -333,14 +332,15 @@ public class LocalIndexHelper {
if (mapPath.canRead()) {
for (File mapFile : listFilesSorted(mapPath)) {
if (mapFile.isFile() && mapFile.getName().endsWith(IndexConstants.BINARY_MAP_INDEX_EXT)) {
String fileName = mapFile.getName();
LocalIndexType lt = LocalIndexType.MAP_DATA;
if (mapFile.getName().endsWith(IndexConstants.BINARY_SRTM_MAP_INDEX_EXT)) {
if (SrtmDownloadItem.isSrtmFile(fileName)) {
lt = LocalIndexType.SRTM_DATA;
} else if (mapFile.getName().endsWith(IndexConstants.BINARY_WIKI_MAP_INDEX_EXT)) {
} else if (fileName.endsWith(IndexConstants.BINARY_WIKI_MAP_INDEX_EXT)) {
lt = LocalIndexType.WIKI_DATA;
}
LocalIndexInfo info = new LocalIndexInfo(lt, mapFile, backup, app);
if (loadedMaps.containsKey(mapFile.getName()) && !backup) {
if (loadedMaps.containsKey(fileName) && !backup) {
info.setLoaded(true);
}
updateDescription(info);
@ -403,7 +403,7 @@ public class LocalIndexHelper {
if (fileName.endsWith(IndexConstants.SQLITE_EXT)) {
return fileName.substring(0, fileName.length() - IndexConstants.SQLITE_EXT.length());
}
if (localIndexInfo.getType() == TRAVEL_DATA &&
if (localIndexInfo.getType() == TRAVEL_DATA &&
fileName.endsWith(IndexConstants.BINARY_WIKIVOYAGE_MAP_INDEX_EXT)) {
return fileName.substring(0, fileName.length() - IndexConstants.BINARY_WIKIVOYAGE_MAP_INDEX_EXT.length());
}
@ -430,5 +430,4 @@ public class LocalIndexHelper {
return fileName;
}
}
}

View file

@ -0,0 +1,80 @@
package net.osmand.plus.base;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.FragmentManager;
import net.osmand.AndroidUtils;
import net.osmand.plus.R;
import net.osmand.plus.widgets.MultiStateToggleButton.RadioItem;
import java.util.Collections;
import java.util.List;
public class ModeSelectionBottomSheet extends SelectionBottomSheet {
public static final String TAG = ModeSelectionBottomSheet.class.getSimpleName();
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
showElements(primaryDescription, toggleContainer);
hideElements(checkBox, checkBoxTitle, titleDescription,
secondaryDescription, selectedSize, selectAllButton);
}
@Override
protected void updateItemView(SelectableItem item, View view) {
ImageView ivIcon = view.findViewById(R.id.icon);
TextView tvTitle = view.findViewById(R.id.title);
TextView tvDescr = view.findViewById(R.id.description);
Drawable icon = uiUtilities.getIcon(item.getIconId(), activeColorRes);
ivIcon.setImageDrawable(icon);
tvTitle.setText(item.getTitle());
tvDescr.setText(item.getDescription());
tvDescr.setTextColor(ContextCompat.getColor(app, AndroidUtils.getSecondaryTextColorId(nightMode)));
}
@Override
protected int getItemLayoutId() {
return R.layout.bottom_sheet_item_with_descr_56dp;
}
public void setItem(SelectableItem item) {
setItems(Collections.singletonList(item));
}
@NonNull
@Override
public List<SelectableItem> getSelectedItems() {
return allItems;
}
@Override
protected boolean shouldShowDivider() {
return false;
}
public static ModeSelectionBottomSheet showInstance(@NonNull AppCompatActivity activity,
@NonNull SelectableItem previewItem,
@NonNull List<RadioItem> radioItems,
boolean usedOnMap) {
ModeSelectionBottomSheet fragment = new ModeSelectionBottomSheet();
fragment.setUsedOnMap(usedOnMap);
fragment.setModes(radioItems);
fragment.setItems(Collections.singletonList(previewItem));
FragmentManager fm = activity.getSupportFragmentManager();
fragment.show(fm, TAG);
return fragment;
}
}

View file

@ -0,0 +1,180 @@
package net.osmand.plus.base;
import android.content.res.ColorStateList;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;
import androidx.core.widget.CompoundButtonCompat;
import androidx.fragment.app.FragmentManager;
import net.osmand.AndroidUtils;
import net.osmand.plus.R;
import net.osmand.plus.helpers.AndroidUiHelper;
import net.osmand.util.Algorithms;
import java.util.ArrayList;
import java.util.List;
import static net.osmand.view.ThreeStateCheckbox.State.CHECKED;
import static net.osmand.view.ThreeStateCheckbox.State.MISC;
import static net.osmand.view.ThreeStateCheckbox.State.UNCHECKED;
public class MultipleSelectionBottomSheet extends SelectionBottomSheet {
public static final String TAG = MultipleSelectionBottomSheet.class.getSimpleName();
private final List<SelectableItem> selectedItems = new ArrayList<>();
private SelectionUpdateListener selectionUpdateListener;
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
selectAllButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
checkBox.performClick();
boolean checked = checkBox.getState() == CHECKED;
if (checked) {
selectedItems.addAll(allItems);
} else {
selectedItems.clear();
}
onSelectedItemsChanged();
updateItemsSelection(checked);
}
});
}
@Override
protected boolean shouldShowDivider() {
return true;
}
@Override
protected void updateItemView(final SelectableItem item, View view) {
boolean checked = selectedItems.contains(item);
ImageView imageView = view.findViewById(R.id.icon);
TextView title = view.findViewById(R.id.title);
TextView description = view.findViewById(R.id.description);
final CheckBox checkBox = view.findViewById(R.id.compound_button);
AndroidUiHelper.setVisibility(View.VISIBLE, imageView, title, description, checkBox);
checkBox.setChecked(checked);
CompoundButtonCompat.setButtonTintList(checkBox, AndroidUtils.createCheckedColorStateList(app, secondaryColorRes, activeColorRes));
view.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
boolean checked = !checkBox.isChecked();
checkBox.setChecked(checked);
if (checked) {
selectedItems.add(item);
} else {
selectedItems.remove(item);
}
onSelectedItemsChanged();
}
});
title.setText(item.getTitle());
description.setText(item.getDescription());
imageView.setImageDrawable(uiUtilities.getIcon(item.getIconId(), activeColorRes));
}
@Override
protected int getItemLayoutId() {
return R.layout.bottom_sheet_item_with_descr_and_checkbox_56dp;
}
@Override
protected void notifyUiInitialized() {
onSelectedItemsChanged();
super.notifyUiInitialized();
}
private void onSelectedItemsChanged() {
updateSelectAllButton();
updateSelectedSizeView();
updateApplyButtonEnable();
if (selectionUpdateListener != null) {
selectionUpdateListener.onSelectionUpdate();
}
}
private void updateSelectAllButton() {
String checkBoxTitle;
if (Algorithms.isEmpty(selectedItems)) {
checkBox.setState(UNCHECKED);
checkBoxTitle = getString(R.string.shared_string_select_all);
} else {
checkBox.setState(selectedItems.containsAll(allItems) ? CHECKED : MISC);
checkBoxTitle = getString(R.string.shared_string_deselect_all);
}
int checkBoxColor = checkBox.getState() == UNCHECKED ? secondaryColorRes : activeColorRes;
CompoundButtonCompat.setButtonTintList(checkBox, ColorStateList.valueOf(ContextCompat.getColor(app, checkBoxColor)));
this.checkBoxTitle.setText(checkBoxTitle);
}
private void updateSelectedSizeView() {
String selected = String.valueOf(selectedItems.size());
String all = String.valueOf(allItems.size());
selectedSize.setText(getString(R.string.ltr_or_rtl_combine_via_slash, selected, all));
}
private void updateApplyButtonEnable() {
boolean noEmptySelection = !Algorithms.isEmpty(selectedItems);
rightButton.setEnabled(noEmptySelection);
}
private void updateItemsSelection(boolean checked) {
for (SelectableItem item : allItems) {
View v = listViews.get(item);
CheckBox checkBox = v != null ? (CheckBox) v.findViewById(R.id.compound_button) : null;
if (checkBox != null) {
checkBox.setChecked(checked);
}
}
}
protected void setSelectedItems(List<SelectableItem> selected) {
selectedItems.clear();
if (!Algorithms.isEmpty(selected)) {
selectedItems.addAll(selected);
}
}
@NonNull
@Override
public List<SelectableItem> getSelectedItems() {
return selectedItems;
}
public void setSelectionUpdateListener(SelectionUpdateListener selectionUpdateListener) {
this.selectionUpdateListener = selectionUpdateListener;
}
public static MultipleSelectionBottomSheet showInstance(@NonNull AppCompatActivity activity,
@NonNull List<SelectableItem> items,
@Nullable List<SelectableItem> selected,
boolean usedOnMap) {
MultipleSelectionBottomSheet fragment = new MultipleSelectionBottomSheet();
fragment.setUsedOnMap(usedOnMap);
fragment.setItems(items);
fragment.setSelectedItems(selected);
FragmentManager fm = activity.getSupportFragmentManager();
fragment.show(fm, TAG);
return fragment;
}
public interface SelectionUpdateListener {
void onSelectionUpdate();
}
}

View file

@ -0,0 +1,41 @@
package net.osmand.plus.base;
import android.os.Bundle;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.FragmentManager;
import net.osmand.plus.widgets.MultiStateToggleButton.RadioItem;
import java.util.List;
public class MultipleSelectionWithModeBottomSheet extends MultipleSelectionBottomSheet {
public static final String TAG = MultipleSelectionWithModeBottomSheet.class.getSimpleName();
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
showElements(secondaryDescription, toggleContainer, checkBox,
checkBoxTitle, titleDescription, selectedSize, selectAllButton);
}
public static MultipleSelectionWithModeBottomSheet showInstance(@NonNull AppCompatActivity activity,
@NonNull List<SelectableItem> items,
@Nullable List<SelectableItem> selected,
@NonNull List<RadioItem> modes,
boolean usedOnMap) {
MultipleSelectionWithModeBottomSheet fragment = new MultipleSelectionWithModeBottomSheet();
fragment.setUsedOnMap(usedOnMap);
fragment.setItems(items);
fragment.setSelectedItems(selected);
fragment.setModes(modes);
FragmentManager fm = activity.getSupportFragmentManager();
fragment.show(fm, TAG);
return fragment;
}
}

View file

@ -1,301 +0,0 @@
package net.osmand.plus.base;
import android.content.res.ColorStateList;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;
import androidx.core.widget.CompoundButtonCompat;
import androidx.fragment.app.FragmentManager;
import net.osmand.AndroidUtils;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.UiUtilities;
import net.osmand.plus.base.bottomsheetmenu.BaseBottomSheetItem;
import net.osmand.plus.base.bottomsheetmenu.BottomSheetItemWithCompoundButton;
import net.osmand.plus.base.bottomsheetmenu.BottomSheetItemWithCompoundButton.Builder;
import net.osmand.plus.base.bottomsheetmenu.SimpleBottomSheetItem;
import net.osmand.plus.base.bottomsheetmenu.simpleitems.SimpleDividerItem;
import net.osmand.util.Algorithms;
import net.osmand.view.ThreeStateCheckbox;
import java.util.ArrayList;
import java.util.List;
import static net.osmand.view.ThreeStateCheckbox.State.CHECKED;
import static net.osmand.view.ThreeStateCheckbox.State.MISC;
import static net.osmand.view.ThreeStateCheckbox.State.UNCHECKED;
public class SelectMultipleItemsBottomSheet extends MenuBottomSheetDialogFragment {
private OsmandApplication app;
private UiUtilities uiUtilities;
private TextView title;
private TextView description;
private TextView applyButtonTitle;
private TextView checkBoxTitle;
private TextView selectedSize;
private ThreeStateCheckbox checkBox;
private int activeColorRes;
private int secondaryColorRes;
private final List<SelectableItem> allItems = new ArrayList<>();
private final List<SelectableItem> selectedItems = new ArrayList<>();
private SelectionUpdateListener selectionUpdateListener;
private OnApplySelectionListener onApplySelectionListener;
public static final String TAG = SelectMultipleItemsBottomSheet.class.getSimpleName();
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
View mainView = super.onCreateView(inflater, parent, savedInstanceState);
onSelectedItemsChanged();
return mainView;
}
@Override
public void createMenuItems(Bundle savedInstanceState) {
app = requiredMyApplication();
uiUtilities = app.getUIUtilities();
activeColorRes = nightMode ? R.color.icon_color_active_dark : R.color.icon_color_active_light;
secondaryColorRes = nightMode ? R.color.icon_color_secondary_dark : R.color.icon_color_secondary_light;
items.add(createTitleItem());
items.add(new SimpleDividerItem(app));
createListItems();
}
private BaseBottomSheetItem createTitleItem() {
LayoutInflater themedInflater = UiUtilities.getInflater(requireContext(), nightMode);
View view = themedInflater.inflate(R.layout.settings_group_title, null);
checkBox = view.findViewById(R.id.check_box);
checkBoxTitle = view.findViewById(R.id.check_box_title);
description = view.findViewById(R.id.description);
selectedSize = view.findViewById(R.id.selected_size);
title = view.findViewById(R.id.title);
View selectAllButton = view.findViewById(R.id.select_all_button);
selectAllButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
checkBox.performClick();
boolean checked = checkBox.getState() == CHECKED;
if (checked) {
selectedItems.addAll(allItems);
} else {
selectedItems.clear();
}
onSelectedItemsChanged();
updateItems(checked);
}
});
return new SimpleBottomSheetItem.Builder().setCustomView(view).create();
}
private void createListItems() {
for (final SelectableItem item : allItems) {
boolean checked = selectedItems.contains(item);
final BottomSheetItemWithCompoundButton[] uiItem = new BottomSheetItemWithCompoundButton[1];
final Builder builder = (BottomSheetItemWithCompoundButton.Builder) new Builder();
builder.setChecked(checked)
.setButtonTintList(AndroidUtils.createCheckedColorStateList(app, secondaryColorRes, activeColorRes))
.setLayoutId(R.layout.bottom_sheet_item_with_descr_and_checkbox_56dp)
.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
boolean checked = !uiItem[0].isChecked();
uiItem[0].setChecked(checked);
SelectableItem tag = (SelectableItem) uiItem[0].getTag();
if (checked) {
selectedItems.add(tag);
} else {
selectedItems.remove(tag);
}
onSelectedItemsChanged();
}
})
.setTag(item);
setupListItem(builder, item);
uiItem[0] = builder.create();
items.add(uiItem[0]);
}
}
@Override
protected void setupRightButton() {
super.setupRightButton();
applyButtonTitle = rightButton.findViewById(R.id.button_text);
}
@Override
protected void onRightBottomButtonClick() {
if (onApplySelectionListener != null) {
onApplySelectionListener.onSelectionApplied(selectedItems);
}
dismiss();
}
private void onSelectedItemsChanged() {
updateSelectAllButton();
updateSelectedSizeView();
updateApplyButtonEnable();
if (selectionUpdateListener != null) {
selectionUpdateListener.onSelectionUpdate();
}
}
@Override
protected int getRightBottomButtonTextId() {
return R.string.shared_string_apply;
}
@Override
protected boolean useVerticalButtons() {
return true;
}
private void setupListItem(Builder builder, SelectableItem item) {
builder.setTitle(item.title);
builder.setDescription(item.description);
builder.setIcon(uiUtilities.getIcon(item.iconId, activeColorRes));
}
private void updateSelectAllButton() {
String checkBoxTitle;
if (Algorithms.isEmpty(selectedItems)) {
checkBox.setState(UNCHECKED);
checkBoxTitle = getString(R.string.shared_string_select_all);
} else {
checkBox.setState(selectedItems.containsAll(allItems) ? CHECKED : MISC);
checkBoxTitle = getString(R.string.shared_string_deselect_all);
}
int checkBoxColor = checkBox.getState() == UNCHECKED ? secondaryColorRes : activeColorRes;
CompoundButtonCompat.setButtonTintList(checkBox, ColorStateList.valueOf(ContextCompat.getColor(app, checkBoxColor)));
this.checkBoxTitle.setText(checkBoxTitle);
}
private void updateSelectedSizeView() {
String selected = String.valueOf(selectedItems.size());
String all = String.valueOf(allItems.size());
selectedSize.setText(getString(R.string.ltr_or_rtl_combine_via_slash, selected, all));
}
private void updateApplyButtonEnable() {
if (Algorithms.isEmpty(selectedItems)) {
rightButton.setEnabled(false);
} else {
rightButton.setEnabled(true);
}
}
private void updateItems(boolean checked) {
for (BaseBottomSheetItem item : items) {
if (item instanceof BottomSheetItemWithCompoundButton) {
((BottomSheetItemWithCompoundButton) item).setChecked(checked);
}
}
}
public void setTitle(@NonNull String title) {
this.title.setText(title);
}
public void setDescription(@NonNull String description) {
this.description.setText(description);
}
public void setConfirmButtonTitle(@NonNull String confirmButtonTitle) {
applyButtonTitle.setText(confirmButtonTitle);
}
private void setItems(List<SelectableItem> allItems) {
if (!Algorithms.isEmpty(allItems)) {
this.allItems.addAll(allItems);
}
}
private void setSelectedItems(List<SelectableItem> selected) {
if (!Algorithms.isEmpty(selected)) {
this.selectedItems.addAll(selected);
}
}
public List<SelectableItem> getSelectedItems() {
return selectedItems;
}
@Override
public void onPause() {
super.onPause();
if (requireActivity().isChangingConfigurations()) {
dismiss();
}
}
public static SelectMultipleItemsBottomSheet showInstance(@NonNull AppCompatActivity activity,
@NonNull List<SelectableItem> items,
@Nullable List<SelectableItem> selected,
boolean usedOnMap) {
SelectMultipleItemsBottomSheet fragment = new SelectMultipleItemsBottomSheet();
fragment.setUsedOnMap(usedOnMap);
fragment.setItems(items);
fragment.setSelectedItems(selected);
FragmentManager fm = activity.getSupportFragmentManager();
fragment.show(fm, TAG);
return fragment;
}
public void setSelectionUpdateListener(SelectionUpdateListener selectionUpdateListener) {
this.selectionUpdateListener = selectionUpdateListener;
}
public void setOnApplySelectionListener(OnApplySelectionListener onApplySelectionListener) {
this.onApplySelectionListener = onApplySelectionListener;
}
public interface SelectionUpdateListener {
void onSelectionUpdate();
}
public interface OnApplySelectionListener {
void onSelectionApplied(List<SelectableItem> selectedItems);
}
public static class SelectableItem {
private String title;
private String description;
private int iconId;
private Object object;
public void setTitle(String title) {
this.title = title;
}
public void setDescription(String description) {
this.description = description;
}
public void setIconId(int iconId) {
this.iconId = iconId;
}
public void setObject(Object object) {
this.object = object;
}
public Object getObject() {
return object;
}
}
}

View file

@ -0,0 +1,289 @@
package net.osmand.plus.base;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.UiUtilities;
import net.osmand.plus.base.bottomsheetmenu.BaseBottomSheetItem;
import net.osmand.plus.base.bottomsheetmenu.SimpleBottomSheetItem;
import net.osmand.plus.base.bottomsheetmenu.simpleitems.SimpleDividerItem;
import net.osmand.plus.helpers.AndroidUiHelper;
import net.osmand.plus.widgets.MultiStateToggleButton;
import net.osmand.plus.widgets.MultiStateToggleButton.RadioItem;
import net.osmand.util.Algorithms;
import net.osmand.view.ThreeStateCheckbox;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public abstract class SelectionBottomSheet extends MenuBottomSheetDialogFragment {
protected OsmandApplication app;
protected LayoutInflater inflater;
protected UiUtilities uiUtilities;
protected TextView title;
protected TextView titleDescription;
protected TextView primaryDescription;
protected TextView secondaryDescription;
protected TextView selectedSize;
protected LinearLayout toggleContainer;
protected MultiStateToggleButton radioGroup;
protected View selectAllButton;
protected TextView checkBoxTitle;
protected ThreeStateCheckbox checkBox;
protected LinearLayout listContainer;
protected TextView applyButtonTitle;
protected int activeColorRes;
protected int secondaryColorRes;
private OnUiInitializedAdapter onUiInitializedAdapter;
private OnApplySelectionListener onApplySelectionListener;
protected List<SelectableItem> allItems = new ArrayList<>();
protected Map<SelectableItem, View> listViews = new HashMap<>();
private List<RadioItem> modes;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
View mainView = super.onCreateView(inflater, parent, savedInstanceState);
createSelectionListIfPossible();
notifyUiInitialized();
return mainView;
}
@Override
public void createMenuItems(Bundle savedInstanceState) {
app = requiredMyApplication();
uiUtilities = app.getUIUtilities();
inflater = UiUtilities.getInflater(requireContext(), nightMode);
activeColorRes = nightMode ? R.color.icon_color_active_dark : R.color.icon_color_active_light;
secondaryColorRes = nightMode ? R.color.icon_color_secondary_dark : R.color.icon_color_secondary_light;
items.add(createHeaderView());
if (shouldShowDivider()) {
items.add(new SimpleDividerItem(app));
}
items.add(createSelectionView());
}
private BaseBottomSheetItem createHeaderView() {
View view = inflater.inflate(R.layout.settings_group_title, null);
title = view.findViewById(R.id.title);
titleDescription = view.findViewById(R.id.title_description);
primaryDescription = view.findViewById(R.id.primary_description);
secondaryDescription = view.findViewById(R.id.secondary_description);
selectedSize = view.findViewById(R.id.selected_size);
toggleContainer = view.findViewById(R.id.custom_radio_buttons);
radioGroup = new MultiStateToggleButton(app, toggleContainer, nightMode);
selectAllButton = view.findViewById(R.id.select_all_button);
checkBoxTitle = view.findViewById(R.id.check_box_title);
checkBox = view.findViewById(R.id.check_box);
if (modes != null) {
radioGroup.setItems(modes);
}
return new SimpleBottomSheetItem.Builder().setCustomView(view).create();
}
private BaseBottomSheetItem createSelectionView() {
Context themedCtx = UiUtilities.getThemedContext(requireContext(), nightMode);
listContainer = new LinearLayout(themedCtx);
listContainer.setLayoutParams(new LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
listContainer.setOrientation(LinearLayout.VERTICAL);
return new SimpleBottomSheetItem.Builder().setCustomView(listContainer).create();
}
public void setTitle(@NonNull String title) {
this.title.setText(title);
}
public void setTitleDescription(@NonNull String description) {
titleDescription.setText(description);
}
public void setPrimaryDescription(@NonNull String description) {
primaryDescription.setText(description);
}
public void setSecondaryDescription(@NonNull String description) {
secondaryDescription.setText(description);
}
public void setApplyButtonTitle(@NonNull String title) {
applyButtonTitle.setText(title);
}
public void setModes(@NonNull List<RadioItem> modes) {
this.modes = modes;
if (radioGroup != null) {
radioGroup.setItems(modes);
}
}
public void setSelectedMode(@NonNull RadioItem mode) {
radioGroup.setSelectedItem(mode);
}
public void setItems(List<SelectableItem> allItems) {
this.allItems.clear();
if (!Algorithms.isEmpty(allItems)) {
this.allItems.addAll(allItems);
createSelectionListIfPossible();
}
}
public void setOnUiInitializedAdapter(OnUiInitializedAdapter onUiInitializedAdapter) {
this.onUiInitializedAdapter = onUiInitializedAdapter;
}
public void setOnApplySelectionListener(OnApplySelectionListener onApplySelectionListener) {
this.onApplySelectionListener = onApplySelectionListener;
}
private void createSelectionListIfPossible() {
if (listContainer != null && allItems != null) {
recreateList();
}
}
private void recreateList() {
listViews.clear();
listContainer.removeAllViews();
for (SelectableItem item : allItems) {
setupItemView(item, inflater.inflate(getItemLayoutId(), null));
}
}
private void setupItemView(SelectableItem item, View view) {
updateItemView(item, view);
listViews.put(item, view);
listContainer.addView(view);
}
public List<SelectableItem> getAllItems() {
return allItems;
}
@NonNull
public abstract List<SelectableItem> getSelectedItems();
protected abstract void updateItemView(SelectableItem item, View view);
protected abstract int getItemLayoutId();
protected abstract boolean shouldShowDivider();
protected void notifyUiInitialized() {
if (onUiInitializedAdapter != null) {
onUiInitializedAdapter.onUiInitialized();
}
}
protected void showElements(View... views) {
AndroidUiHelper.setVisibility(View.VISIBLE, views);
}
protected void hideElements(View... views) {
AndroidUiHelper.setVisibility(View.GONE, views);
}
@Override
protected void setupRightButton() {
super.setupRightButton();
applyButtonTitle = rightButton.findViewById(R.id.button_text);
}
@Override
protected void onRightBottomButtonClick() {
if (onApplySelectionListener != null) {
onApplySelectionListener.onSelectionApplied(getSelectedItems());
}
dismiss();
}
@Override
protected int getRightBottomButtonTextId() {
return R.string.shared_string_apply;
}
@Override
protected boolean useVerticalButtons() {
return true;
}
@Override
public void onPause() {
super.onPause();
if (requireActivity().isChangingConfigurations()) {
dismiss();
}
}
public interface OnUiInitializedAdapter {
void onUiInitialized();
}
public interface OnApplySelectionListener {
void onSelectionApplied(List<SelectableItem> selectedItems);
}
public static class SelectableItem {
private String title;
private String description;
private int iconId;
private Object object;
public String getTitle() {
return title;
}
public String getDescription() {
return description;
}
public int getIconId() {
return iconId;
}
public Object getObject() {
return object;
}
public void setTitle(String title) {
this.title = title;
}
public void setDescription(String description) {
this.description = description;
}
public void setIconId(int iconId) {
this.iconId = iconId;
}
public void setObject(Object object) {
this.object = object;
}
}
}

View file

@ -32,6 +32,10 @@ public class BaseBottomSheetItem {
return tag;
}
public void setTag(Object tag) {
this.tag = tag;
}
public BaseBottomSheetItem(View view,
@LayoutRes int layoutId,
Object tag,

View file

@ -10,6 +10,7 @@ import net.osmand.map.OsmandRegions;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.Version;
import net.osmand.plus.activities.LocalIndexInfo;
import net.osmand.plus.helpers.FileNameTranslationHelper;
import net.osmand.util.Algorithms;
@ -27,11 +28,12 @@ import java.util.Locale;
import java.util.Map;
import static net.osmand.IndexConstants.BINARY_MAP_INDEX_EXT;
import static net.osmand.plus.activities.LocalIndexHelper.LocalIndexType.SRTM_DATA;
public class DownloadActivityType {
private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd.MM.yyyy", Locale.US);
private static Map<String, DownloadActivityType> byTag = new HashMap<>();
public static final DownloadActivityType NORMAL_FILE =
new DownloadActivityType(R.string.download_regular_maps, "map", 10);
public static final DownloadActivityType VOICE_FILE =
@ -83,7 +85,7 @@ public class DownloadActivityType {
iconResource = R.drawable.ic_map;
}
public int getStringResource(){
public int getStringResource() {
return stringResource;
}
@ -101,7 +103,7 @@ public class DownloadActivityType {
public static boolean isCountedInDownloads(IndexItem es) {
DownloadActivityType tp = es.getType();
if(tp == NORMAL_FILE || tp == ROADS_FILE){
if (tp == NORMAL_FILE || tp == ROADS_FILE) {
if (!es.extra) {
return true;
}
@ -120,17 +122,17 @@ public class DownloadActivityType {
public static Collection<DownloadActivityType> values() {
return byTag.values();
}
protected static String addVersionToExt(String ext, int version) {
return "_" + version + ext;
}
public boolean isAccepted(String fileName) {
if(NORMAL_FILE == this) {
return fileName.endsWith(addVersionToExt(IndexConstants.BINARY_MAP_INDEX_EXT_ZIP, IndexConstants.BINARY_MAP_VERSION))
if (NORMAL_FILE == this) {
return fileName.endsWith(addVersionToExt(IndexConstants.BINARY_MAP_INDEX_EXT_ZIP, IndexConstants.BINARY_MAP_VERSION))
|| fileName.endsWith(IndexConstants.EXTRA_ZIP_EXT)
|| fileName.endsWith(IndexConstants.SQLITE_EXT);
} else if(ROADS_FILE == this) {
} else if (ROADS_FILE == this) {
return fileName.endsWith(addVersionToExt(IndexConstants.BINARY_ROAD_MAP_INDEX_EXT_ZIP, IndexConstants.BINARY_MAP_VERSION));
} else if (VOICE_FILE == this) {
return fileName.endsWith(addVersionToExt(IndexConstants.VOICE_INDEX_EXT_ZIP, IndexConstants.VOICE_VERSION));
@ -145,8 +147,9 @@ public class DownloadActivityType {
return fileName.endsWith(addVersionToExt(IndexConstants.BINARY_TRAVEL_GUIDE_MAP_INDEX_EXT_ZIP,
IndexConstants.BINARY_MAP_VERSION));
} else if (SRTM_COUNTRY_FILE == this) {
return fileName.endsWith(addVersionToExt(IndexConstants.BINARY_SRTM_MAP_INDEX_EXT_ZIP,
IndexConstants.BINARY_MAP_VERSION));
boolean srtm = fileName.endsWith(addVersionToExt(IndexConstants.BINARY_SRTM_MAP_INDEX_EXT_ZIP, IndexConstants.BINARY_MAP_VERSION));
boolean srtmf = fileName.endsWith(addVersionToExt(IndexConstants.BINARY_SRTM_FEET_MAP_INDEX_EXT_ZIP, IndexConstants.BINARY_MAP_VERSION));
return srtm || srtmf;
} else if (HILLSHADE_FILE == this) {
return fileName.endsWith(IndexConstants.SQLITE_EXT);
} else if (SLOPE_FILE == this) {
@ -160,7 +163,7 @@ public class DownloadActivityType {
}
return false;
}
public File getDownloadFolder(OsmandApplication ctx, IndexItem indexItem) {
if (NORMAL_FILE == this) {
if (indexItem.fileName.endsWith(IndexConstants.SQLITE_EXT)) {
@ -196,17 +199,17 @@ public class DownloadActivityType {
}
public boolean isZipStream(OsmandApplication ctx, IndexItem indexItem) {
return HILLSHADE_FILE != this && SLOPE_FILE != this && SQLITE_FILE != this && WIKIVOYAGE_FILE != this && GPX_FILE != this;
return HILLSHADE_FILE != this && SLOPE_FILE != this && SQLITE_FILE != this && WIKIVOYAGE_FILE != this && GPX_FILE != this;
}
public boolean isZipFolder(OsmandApplication ctx, IndexItem indexItem) {
return this == VOICE_FILE;
}
public boolean preventMediaIndexing(OsmandApplication ctx, IndexItem indexItem) {
return this == VOICE_FILE && indexItem.fileName.endsWith(IndexConstants.VOICE_INDEX_EXT_ZIP);
}
public String getUnzipExtension(OsmandApplication ctx, IndexItem indexItem) {
if (NORMAL_FILE == this) {
if (indexItem.fileName.endsWith(IndexConstants.BINARY_MAP_INDEX_EXT_ZIP)) {
@ -217,7 +220,7 @@ public class DownloadActivityType {
return IndexConstants.EXTRA_EXT;
} else if (indexItem.fileName.endsWith(IndexConstants.SQLITE_EXT)) {
return IndexConstants.SQLITE_EXT;
} else if (indexItem.fileName.endsWith(IndexConstants.ANYVOICE_INDEX_EXT_ZIP)){
} else if (indexItem.fileName.endsWith(IndexConstants.ANYVOICE_INDEX_EXT_ZIP)) {
return "";
}
} else if (ROADS_FILE == this) {
@ -227,7 +230,7 @@ public class DownloadActivityType {
} else if (FONT_FILE == this) {
return IndexConstants.FONT_INDEX_EXT;
} else if (SRTM_COUNTRY_FILE == this) {
return IndexConstants.BINARY_SRTM_MAP_INDEX_EXT;
return SrtmDownloadItem.getExtension(indexItem);
} else if (WIKIPEDIA_FILE == this) {
return IndexConstants.BINARY_WIKI_MAP_INDEX_EXT;
} else if (WIKIVOYAGE_FILE == this) {
@ -249,9 +252,9 @@ public class DownloadActivityType {
}
throw new UnsupportedOperationException();
}
public String getUrlSuffix(OsmandApplication ctx) {
if (this== ROADS_FILE) {
if (this == ROADS_FILE) {
return "&road=yes";
} else if (this == LIVE_UPDATES_FILE) {
return "&aosmc=yes";
@ -280,7 +283,7 @@ public class DownloadActivityType {
public String getBaseUrl(OsmandApplication ctx, String fileName) {
String url = "https://" + IndexConstants.INDEX_DOWNLOAD_DOMAIN + "/download?event=2&"
+ Version.getVersionAsURLParam(ctx) + "&file=" + encode(fileName);
if(this == LIVE_UPDATES_FILE && fileName.length() > 16) {
if (this == LIVE_UPDATES_FILE && fileName.length() > 16) {
// DATE_AND_EXT_STR_LEN = "_18_06_02.obf.gz".length()
String region = fileName.substring(0, fileName.length() - 16).toLowerCase();
url += "&region=" + encode(region);
@ -343,7 +346,7 @@ public class DownloadActivityType {
}
return "";
}
public String getVisibleName(DownloadItem downloadItem, Context ctx, OsmandRegions osmandRegions, boolean includingParent) {
if (this == VOICE_FILE) {
String fileName = downloadItem.getFileName();
@ -386,7 +389,7 @@ public class DownloadActivityType {
return osmandRegions.getLocaleName(basename, includingParent);
}
public String getTargetFileName(IndexItem item) {
String fileName = item.fileName;
// if(fileName.endsWith(IndexConstants.VOICE_INDEX_EXT_ZIP) ||
@ -426,7 +429,7 @@ public class DownloadActivityType {
}
String baseNameWithoutVersion = fileName.substring(0, l);
if (this == SRTM_COUNTRY_FILE) {
return baseNameWithoutVersion + IndexConstants.BINARY_SRTM_MAP_INDEX_EXT;
return baseNameWithoutVersion + SrtmDownloadItem.getExtension(item);
}
if (this == WIKIPEDIA_FILE) {
return baseNameWithoutVersion + IndexConstants.BINARY_WIKI_MAP_INDEX_EXT;
@ -490,7 +493,7 @@ public class DownloadActivityType {
return fileName.substring(0, l);
}
if (this == LIVE_UPDATES_FILE) {
if(fileName.indexOf('.') > 0){
if (fileName.indexOf('.') > 0) {
return fileName.substring(0, fileName.indexOf('.'));
}
return fileName;
@ -498,10 +501,10 @@ public class DownloadActivityType {
int ls = fileName.lastIndexOf('_');
if (ls >= 0) {
return fileName.substring(0, ls);
} else if(fileName.indexOf('.') > 0){
} else if (fileName.indexOf('.') > 0) {
return fileName.substring(0, fileName.indexOf('.'));
}
return fileName;
}
}
}

View file

@ -240,9 +240,12 @@ public class DownloadIndexesThread {
}
public void cancelDownload(DownloadItem item) {
if (item instanceof MultipleIndexItem) {
MultipleIndexItem multipleIndexItem = (MultipleIndexItem) item;
cancelDownload(multipleIndexItem.getAllIndexes());
if (item instanceof MultipleDownloadItem) {
MultipleDownloadItem multipleDownloadItem = (MultipleDownloadItem) item;
cancelDownload(multipleDownloadItem.getAllIndexes());
} else if (item instanceof SrtmDownloadItem) {
IndexItem indexItem = ((SrtmDownloadItem) item).getIndexItem();
cancelDownload(indexItem);
} else if (item instanceof IndexItem) {
IndexItem indexItem = (IndexItem) item;
cancelDownload(indexItem);

View file

@ -3,12 +3,14 @@ package net.osmand.plus.download;
import android.content.Context;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import net.osmand.map.OsmandRegions;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import java.io.File;
import java.text.DateFormat;
import java.util.List;
import java.util.Locale;
@ -55,6 +57,12 @@ public abstract class DownloadItem {
return type.getBasename(this);
}
@NonNull
public abstract List<File> getDownloadedFiles(@NonNull OsmandApplication app);
@Nullable
public abstract String getAdditionalDescription(Context ctx);
protected abstract double getSizeToDownloadInMb();
public abstract double getArchiveSizeMB();
@ -69,8 +77,7 @@ public abstract class DownloadItem {
public abstract String getFileName();
@NonNull
public abstract List<File> getDownloadedFiles(@NonNull OsmandApplication app);
public abstract String getDate(@NonNull DateFormat dateFormat, boolean remote);
@NonNull
public static String getFormattedMb(@NonNull Context ctx, double sizeInMb) {

View file

@ -1,5 +1,26 @@
package net.osmand.plus.download;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.AssetManager;
import android.provider.Settings.Secure;
import net.osmand.AndroidUtils;
import net.osmand.IndexConstants;
import net.osmand.PlatformUtil;
import net.osmand.osm.io.NetworkUtils;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.util.Algorithms;
import org.apache.commons.logging.Log;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
@ -11,29 +32,9 @@ import java.util.Comparator;
import java.util.List;
import java.util.zip.GZIPInputStream;
import net.osmand.AndroidUtils;
import net.osmand.IndexConstants;
import net.osmand.PlatformUtil;
import net.osmand.osm.io.NetworkUtils;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.settings.backend.OsmandSettings;
import org.apache.commons.logging.Log;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.AssetManager;
import android.provider.Settings.Secure;
public class DownloadOsmandIndexesHelper {
private final static Log log = PlatformUtil.getLog(DownloadOsmandIndexesHelper.class);
public static class IndexFileList implements Serializable {
private static final long serialVersionUID = 1L;
@ -41,29 +42,29 @@ public class DownloadOsmandIndexesHelper {
IndexItem basemap;
ArrayList<IndexItem> indexFiles = new ArrayList<IndexItem>();
private String mapversion;
private Comparator<IndexItem> comparator = new Comparator<IndexItem>(){
private Comparator<IndexItem> comparator = new Comparator<IndexItem>() {
@Override
public int compare(IndexItem o1, IndexItem o2) {
String object1 = o1.getFileName();
String object2 = o2.getFileName();
if(object1.endsWith(IndexConstants.ANYVOICE_INDEX_EXT_ZIP)){
if(object2.endsWith(IndexConstants.ANYVOICE_INDEX_EXT_ZIP)){
if (object1.endsWith(IndexConstants.ANYVOICE_INDEX_EXT_ZIP)) {
if (object2.endsWith(IndexConstants.ANYVOICE_INDEX_EXT_ZIP)) {
return object1.compareTo(object2);
} else {
return -1;
}
} else if(object2.endsWith(IndexConstants.ANYVOICE_INDEX_EXT_ZIP)){
} else if (object2.endsWith(IndexConstants.ANYVOICE_INDEX_EXT_ZIP)) {
return 1;
}
return object1.compareTo(object2);
}
};
public void setDownloadedFromInternet(boolean downloadedFromInternet) {
this.downloadedFromInternet = downloadedFromInternet;
}
public boolean isDownloadedFromInternet() {
return downloadedFromInternet;
}
@ -75,12 +76,12 @@ public class DownloadOsmandIndexesHelper {
@SuppressLint("DefaultLocale")
public void add(IndexItem indexItem) {
indexFiles.add(indexItem);
if(indexItem.getFileName().toLowerCase().startsWith("world_basemap")) {
if (indexItem.getFileName().toLowerCase().startsWith("world_basemap")) {
basemap = indexItem;
}
}
public void sort(){
public void sort() {
Collections.sort(indexFiles, comparator);
}
@ -91,7 +92,7 @@ public class DownloadOsmandIndexesHelper {
public List<IndexItem> getIndexFiles() {
return indexFiles;
}
public IndexItem getBasemap() {
return basemap;
}
@ -106,7 +107,7 @@ public class DownloadOsmandIndexesHelper {
return false;
}
}
}
public static IndexFileList getIndexesList(OsmandApplication app) {
PackageManager pm = app.getPackageManager();
@ -141,16 +142,16 @@ public class DownloadOsmandIndexesHelper {
}
private static void listVoiceAssets(IndexFileList result, AssetManager amanager, PackageManager pm,
OsmandSettings settings) {
OsmandSettings settings) {
try {
File voicePath = settings.getContext().getAppPath(IndexConstants.VOICE_INDEX_DIR);
File voicePath = settings.getContext().getAppPath(IndexConstants.VOICE_INDEX_DIR);
// list = amanager.list("voice");
String date = "";
long dateModified = System.currentTimeMillis();
try {
OsmandApplication app = settings.getContext();
ApplicationInfo appInfo = pm.getApplicationInfo(app.getPackageName(), 0);
dateModified = new File(appInfo.sourceDir).lastModified();
dateModified = new File(appInfo.sourceDir).lastModified();
date = AndroidUtils.formatDate((Context) settings.getContext(), dateModified);
} catch (NameNotFoundException e) {
log.error(e);
@ -177,17 +178,17 @@ public class DownloadOsmandIndexesHelper {
log.error("Error while loading tts files from assets", e); //$NON-NLS-1$
}
}
private static IndexFileList downloadIndexesListFromInternet(OsmandApplication ctx){
private static IndexFileList downloadIndexesListFromInternet(OsmandApplication ctx) {
try {
IndexFileList result = new IndexFileList();
log.debug("Start loading list of index files"); //$NON-NLS-1$
try {
String strUrl = ctx.getAppCustomization().getIndexesUrl();
long nd = ctx.getAppInitializer().getFirstInstalledDays();
if(nd > 0) {
strUrl += "&nd=" + nd;
if (nd > 0) {
strUrl += "&nd=" + nd;
}
strUrl += "&ns=" + ctx.getAppInitializer().getNumberOfStarts();
try {
@ -202,12 +203,12 @@ public class DownloadOsmandIndexesHelper {
GZIPInputStream gzin = new GZIPInputStream(in);
parser.setInput(gzin, "UTF-8"); //$NON-NLS-1$
int next;
while((next = parser.next()) != XmlPullParser.END_DOCUMENT) {
while ((next = parser.next()) != XmlPullParser.END_DOCUMENT) {
if (next == XmlPullParser.START_TAG) {
DownloadActivityType tp = DownloadActivityType.getIndexType(parser.getAttributeValue(null, "type"));
if (tp != null) {
IndexItem it = tp.parseIndexItem(ctx, parser);
if(it != null) {
if (it != null) {
result.add(it);
}
} else if ("osmand_regions".equals(parser.getName())) {
@ -226,7 +227,7 @@ public class DownloadOsmandIndexesHelper {
log.error("Error while loading indexes from repository", e); //$NON-NLS-1$
return null;
}
if (result.isAcceptable()) {
return result;
} else {
@ -239,19 +240,19 @@ public class DownloadOsmandIndexesHelper {
}
public static class AssetIndexItem extends IndexItem {
private final String assetName;
private final String destFile;
private final long dateModified;
public AssetIndexItem(String fileName, String description, String date,
long dateModified, String size, long sizeL, String assetName, String destFile, DownloadActivityType type) {
long dateModified, String size, long sizeL, String assetName, String destFile, DownloadActivityType type) {
super(fileName, description, dateModified, size, sizeL, sizeL, type);
this.dateModified = dateModified;
this.assetName = assetName;
this.destFile = destFile;
}
public long getDateModified() {
return dateModified;
}
@ -261,7 +262,7 @@ public class DownloadOsmandIndexesHelper {
return new DownloadEntry(assetName, destFile, dateModified);
}
public String getDestFile(){
public String getDestFile() {
return destFile;
}
}

View file

@ -25,12 +25,11 @@ import java.io.InputStream;
import java.text.DateFormat;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static net.osmand.plus.download.DownloadResourceGroup.DownloadResourceGroupType.REGION_MAPS;
@ -117,6 +116,16 @@ public class DownloadResources extends DownloadResourceGroup {
return res;
}
@NonNull
public List<DownloadItem> getDownloadItems(WorldRegion region) {
DownloadResourceGroup group = getRegionMapsGroup(region);
if (group != null) {
return group.getIndividualDownloadItems();
}
return Collections.emptyList();
}
@NonNull
public List<IndexItem> getIndexItems(WorldRegion region) {
if (groupByRegion != null) {
List<IndexItem> res = groupByRegion.get(region);
@ -124,7 +133,7 @@ public class DownloadResources extends DownloadResourceGroup {
return res;
}
}
return new LinkedList<>();
return Collections.emptyList();
}
public void updateLoadedFiles() {
@ -471,30 +480,60 @@ public class DownloadResources extends DownloadResourceGroup {
addGroup(otherGroup);
createHillshadeSRTMGroups();
collectMultipleIndexesItems();
replaceIndividualSrtmWithGroups(region);
createMultipleDownloadItems(region);
trimEmptyGroups();
updateLoadedFiles();
return true;
}
private void collectMultipleIndexesItems() {
collectMultipleIndexesItems(region);
private void replaceIndividualSrtmWithGroups(@NonNull WorldRegion region) {
DownloadResourceGroup group = getRegionMapsGroup(region);
if (group != null) {
boolean useMetersByDefault = SrtmDownloadItem.shouldUseMetersByDefault(app);
boolean listModified = false;
DownloadActivityType srtmType = DownloadActivityType.SRTM_COUNTRY_FILE;
List<DownloadItem> individualItems = group.getIndividualDownloadItems();
if (isListContainsType(individualItems, srtmType)) {
List<IndexItem> srtmIndexes = new ArrayList<>();
for (DownloadItem item : individualItems) {
if (item.getType() == srtmType && item instanceof IndexItem) {
srtmIndexes.add((IndexItem) item);
}
}
if (srtmIndexes.size() > 1) {
individualItems.removeAll(srtmIndexes);
group.addItem(new SrtmDownloadItem(srtmIndexes, useMetersByDefault));
}
listModified = true;
}
if (listModified) {
sortDownloadItems(individualItems);
}
}
List<WorldRegion> subRegions = region.getSubregions();
if (!Algorithms.isEmpty(subRegions)) {
for (WorldRegion subRegion : subRegions) {
replaceIndividualSrtmWithGroups(subRegion);
}
}
}
private void collectMultipleIndexesItems(@NonNull WorldRegion region) {
private void createMultipleDownloadItems(@NonNull WorldRegion region) {
List<WorldRegion> subRegions = region.getSubregions();
if (Algorithms.isEmpty(subRegions)) return;
DownloadResourceGroup group = getRegionMapsGroup(region);
if (group != null) {
boolean listModified = false;
List<IndexItem> indexesList = group.getIndividualResources();
List<WorldRegion> regionsToCollect = removeDuplicateRegions(subRegions);
List<DownloadItem> downloadItems = group.getIndividualDownloadItems();
List<WorldRegion> uniqueSubRegions = WorldRegion.removeDuplicates(subRegions);
for (DownloadActivityType type : DownloadActivityType.values()) {
if (!doesListContainIndexWithType(indexesList, type)) {
List<IndexItem> indexesFromSubRegions = collectIndexesOfType(regionsToCollect, type);
if (indexesFromSubRegions != null) {
group.addItem(new MultipleIndexItem(region, indexesFromSubRegions, type));
if (!isListContainsType(downloadItems, type)) {
List<DownloadItem> itemsFromSubRegions = collectItemsOfType(uniqueSubRegions, type);
if (itemsFromSubRegions != null) {
group.addItem(new MultipleDownloadItem(region, itemsFromSubRegions, type));
listModified = true;
}
}
@ -504,7 +543,7 @@ public class DownloadResources extends DownloadResourceGroup {
}
}
for (WorldRegion subRegion : subRegions) {
collectMultipleIndexesItems(subRegion);
createMultipleDownloadItems(subRegion);
}
}
@ -517,43 +556,21 @@ public class DownloadResources extends DownloadResourceGroup {
}
@Nullable
private List<IndexItem> collectIndexesOfType(@NonNull List<WorldRegion> regions,
@NonNull DownloadActivityType type) {
List<IndexItem> collectedIndexes = new ArrayList<>();
private List<DownloadItem> collectItemsOfType(@NonNull List<WorldRegion> regions,
@NonNull DownloadActivityType type) {
List<DownloadItem> collectedItems = new ArrayList<>();
for (WorldRegion region : regions) {
List<IndexItem> regionIndexes = getIndexItems(region);
boolean found = false;
if (regionIndexes != null) {
for (IndexItem index : regionIndexes) {
if (index.getType() == type) {
found = true;
collectedIndexes.add(index);
break;
}
for (DownloadItem item : getDownloadItems(region)) {
if (item.getType() == type) {
found = true;
collectedItems.add(item);
break;
}
}
if (!found) return null;
}
return collectedIndexes;
}
private List<WorldRegion> removeDuplicateRegions(List<WorldRegion> regions) {
Set<WorldRegion> duplicates = new HashSet<>();
for (int i = 0; i < regions.size() - 1; i++) {
WorldRegion r1 = regions.get(i);
for (int j = i + 1; j < regions.size(); j++) {
WorldRegion r2 = regions.get(j);
if (r1.containsRegion(r2)) {
duplicates.add(r2);
} else if (r2.containsRegion(r1)) {
duplicates.add(r1);
}
}
}
for (WorldRegion region : duplicates) {
regions.remove(region);
}
return regions;
return collectedItems;
}
private void buildRegionsGroups(WorldRegion region, DownloadResourceGroup group) {
@ -680,11 +697,11 @@ public class DownloadResources extends DownloadResourceGroup {
&& isIndexItemDownloaded(downloadThread, type, downloadRegion.getSuperregion(), res);
}
private boolean doesListContainIndexWithType(List<IndexItem> indexItems,
DownloadActivityType type) {
if (indexItems != null) {
for (IndexItem indexItem : indexItems) {
if (indexItem.getType() == type) {
private boolean isListContainsType(List<DownloadItem> items,
DownloadActivityType type) {
if (items != null) {
for (DownloadItem item : items) {
if (item.getType() == type) {
return true;
}
}

View file

@ -1,6 +1,9 @@
package net.osmand.plus.download;
import android.content.Context;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import net.osmand.IndexConstants;
import net.osmand.PlatformUtil;
@ -19,6 +22,7 @@ import java.util.Date;
import java.util.List;
public class IndexItem extends DownloadItem implements Comparable<IndexItem> {
private static final Log log = PlatformUtil.getLog(IndexItem.class);
String description;
@ -225,6 +229,12 @@ public class IndexItem extends DownloadItem implements Comparable<IndexItem> {
public String getDate(java.text.DateFormat format) {
return format.format(new Date(timestamp));
}
@Nullable
@Override
public String getAdditionalDescription(Context ctx) {
return null;
}
public static class DownloadEntry {
public long dateModified;
@ -254,5 +264,4 @@ public class IndexItem extends DownloadItem implements Comparable<IndexItem> {
}
}
}

View file

@ -1,32 +1,47 @@
package net.osmand.plus.download;
import android.content.Context;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import net.osmand.map.WorldRegion;
import net.osmand.plus.OsmandApplication;
import java.io.File;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.List;
public class MultipleIndexItem extends DownloadItem {
public class MultipleDownloadItem extends DownloadItem {
private final List<IndexItem> items;
private final List<DownloadItem> items;
public MultipleIndexItem(@NonNull WorldRegion region,
@NonNull List<IndexItem> items,
@NonNull DownloadActivityType type) {
public MultipleDownloadItem(@NonNull WorldRegion region,
@NonNull List<DownloadItem> items,
@NonNull DownloadActivityType type) {
super(type);
this.items = items;
}
public List<IndexItem> getAllIndexes() {
List<IndexItem> indexes = new ArrayList<>();
for (DownloadItem item : items) {
IndexItem index = getIndexItem(item);
if (index != null) {
indexes.add(index);
}
}
return indexes;
}
public List<DownloadItem> getAllItems() {
return items;
}
@Override
public boolean isOutdated() {
for (IndexItem item : items) {
for (DownloadItem item : items) {
if (item.isOutdated()) {
return true;
}
@ -36,7 +51,7 @@ public class MultipleIndexItem extends DownloadItem {
@Override
public boolean isDownloaded() {
for (IndexItem item : items) {
for (DownloadItem item : items) {
if (item.isDownloaded()) {
return true;
}
@ -46,8 +61,8 @@ public class MultipleIndexItem extends DownloadItem {
@Override
public boolean isDownloading(@NonNull DownloadIndexesThread thread) {
for (IndexItem item : items) {
if (thread.isDownloading(item)) {
for (DownloadItem item : items) {
if (item.isDownloading(thread)) {
return true;
}
}
@ -78,31 +93,31 @@ public class MultipleIndexItem extends DownloadItem {
@Override
public List<File> getDownloadedFiles(@NonNull OsmandApplication app) {
List<File> result = new ArrayList<>();
for (IndexItem item : items) {
for (DownloadItem item : items) {
result.addAll(item.getDownloadedFiles(app));
}
return result;
}
public List<IndexItem> getIndexesToDownload() {
List<IndexItem> indexesToDownload = new ArrayList<>();
for (IndexItem item : items) {
public List<DownloadItem> getItemsToDownload() {
List<DownloadItem> itemsToDownload = new ArrayList<>();
for (DownloadItem item : getAllItems()) {
if (item.hasActualDataToDownload()) {
indexesToDownload.add(item);
itemsToDownload.add(item);
}
}
return indexesToDownload;
return itemsToDownload;
}
@Override
public boolean hasActualDataToDownload() {
return getIndexesToDownload().size() > 0;
return getItemsToDownload().size() > 0;
}
@Override
public double getSizeToDownloadInMb() {
double totalSizeMb = 0.0d;
for (IndexItem item : items) {
for (DownloadItem item : items) {
if (item.hasActualDataToDownload()) {
totalSizeMb += item.getSizeToDownloadInMb();
}
@ -113,10 +128,33 @@ public class MultipleIndexItem extends DownloadItem {
@Override
public double getArchiveSizeMB() {
double result = 0.0d;
for (IndexItem item : items) {
for (DownloadItem item : items) {
result += item.getArchiveSizeMB();
}
return result;
}
@Nullable
public static IndexItem getIndexItem(@NonNull DownloadItem obj) {
if (obj instanceof IndexItem) {
return (IndexItem) obj;
} else if (obj instanceof SrtmDownloadItem) {
return ((SrtmDownloadItem) obj).getIndexItem();
}
return null;
}
@Nullable
@Override
public String getAdditionalDescription(Context ctx) {
for (DownloadItem item : items) {
return item.getAdditionalDescription(ctx);
}
return null;
}
@Override
public String getDate(@NonNull DateFormat dateFormat, boolean remote) {
return "";
}
}

View file

@ -1,113 +0,0 @@
package net.osmand.plus.download;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import net.osmand.map.OsmandRegions;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.base.SelectMultipleItemsBottomSheet;
import net.osmand.plus.base.SelectMultipleItemsBottomSheet.OnApplySelectionListener;
import net.osmand.plus.base.SelectMultipleItemsBottomSheet.SelectableItem;
import net.osmand.plus.base.SelectMultipleItemsBottomSheet.SelectionUpdateListener;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.List;
public class MultipleIndexesUiHelper {
public static void showDialog(@NonNull MultipleIndexItem multipleIndexItem,
@NonNull AppCompatActivity activity,
@NonNull final OsmandApplication app,
@NonNull DateFormat dateFormat,
boolean showRemoteDate,
@NonNull final SelectItemsToDownloadListener listener) {
List<IndexItem> indexesToDownload = getIndexesToDownload(multipleIndexItem);
List<SelectableItem> allItems = new ArrayList<>();
List<SelectableItem> selectedItems = new ArrayList<>();
OsmandRegions osmandRegions = app.getRegions();
for (IndexItem indexItem : multipleIndexItem.getAllIndexes()) {
SelectableItem selectableItem = new SelectableItem();
selectableItem.setTitle(indexItem.getVisibleName(app, osmandRegions, false));
String size = indexItem.getSizeDescription(app);
String date = indexItem.getDate(dateFormat, showRemoteDate);
String description = app.getString(R.string.ltr_or_rtl_combine_via_bold_point, size, date);
selectableItem.setDescription(description);
selectableItem.setIconId(indexItem.getType().getIconResource());
selectableItem.setObject(indexItem);
allItems.add(selectableItem);
if (indexesToDownload.contains(indexItem)) {
selectedItems.add(selectableItem);
}
}
final SelectMultipleItemsBottomSheet dialog =
SelectMultipleItemsBottomSheet.showInstance(activity, allItems, selectedItems, true);
dialog.setSelectionUpdateListener(new SelectionUpdateListener() {
@Override
public void onSelectionUpdate() {
dialog.setTitle(app.getString(R.string.welmode_download_maps));
String total = app.getString(R.string.shared_string_total);
double sizeToDownload = getDownloadSizeInMb(dialog.getSelectedItems());
String size = DownloadItem.getFormattedMb(app, sizeToDownload);
String description =
app.getString(R.string.ltr_or_rtl_combine_via_colon, total, size);
dialog.setDescription(description);
String btnTitle = app.getString(R.string.shared_string_download);
if (sizeToDownload > 0) {
btnTitle = app.getString(R.string.ltr_or_rtl_combine_via_dash, btnTitle, size);
}
dialog.setConfirmButtonTitle(btnTitle);
}
});
dialog.setOnApplySelectionListener(new OnApplySelectionListener() {
@Override
public void onSelectionApplied(List<SelectableItem> selectedItems) {
List<IndexItem> indexItems = new ArrayList<>();
for (SelectableItem item : selectedItems) {
Object obj = item.getObject();
if (obj instanceof IndexItem) {
indexItems.add((IndexItem) obj);
}
}
listener.onItemsToDownloadSelected(indexItems);
}
});
}
private static List<IndexItem> getIndexesToDownload(MultipleIndexItem multipleIndexItem) {
if (multipleIndexItem.hasActualDataToDownload()) {
// download left regions
return multipleIndexItem.getIndexesToDownload();
} else {
// download all regions again
return multipleIndexItem.getAllIndexes();
}
}
private static double getDownloadSizeInMb(@NonNull List<SelectableItem> selectableItems) {
List<IndexItem> indexItems = new ArrayList<>();
for (SelectableItem i : selectableItems) {
Object obj = i.getObject();
if (obj instanceof IndexItem) {
indexItems.add((IndexItem) obj);
}
}
double totalSizeMb = 0.0d;
for (IndexItem item : indexItems) {
totalSizeMb += item.getSizeToDownloadInMb();
}
return totalSizeMb;
}
public interface SelectItemsToDownloadListener {
void onItemsToDownloadSelected(List<IndexItem> items);
}
}

View file

@ -0,0 +1,280 @@
package net.osmand.plus.download;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.base.MultipleSelectionBottomSheet;
import net.osmand.plus.base.MultipleSelectionBottomSheet.SelectionUpdateListener;
import net.osmand.plus.base.ModeSelectionBottomSheet;
import net.osmand.plus.base.MultipleSelectionWithModeBottomSheet;
import net.osmand.plus.base.SelectionBottomSheet;
import net.osmand.plus.base.SelectionBottomSheet.OnApplySelectionListener;
import net.osmand.plus.base.SelectionBottomSheet.OnUiInitializedAdapter;
import net.osmand.plus.base.SelectionBottomSheet.SelectableItem;
import net.osmand.plus.widgets.MultiStateToggleButton.OnRadioItemClickListener;
import net.osmand.plus.widgets.MultiStateToggleButton.RadioItem;
import net.osmand.util.Algorithms;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.List;
import static net.osmand.plus.download.MultipleDownloadItem.getIndexItem;
public class SelectIndexesUiHelper {
private final OsmandApplication app;
private final AppCompatActivity activity;
private final ItemsToDownloadSelectedListener listener;
private final DateFormat dateFormat;
private final boolean showRemoteDate;
private final DownloadItem downloadItem;
private SelectionBottomSheet dialog;
private SelectIndexesUiHelper(@NonNull DownloadItem downloadItem,
@NonNull AppCompatActivity activity,
@NonNull DateFormat dateFormat,
boolean showRemoteDate,
@NonNull ItemsToDownloadSelectedListener listener) {
this.app = (OsmandApplication) activity.getApplicationContext();
this.activity = activity;
this.downloadItem = downloadItem;
this.dateFormat = dateFormat;
this.showRemoteDate = showRemoteDate;
this.listener = listener;
}
public static void showDialog(@NonNull DownloadItem i,
@NonNull AppCompatActivity a,
@NonNull DateFormat df,
boolean showRemoteDate,
@NonNull ItemsToDownloadSelectedListener l) {
new SelectIndexesUiHelper(i, a, df, showRemoteDate, l).showDialogInternal();
}
private void showDialogInternal() {
if (downloadItem.getType() == DownloadActivityType.SRTM_COUNTRY_FILE) {
if (downloadItem instanceof MultipleDownloadItem) {
showSrtmMultipleSelectionDialog();
} else {
showSrtmModeSelectionDialog();
}
} else if (downloadItem instanceof MultipleDownloadItem) {
showMultipleSelectionDialog();
}
}
private void showMultipleSelectionDialog() {
List<SelectableItem> allItems = new ArrayList<>();
List<SelectableItem> selectedItems = new ArrayList<>();
prepareItems(allItems, selectedItems);
MultipleSelectionBottomSheet msDialog = MultipleSelectionBottomSheet.showInstance(
activity, allItems, selectedItems, true);
this.dialog = msDialog;
msDialog.setOnUiInitializedAdapter(new OnUiInitializedAdapter() {
@Override
public void onUiInitialized() {
dialog.setTitle(app.getString(R.string.welmode_download_maps));
}
});
msDialog.setSelectionUpdateListener(new SelectionUpdateListener() {
@Override
public void onSelectionUpdate() {
updateSize();
}
});
msDialog.setOnApplySelectionListener(getOnApplySelectionListener(listener));
}
private void showSrtmMultipleSelectionDialog() {
List<SelectableItem> allItems = new ArrayList<>();
List<SelectableItem> selectedItems = new ArrayList<>();
prepareItems(allItems, selectedItems);
SrtmDownloadItem srtmItem = (SrtmDownloadItem) ((MultipleDownloadItem)downloadItem).getAllItems().get(0);
final int selectedModeOrder = srtmItem.isUseMetric() ? 0 : 1;
final List<RadioItem> radioItems = createSrtmRadioItems();
MultipleSelectionBottomSheet msDialog = MultipleSelectionWithModeBottomSheet.showInstance(
activity, allItems, selectedItems, radioItems, true);
this.dialog = msDialog;
msDialog.setOnUiInitializedAdapter(new OnUiInitializedAdapter() {
@Override
public void onUiInitialized() {
dialog.setTitle(app.getString(R.string.welmode_download_maps));
dialog.setSelectedMode(radioItems.get(selectedModeOrder));
dialog.setSecondaryDescription(app.getString(R.string.srtm_download_list_help_message));
}
});
msDialog.setSelectionUpdateListener(new SelectionUpdateListener() {
@Override
public void onSelectionUpdate() {
updateSize();
}
});
msDialog.setOnApplySelectionListener(getOnApplySelectionListener(listener));
}
private void showSrtmModeSelectionDialog() {
SrtmDownloadItem srtmItem = (SrtmDownloadItem) downloadItem;
final int selectedModeOrder = srtmItem.isUseMetric() ? 0 : 1;
final List<RadioItem> radioItems = createSrtmRadioItems();
SelectableItem preview = createSelectableItem(srtmItem);
dialog = ModeSelectionBottomSheet.showInstance(activity, preview, radioItems, true);
dialog.setOnUiInitializedAdapter(new OnUiInitializedAdapter() {
@Override
public void onUiInitialized() {
ModeSelectionBottomSheet dialog = (ModeSelectionBottomSheet) SelectIndexesUiHelper.this.dialog;
dialog.setTitle(app.getString(R.string.srtm_unit_format));
dialog.setPrimaryDescription(app.getString(R.string.srtm_download_single_help_message));
updateSize();
dialog.setSelectedMode(radioItems.get(selectedModeOrder));
}
});
dialog.setOnApplySelectionListener(getOnApplySelectionListener(listener));
}
private void prepareItems(List<SelectableItem> allItems,
List<SelectableItem> selectedItems) {
final MultipleDownloadItem multipleDownloadItem = (MultipleDownloadItem) downloadItem;
final List<DownloadItem> itemsToDownload = getItemsToDownload(multipleDownloadItem);
for (DownloadItem downloadItem : multipleDownloadItem.getAllItems()) {
SelectableItem selectableItem = createSelectableItem(downloadItem);
allItems.add(selectableItem);
if (itemsToDownload.contains(downloadItem)) {
selectedItems.add(selectableItem);
}
}
}
private List<RadioItem> createSrtmRadioItems() {
List<RadioItem> radioItems = new ArrayList<>();
radioItems.add(createSrtmRadioBtn(R.string.shared_string_meters, true));
radioItems.add(createSrtmRadioBtn(R.string.shared_string_feet, false));
return radioItems;
}
private RadioItem createSrtmRadioBtn(int titleId,
final boolean useMeters) {
String title = Algorithms.capitalizeFirstLetter(app.getString(titleId));
RadioItem radioItem = new RadioItem(title);
radioItem.setOnClickListener(new OnRadioItemClickListener() {
@Override
public boolean onRadioItemClick(RadioItem radioItem, View view) {
updateDialogListItems(useMeters);
updateSize();
return true;
}
});
return radioItem;
}
private void updateDialogListItems(boolean useMeters) {
List<SelectableItem> items = new ArrayList<>(dialog.getAllItems());
for (SelectableItem item : items) {
DownloadItem downloadItem = (DownloadItem) item.getObject();
if (downloadItem instanceof SrtmDownloadItem) {
((SrtmDownloadItem) downloadItem).setUseMetric(useMeters);
updateSelectableItem(item, downloadItem);
}
}
dialog.setItems(items);
}
private SelectableItem createSelectableItem(DownloadItem item) {
SelectableItem selectableItem = new SelectableItem();
updateSelectableItem(selectableItem, item);
return selectableItem;
}
private void updateSelectableItem(SelectableItem selectableItem,
DownloadItem downloadItem) {
selectableItem.setTitle(downloadItem.getVisibleName(app, app.getRegions(), false));
String size = downloadItem.getSizeDescription(app);
String addDescr = downloadItem.getAdditionalDescription(app);
if (addDescr != null) {
size += " " + addDescr;
}
String date = downloadItem.getDate(dateFormat, showRemoteDate);
String description = app.getString(R.string.ltr_or_rtl_combine_via_bold_point, size, date);
selectableItem.setDescription(description);
selectableItem.setIconId(downloadItem.getType().getIconResource());
selectableItem.setObject(downloadItem);
}
private OnApplySelectionListener getOnApplySelectionListener(final ItemsToDownloadSelectedListener listener) {
return new OnApplySelectionListener() {
@Override
public void onSelectionApplied(List<SelectableItem> selectedItems) {
List<IndexItem> indexes = new ArrayList<>();
for (SelectableItem item : selectedItems) {
IndexItem index = getIndexItem((DownloadItem) item.getObject());
if (index != null) {
indexes.add(index);
}
}
listener.onItemsToDownloadSelected(indexes);
}
};
}
private void updateSize() {
double sizeToDownload = getDownloadSizeInMb(dialog.getSelectedItems());
String size = DownloadItem.getFormattedMb(app, sizeToDownload);
String total = app.getString(R.string.shared_string_total);
String description = app.getString(R.string.ltr_or_rtl_combine_via_colon, total, size);
dialog.setTitleDescription(description);
String btnTitle = app.getString(R.string.shared_string_download);
if (sizeToDownload > 0) {
btnTitle = app.getString(R.string.ltr_or_rtl_combine_via_dash, btnTitle, size);
}
dialog.setApplyButtonTitle(btnTitle);
}
private double getDownloadSizeInMb(@NonNull List<SelectableItem> selectableItems) {
double totalSizeMb = 0.0d;
for (SelectableItem i : selectableItems) {
Object obj = i.getObject();
if (obj instanceof DownloadItem) {
totalSizeMb += ((DownloadItem) obj).getSizeToDownloadInMb();
}
}
return totalSizeMb;
}
private static List<DownloadItem> getItemsToDownload(MultipleDownloadItem md) {
if (md.hasActualDataToDownload()) {
// download left regions
return md.getItemsToDownload();
} else {
// download all regions again
return md.getAllItems();
}
}
public interface ItemsToDownloadSelectedListener {
void onItemsToDownloadSelected(List<IndexItem> items);
}
}

View file

@ -0,0 +1,191 @@
package net.osmand.plus.download;
import android.content.Context;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import net.osmand.IndexConstants;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.activities.LocalIndexInfo;
import net.osmand.plus.helpers.enums.MetricsConstants;
import net.osmand.util.Algorithms;
import java.io.File;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.List;
import static net.osmand.IndexConstants.BINARY_SRTM_MAP_INDEX_EXT;
import static net.osmand.IndexConstants.BINARY_SRTM_MAP_INDEX_EXT_ZIP;
import static net.osmand.plus.activities.LocalIndexHelper.LocalIndexType.SRTM_DATA;
import static net.osmand.plus.download.DownloadActivityType.SRTM_COUNTRY_FILE;
public class SrtmDownloadItem extends DownloadItem {
private final List<IndexItem> indexes;
private boolean useMetric;
public SrtmDownloadItem(List<IndexItem> indexes, boolean useMetric) {
super(SRTM_COUNTRY_FILE);
this.indexes = indexes;
this.useMetric = useMetric;
}
public void setUseMetric(boolean useMetric) {
this.useMetric = useMetric;
}
public boolean isUseMetric() {
for (IndexItem index : indexes) {
if (index.isDownloaded()) {
return isMetricItem(index);
}
}
return useMetric;
}
@NonNull
public IndexItem getIndexItem() {
for (IndexItem index : indexes) {
if (index.isDownloaded()) {
return index;
}
}
for (IndexItem index : indexes) {
if (useMetric && isMetricItem(index) || !useMetric && !isMetricItem(index)) {
return index;
}
}
return indexes.get(0);
}
@Override
protected double getSizeToDownloadInMb() {
return getIndexItem().getSizeToDownloadInMb();
}
@Override
public double getArchiveSizeMB() {
return getIndexItem().getArchiveSizeMB();
}
@Override
public boolean isOutdated() {
for (DownloadItem item : indexes) {
if (item.isOutdated()) {
return true;
}
}
return false;
}
@Override
public boolean isDownloaded() {
for (DownloadItem item : indexes) {
if (item.isDownloaded()) {
return true;
}
}
return false;
}
@Override
public boolean hasActualDataToDownload() {
for (IndexItem item : indexes) {
if (!item.hasActualDataToDownload()) {
return false;
}
}
return true;
}
@Override
public boolean isDownloading(@NonNull DownloadIndexesThread thread) {
for (IndexItem item : indexes) {
if (thread.isDownloading(item)) {
return true;
}
}
return false;
}
@Override
public String getFileName() {
return getIndexItem().getFileName();
}
@NonNull
@Override
public List<File> getDownloadedFiles(@NonNull OsmandApplication app) {
List<File> result = new ArrayList<>();
for (IndexItem index : indexes) {
result.addAll(index.getDownloadedFiles(app));
}
return result;
}
public String getDate(@NonNull DateFormat dateFormat, boolean remote) {
return getIndexItem().getDate(dateFormat, remote);
}
@Override
public @Nullable String getAdditionalDescription(Context ctx) {
return getAbbreviationInScopes(ctx, this);
}
public static boolean shouldUseMetersByDefault(@NonNull OsmandApplication app) {
MetricsConstants metricSystem = app.getSettings().METRIC_SYSTEM.get();
return metricSystem != MetricsConstants.MILES_AND_FEET;
}
@NonNull
public static String getAbbreviationInScopes(Context ctx, Object obj) {
String abbreviation = ctx.getString(isMetricItem(obj) ? R.string.m : R.string.foot);
return "(" + abbreviation + ")";
}
public static boolean containsSrtmExtension(@NonNull String fileName) {
return fileName.contains(IndexConstants.BINARY_SRTM_MAP_INDEX_EXT)
|| fileName.contains(IndexConstants.BINARY_SRTM_FEET_MAP_INDEX_EXT);
}
public static boolean isSrtmFile(@NonNull String fileName) {
return fileName.endsWith(IndexConstants.BINARY_SRTM_MAP_INDEX_EXT)
|| fileName.endsWith(IndexConstants.BINARY_SRTM_FEET_MAP_INDEX_EXT);
}
@NonNull
public static String getExtension(IndexItem indexItem) {
return isMetricItem(indexItem) ?
IndexConstants.BINARY_SRTM_MAP_INDEX_EXT :
IndexConstants.BINARY_SRTM_FEET_MAP_INDEX_EXT;
}
public static boolean isSRTMItem(Object item) {
if (item instanceof DownloadItem) {
return ((DownloadItem) item).getType() == SRTM_COUNTRY_FILE;
} else if (item instanceof LocalIndexInfo) {
return ((LocalIndexInfo) item).getType() == SRTM_DATA;
}
return false;
}
private static boolean isMetricItem(Object item) {
if (item instanceof IndexItem) {
return ((IndexItem) item).getFileName().endsWith(BINARY_SRTM_MAP_INDEX_EXT_ZIP);
} else if (item instanceof LocalIndexInfo) {
return ((LocalIndexInfo) item).getFileName().endsWith(BINARY_SRTM_MAP_INDEX_EXT);
} else if (item instanceof SrtmDownloadItem) {
return isMetricItem(((SrtmDownloadItem) item).getIndexItem());
} else if (item instanceof MultipleDownloadItem) {
List<DownloadItem> items = ((MultipleDownloadItem) item).getAllItems();
if (!Algorithms.isEmpty(items)) {
return isMetricItem(items.get(0));
}
}
return false;
}
}

View file

@ -87,7 +87,7 @@ public class ActiveDownloadsDialogFragment extends DialogFragment implements Dow
}
ItemViewHolder viewHolder = (ItemViewHolder) convertView.getTag();
IndexItem item = getItem(position);
viewHolder.bindIndexItem(item);
viewHolder.bindDownloadItem(item);
return convertView;
}

View file

@ -78,7 +78,7 @@ public class DownloadResourceGroupAdapter extends OsmandBaseExpandableListAdapte
} else {
viewHolder.setShowTypeInDesc(true);
}
viewHolder.bindIndexItem(item);
viewHolder.bindDownloadItem(item);
} else {
DownloadResourceGroup group = (DownloadResourceGroup) child;
DownloadGroupViewHolder viewHolder;

View file

@ -41,9 +41,9 @@ import net.osmand.plus.download.DownloadActivityType;
import net.osmand.plus.download.DownloadResourceGroup;
import net.osmand.plus.download.DownloadResources;
import net.osmand.plus.download.IndexItem;
import net.osmand.plus.download.MultipleIndexesUiHelper;
import net.osmand.plus.download.MultipleIndexesUiHelper.SelectItemsToDownloadListener;
import net.osmand.plus.download.MultipleIndexItem;
import net.osmand.plus.download.SelectIndexesUiHelper;
import net.osmand.plus.download.SelectIndexesUiHelper.ItemsToDownloadSelectedListener;
import net.osmand.plus.download.MultipleDownloadItem;
import net.osmand.plus.download.ui.LocalIndexesFragment.LocalIndexOperationTask;
import net.osmand.plus.helpers.FileNameTranslationHelper;
import net.osmand.plus.inapp.InAppPurchaseHelper;
@ -146,11 +146,11 @@ public class ItemViewHolder {
depthContoursPurchased = InAppPurchaseHelper.isDepthContoursPurchased(context.getMyApplication());
}
public void bindIndexItem(final DownloadItem downloadItem) {
bindIndexItem(downloadItem, null);
public void bindDownloadItem(final DownloadItem downloadItem) {
bindDownloadItem(downloadItem, null);
}
public void bindIndexItem(final DownloadItem downloadItem, final String cityName) {
public void bindDownloadItem(final DownloadItem downloadItem, final String cityName) {
initAppStatusVariables();
boolean isDownloading = downloadItem.isDownloading(context.getDownloadThread());
int progress = -1;
@ -160,20 +160,20 @@ public class ItemViewHolder {
boolean disabled = checkDisabledAndClickAction(downloadItem);
/// name and left item
String name;
if(showTypeInName) {
if (showTypeInName) {
name = downloadItem.getType().getString(context);
} else {
name = downloadItem.getVisibleName(context, context.getMyApplication().getRegions(), showParentRegionName);
}
String text = (!Algorithms.isEmpty(cityName) && !cityName.equals(name) ? cityName + "\n" : "") + name;
nameTextView.setText(text);
if(!disabled) {
if (!disabled) {
nameTextView.setTextColor(textColorPrimary);
} else {
nameTextView.setTextColor(textColorSecondary);
}
int color = textColorSecondary;
if(downloadItem.isDownloaded() && !isDownloading) {
if (downloadItem.isDownloaded() && !isDownloading) {
int colorId = downloadItem.isOutdated() ? R.color.color_distance : R.color.color_ok;
color = context.getResources().getColor(colorId);
}
@ -203,12 +203,12 @@ public class ItemViewHolder {
} else {
descrTextView.setText(downloadItem.getType().getString(context));
}
} else if (downloadItem instanceof MultipleIndexItem) {
MultipleIndexItem item = (MultipleIndexItem) downloadItem;
} else if (downloadItem instanceof MultipleDownloadItem) {
MultipleDownloadItem item = (MultipleDownloadItem) downloadItem;
String allRegionsHeader = context.getString(R.string.shared_strings_all_regions);
String regionsHeader = context.getString(R.string.regions);
String allRegionsCount = String.valueOf(item.getAllIndexes().size());
String leftToDownloadCount = String.valueOf(item.getIndexesToDownload().size());
String allRegionsCount = String.valueOf(item.getAllItems().size());
String leftToDownloadCount = String.valueOf(item.getItemsToDownload().size());
String header;
String count;
if (item.hasActualDataToDownload()) {
@ -226,8 +226,11 @@ public class ItemViewHolder {
header = allRegionsHeader;
count = allRegionsCount;
}
String fullDescription =
context.getString(R.string.ltr_or_rtl_combine_via_colon, header, count);
String fullDescription = context.getString(R.string.ltr_or_rtl_combine_via_colon, header, count);
String addDescr = item.getAdditionalDescription(context);
if (addDescr != null) {
fullDescription += " " + addDescr;
}
if (item.hasActualDataToDownload()) {
fullDescription = context.getString(
R.string.ltr_or_rtl_combine_via_bold_point, fullDescription,
@ -235,11 +238,14 @@ public class ItemViewHolder {
}
descrTextView.setText(fullDescription);
} else {
IndexItem item = (IndexItem) downloadItem;
String pattern = context.getString(R.string.ltr_or_rtl_combine_via_bold_point);
String type = item.getType().getString(context);
String size = item.getSizeDescription(context);
String date = item.getDate(dateFormat, showRemoteDate);
String type = downloadItem.getType().getString(context);
String size = downloadItem.getSizeDescription(context);
String addDescr = downloadItem.getAdditionalDescription(context);
if (addDescr != null) {
size += " " + addDescr;
}
String date = downloadItem.getDate(dateFormat, showRemoteDate);
String fullDescription = String.format(pattern, size, date);
if (showTypeInDesc) {
fullDescription = String.format(pattern, type, fullDescription);
@ -254,14 +260,14 @@ public class ItemViewHolder {
if (showProgressInDesc) {
double mb = downloadItem.getArchiveSizeMB();
String v ;
String v;
if (progress != -1) {
v = context.getString(R.string.value_downloaded_of_max, mb * progress / 100, mb);
} else {
v = context.getString(R.string.file_size_in_mb, mb);
}
String fullDescription = v;
if(showTypeInDesc && downloadItem.getType() == DownloadActivityType.ROADS_FILE) {
if (showTypeInDesc && downloadItem.getType() == DownloadActivityType.ROADS_FILE) {
fullDescription = context.getString(R.string.ltr_or_rtl_combine_via_bold_point,
downloadItem.getType().getString(context), fullDescription);
}
@ -274,9 +280,9 @@ public class ItemViewHolder {
}
}
public void bindIndexItem(final CityItem cityItem) {
public void bindDownloadItem(final CityItem cityItem) {
if (cityItem.getIndexItem() != null) {
bindIndexItem(cityItem.getIndexItem(), cityItem.getName());
bindDownloadItem(cityItem.getIndexItem(), cityItem.getName());
} else {
nameTextView.setText(cityItem.getName());
nameTextView.setTextColor(textColorPrimary);
@ -302,7 +308,7 @@ public class ItemViewHolder {
if (isDownloading) {
rightImageButton.setImageDrawable(getContentIcon(context, R.drawable.ic_action_remove_dark));
rightImageButton.setContentDescription(context.getString(R.string.shared_string_cancel));
} else if(!item.hasActualDataToDownload()) {
} else if (!item.hasActualDataToDownload()) {
rightImageButton.setImageDrawable(getContentIcon(context, R.drawable.ic_overflow_menu_white));
rightImageButton.setContentDescription(context.getString(R.string.shared_string_more));
} else {
@ -316,9 +322,9 @@ public class ItemViewHolder {
}
private int getDownloadActionIconId(@NonNull DownloadItem item) {
return item instanceof MultipleIndexItem ?
return item instanceof MultipleDownloadItem ?
R.drawable.ic_action_multi_download :
R.drawable.ic_action_import;
R.drawable.ic_action_gsave_dark;
}
@SuppressLint("DefaultLocale")
@ -389,13 +395,13 @@ public class ItemViewHolder {
return new View.OnClickListener() {
@Override
public void onClick(View v) {
if(isDownloading) {
if(silentCancelDownload) {
if (isDownloading) {
if (silentCancelDownload) {
context.getDownloadThread().cancelDownload(item);
} else {
context.makeSureUserCancelDownload(item);
}
} else if(!item.hasActualDataToDownload()){
} else if (!item.hasActualDataToDownload()) {
showContextMenu(v, item, item.getRelatedGroup());
} else {
download(item, item.getRelatedGroup());
@ -406,8 +412,8 @@ public class ItemViewHolder {
}
protected void showContextMenu(View v,
final DownloadItem downloadItem,
final DownloadResourceGroup parentOptional) {
final DownloadItem downloadItem,
final DownloadResourceGroup parentOptional) {
OsmandApplication app = context.getMyApplication();
PopupMenu optionsMenu = new PopupMenu(context, v);
MenuItem item;
@ -455,10 +461,11 @@ public class ItemViewHolder {
}
}
}
if(!handled) {
if (!handled) {
startDownload(item);
}
}
private void confirmDownload(final DownloadItem item) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(R.string.are_you_sure);
@ -476,18 +483,17 @@ public class ItemViewHolder {
}
private void startDownload(DownloadItem item) {
if (item instanceof MultipleIndexItem) {
selectIndexesToDownload((MultipleIndexItem) item);
} else if (item instanceof IndexItem) {
if (item instanceof IndexItem) {
IndexItem indexItem = (IndexItem) item;
context.startDownload(indexItem);
} else {
selectIndexesToDownload(item);
}
}
private void selectIndexesToDownload(MultipleIndexItem item) {
OsmandApplication app = context.getMyApplication();
MultipleIndexesUiHelper.showDialog(item, context, app, dateFormat, showRemoteDate,
new SelectItemsToDownloadListener() {
private void selectIndexesToDownload(DownloadItem item) {
SelectIndexesUiHelper.showDialog(item, context, dateFormat, showRemoteDate,
new ItemsToDownloadSelectedListener() {
@Override
public void onItemsToDownloadSelected(List<IndexItem> indexes) {
IndexItem[] indexesArray = new IndexItem[indexes.size()];
@ -498,7 +504,7 @@ public class ItemViewHolder {
}
private void confirmRemove(@NonNull final DownloadItem downloadItem,
@NonNull final List<File> downloadedFiles) {
@NonNull final List<File> downloadedFiles) {
OsmandApplication app = context.getMyApplication();
AlertDialog.Builder confirm = new AlertDialog.Builder(context);
@ -526,7 +532,7 @@ public class ItemViewHolder {
}
private void remove(@NonNull LocalIndexType type,
@NonNull List<File> filesToDelete) {
@NonNull List<File> filesToDelete) {
OsmandApplication app = context.getMyApplication();
LocalIndexOperationTask removeTask = new LocalIndexOperationTask(
context,

View file

@ -55,6 +55,7 @@ import net.osmand.plus.dialogs.DirectionsDialogs;
import net.osmand.plus.download.DownloadActivity;
import net.osmand.plus.download.DownloadIndexesThread.DownloadEvents;
import net.osmand.plus.download.IndexItem;
import net.osmand.plus.download.SrtmDownloadItem;
import net.osmand.plus.helpers.FileNameTranslationHelper;
import net.osmand.plus.inapp.InAppPurchaseHelper;
import net.osmand.plus.mapsource.EditMapSourceDialogFragment.OnMapSourceUpdateListener;
@ -74,6 +75,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
public class LocalIndexesFragment extends OsmandExpandableListFragment implements DownloadEvents,
OnMapSourceUpdateListener, RenameCallback {
private LoadLocalIndexTask asyncLoader;
@ -351,10 +353,10 @@ public class LocalIndexesFragment extends OsmandExpandableListFragment implement
getMyApplication().getResourceManager().closeFile(info.getFileName());
File tShm = new File(f.getParentFile(), f.getName() + "-shm");
File tWal = new File(f.getParentFile(), f.getName() + "-wal");
if(tShm.exists()) {
if (tShm.exists()) {
Algorithms.removeAllFiles(tShm);
}
if(tWal.exists()) {
if (tWal.exists()) {
Algorithms.removeAllFiles(tWal);
}
}
@ -370,8 +372,8 @@ public class LocalIndexesFragment extends OsmandExpandableListFragment implement
getMyApplication().getResourceManager().closeFile(info.getFileName());
}
} else if (operation == CLEAR_TILES_OPERATION) {
ITileSource src = (ITileSource) info.getAttachedObject();
if(src != null) {
ITileSource src = (ITileSource) info.getAttachedObject();
if (src != null) {
src.deleteTiles(info.getPathToData());
}
}
@ -419,10 +421,10 @@ public class LocalIndexesFragment extends OsmandExpandableListFragment implement
@Override
protected void onPostExecute(String result) {
a.setProgressBarIndeterminateVisibility(false);
if(result != null && result.length() > 0) {
if (result != null && result.length() > 0) {
Toast.makeText(a, result, Toast.LENGTH_LONG).show();
}
if (operation == RESTORE_OPERATION || operation == BACKUP_OPERATION || operation == CLEAR_TILES_OPERATION) {
a.reloadLocalIndexes();
} else {
@ -507,7 +509,7 @@ public class LocalIndexesFragment extends OsmandExpandableListFragment implement
ItemClickListener listener = new ContextMenuAdapter.ItemClickListener() {
@Override
public boolean onContextMenuClick(ArrayAdapter<ContextMenuItem> adapter,
int itemId, int pos, boolean isChecked, int[] viewCoordinates) {
int itemId, int pos, boolean isChecked, int[] viewCoordinates) {
localOptionsMenu(itemId);
return true;
}
@ -608,7 +610,7 @@ public class LocalIndexesFragment extends OsmandExpandableListFragment implement
}
private void openSelectionMode(final int actionResId, final int actionIconId,
final DialogInterface.OnClickListener listener) {
final DialogInterface.OnClickListener listener) {
final int colorResId = getMyApplication().getSettings().isLightContent() ? R.color.active_buttons_and_links_text_light : R.color.active_buttons_and_links_text_dark;
String value = getString(actionResId);
if (value.endsWith("...")) {
@ -709,7 +711,7 @@ public class LocalIndexesFragment extends OsmandExpandableListFragment implement
}
public void openSelectionMode(int stringRes, int darkIcon, DialogInterface.OnClickListener listener,
EnumSet<LocalIndexType> filter) {
EnumSet<LocalIndexType> filter) {
if (filter != null) {
listAdapter.filterCategories(filter);
}
@ -860,7 +862,7 @@ public class LocalIndexesFragment extends OsmandExpandableListFragment implement
@Override
public View getChildView(final int groupPosition, final int childPosition,
boolean isLastChild, View convertView, ViewGroup parent) {
boolean isLastChild, View convertView, ViewGroup parent) {
LocalIndexInfoViewHolder viewHolder;
if (convertView == null) {
LayoutInflater inflater = LayoutInflater.from(ctx);
@ -878,8 +880,8 @@ public class LocalIndexesFragment extends OsmandExpandableListFragment implement
private String getNameToDisplay(LocalIndexInfo child) {
return child.getType() == LocalIndexType.VOICE_DATA ? FileNameTranslationHelper.getVoiceName(ctx, child.getFileName()) :
FileNameTranslationHelper.getFileName(ctx,
ctx.getMyApplication().getResourceManager().getOsmandRegions(),
child.getFileName());
ctx.getMyApplication().getResourceManager().getOsmandRegions(),
child.getFileName());
}
@Override
@ -963,7 +965,7 @@ public class LocalIndexesFragment extends OsmandExpandableListFragment implement
return ctx.getString(R.string.download_roads_only_item);
} else if (child.isBackupedData() && child.getFileName().endsWith(IndexConstants.BINARY_WIKI_MAP_INDEX_EXT)) {
return ctx.getString(R.string.download_wikipedia_maps);
} else if (child.isBackupedData() && child.getFileName().endsWith(IndexConstants.BINARY_SRTM_MAP_INDEX_EXT)) {
} else if (child.isBackupedData() && (SrtmDownloadItem.isSrtmFile(child.getFileName()))) {
return ctx.getString(R.string.download_srtm_maps);
}
return "";
@ -1029,6 +1031,10 @@ public class LocalIndexesFragment extends OsmandExpandableListFragment implement
builder.append(AndroidUtils.formatSize(ctx, child.getSize() * 1024l));
}
if (SrtmDownloadItem.isSRTMItem(child)) {
builder.append(" ").append(SrtmDownloadItem.getAbbreviationInScopes(ctx, child));
}
if (!Algorithms.isEmpty(child.getDescription())) {
if (builder.length() > 0) {
builder.append("");
@ -1150,5 +1156,4 @@ public class LocalIndexesFragment extends OsmandExpandableListFragment implement
private DownloadActivity getDownloadActivity() {
return (DownloadActivity) getActivity();
}
}

View file

@ -382,10 +382,10 @@ public class SearchDialogFragment extends DialogFragment implements DownloadEven
if (obj instanceof IndexItem) {
IndexItem item = (IndexItem) obj;
viewHolder.setShowTypeInDesc(true);
viewHolder.bindIndexItem(item);
viewHolder.bindDownloadItem(item);
} else {
CityItem item = (CityItem) obj;
viewHolder.bindIndexItem(item);
viewHolder.bindDownloadItem(item);
if (item.getIndexItem() == null) {
new IndexItemResolverTask(viewHolder, item).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
@ -461,7 +461,7 @@ public class SearchDialogFragment extends DialogFragment implements DownloadEven
if (viewHolder != null) {
if (indexItem != null) {
cityItem.setIndexItem(indexItem);
viewHolder.bindIndexItem(indexItem, cityItem.getName());
viewHolder.bindDownloadItem(indexItem, cityItem.getName());
}
}
}

View file

@ -410,7 +410,7 @@ public class UpdatesIndexFragment extends OsmAndListFragment implements Download
holder.setShowRemoteDate(true);
holder.setShowTypeInDesc(true);
holder.setShowParentRegionName(true);
holder.bindIndexItem(getItem(position));
holder.bindDownloadItem(getItem(position));
}
return view;
}

View file

@ -1,12 +1,11 @@
package net.osmand.plus.resources;
import android.view.LayoutInflater;
import net.osmand.IndexConstants;
import net.osmand.PlatformUtil;
import net.osmand.binary.BinaryMapIndexReader;
import net.osmand.osm.io.NetworkUtils;
import net.osmand.plus.R;
import net.osmand.plus.download.SrtmDownloadItem;
import net.osmand.util.Algorithms;
import org.apache.commons.logging.Log;
@ -33,12 +32,11 @@ public class IncrementalChangesManager {
private static final org.apache.commons.logging.Log log = PlatformUtil.getLog(IncrementalChangesManager.class);
private ResourceManager resourceManager;
private final Map<String, RegionUpdateFiles> regions = new ConcurrentHashMap<String, IncrementalChangesManager.RegionUpdateFiles>();
public IncrementalChangesManager(ResourceManager resourceManager) {
this.resourceManager = resourceManager;
}
public List<File> collectChangesFiles(File dir, String ext, List<File> files) {
if (dir.exists() && dir.canRead()) {
File[] lf = dir.listFiles();
@ -47,8 +45,8 @@ public class IncrementalChangesManager {
}
Set<String> existingFiles = new HashSet<String>();
for (File f : files) {
if(!f.getName().endsWith(IndexConstants.BINARY_WIKI_MAP_INDEX_EXT) &&
!f.getName().endsWith(IndexConstants.BINARY_SRTM_MAP_INDEX_EXT)) {
if (!f.getName().endsWith(IndexConstants.BINARY_WIKI_MAP_INDEX_EXT) &&
!SrtmDownloadItem.isSrtmFile(f.getName())) {
existingFiles.add(Algorithms.getFileNameWithoutExtension(f));
}
}
@ -71,7 +69,7 @@ public class IncrementalChangesManager {
public synchronized void indexMainMap(File f, long dateCreated) {
String nm = Algorithms.getFileNameWithoutExtension(f).toLowerCase();
RegionUpdateFiles regionUpdateFiles = regions.get(nm);
if(regionUpdateFiles == null) {
if (regionUpdateFiles == null) {
regionUpdateFiles = new RegionUpdateFiles(nm);
regions.put(nm, regionUpdateFiles);
}
@ -98,7 +96,7 @@ public class IncrementalChangesManager {
RegionUpdate monthRu = regionUpdateFiles.monthUpdates.get(month);
while (it.hasNext()) {
RegionUpdate ru = it.next();
if(ru == null) {
if (ru == null) {
continue;
}
if (ru.obfCreated <= dateCreated ||
@ -114,58 +112,58 @@ public class IncrementalChangesManager {
}
}
}
public synchronized boolean index(File f, long dateCreated, BinaryMapIndexReader mapReader) {
String index = Algorithms.getFileNameWithoutExtension(f).toLowerCase();
if(index.length() <= 9 || index.charAt(index.length() - 9) != '_'){
if (index.length() <= 9 || index.charAt(index.length() - 9) != '_') {
return false;
}
String nm = index.substring(0, index.length() - 9);
String date = index.substring(index.length() - 9 + 1);
RegionUpdateFiles regionUpdateFiles = regions.get(nm);
if(regionUpdateFiles == null) {
if (regionUpdateFiles == null) {
regionUpdateFiles = new RegionUpdateFiles(nm);
regions.put(nm, regionUpdateFiles);
}
return regionUpdateFiles.addUpdate(date, f, dateCreated);
}
protected static String formatSize(long vl) {
return (vl * 1000 / (1 << 20l)) / 1000.0f + "";
}
public static long calculateSize(List<IncrementalUpdate> list) {
long l = 0;
for(IncrementalUpdate iu : list) {
for (IncrementalUpdate iu : list) {
l += iu.containerSize;
}
return l;
}
}
protected class RegionUpdate {
protected File file;
protected String date;
protected long obfCreated;
protected long obfCreated;
}
protected class RegionUpdateFiles {
protected String nm;
protected File mainFile;
protected long mainFileInit;
TreeMap<String, List<RegionUpdate>> dayUpdates = new TreeMap<String, List<RegionUpdate>>();
TreeMap<String, RegionUpdate> monthUpdates = new TreeMap<String, RegionUpdate>();
public RegionUpdateFiles(String nm) {
this.nm = nm;
}
public boolean addUpdate(String date, File file, long dateCreated) {
String monthYear = date.substring(0, 5);
RegionUpdate ru = new RegionUpdate();
ru.date = date;
ru.file = file;
ru.obfCreated = dateCreated;
if(date.endsWith("00")) {
if (date.endsWith("00")) {
monthUpdates.put(monthYear, ru);
} else {
List<RegionUpdate> list = dayUpdates.get(monthYear);
@ -179,22 +177,21 @@ public class IncrementalChangesManager {
}
}
public class IncrementalUpdateList {
public TreeMap<String, IncrementalUpdateGroupByMonth> updateByMonth =
public TreeMap<String, IncrementalUpdateGroupByMonth> updateByMonth =
new TreeMap<String, IncrementalUpdateGroupByMonth>();
public String errorMessage;
public RegionUpdateFiles updateFiles;
public boolean isPreferrableLimitForDayUpdates(String monthYearPart, List<IncrementalUpdate> dayUpdates) {
List<RegionUpdate> lst = updateFiles.dayUpdates.get(monthYearPart);
if(lst == null || lst.size() < 10) {
if (lst == null || lst.size() < 10) {
return true;
}
return false;
}
public List<IncrementalUpdate> getItemsForUpdate() {
Iterator<IncrementalUpdateGroupByMonth> it = updateByMonth.values().iterator();
List<IncrementalUpdate> ll = new ArrayList<IncrementalUpdate>();
@ -208,7 +205,7 @@ public class IncrementalChangesManager {
} else {
// it causes problem when person doesn't restart application for 10 days so updates stop working
// && isPreferrableLimitForDayUpdates(n.monthYearPart, n.getDayUpdates())
if (n.isDayUpdateApplicable() ) {
if (n.isDayUpdateApplicable()) {
ll.addAll(n.getDayUpdates());
} else if (n.isMonthUpdateApplicable()) {
ll.addAll(n.getMonthUpdate());
@ -234,51 +231,51 @@ public class IncrementalChangesManager {
}
}
}
protected static class IncrementalUpdateGroupByMonth {
public final String monthYearPart ;
public final String monthYearPart;
public List<IncrementalUpdate> dayUpdates = new ArrayList<IncrementalUpdate>();
public IncrementalUpdate monthUpdate;
public long calculateSizeMonthUpdates() {
return calculateSize(getMonthUpdate());
}
public long calculateSizeDayUpdates() {
return calculateSize(getDayUpdates());
}
public boolean isMonthUpdateApplicable() {
return monthUpdate != null;
}
public boolean isDayUpdateApplicable() {
boolean inLimits = dayUpdates.size() > 0 && dayUpdates.size() < 4;
if(!inLimits) {
if (!inLimits) {
return false;
}
return true;
}
public List<IncrementalUpdate> getMonthUpdate() {
List<IncrementalUpdate> ll = new ArrayList<IncrementalUpdate>();
if(monthUpdate == null) {
if (monthUpdate == null) {
return ll;
}
ll.add(monthUpdate);
for(IncrementalUpdate iu : dayUpdates) {
if(iu.timestamp > monthUpdate.timestamp) {
for (IncrementalUpdate iu : dayUpdates) {
if (iu.timestamp > monthUpdate.timestamp) {
ll.add(iu);
}
}
return ll;
}
public List<IncrementalUpdate> getDayUpdates() {
return dayUpdates;
}
public IncrementalUpdateGroupByMonth(String monthYearPart ) {
public IncrementalUpdateGroupByMonth(String monthYearPart) {
this.monthYearPart = monthYearPart;
}
}
@ -300,7 +297,7 @@ public class IncrementalChangesManager {
return "Update " + fileName + " " + sizeText + " MB " + date + ", timestamp: " + timestamp;
}
}
private List<IncrementalUpdate> getIncrementalUpdates(String file, long timestamp) throws IOException,
XmlPullParserException {
String url = URL + "?aosmc=true&timestamp=" + timestamp + "&file=" + URLEncoder.encode(file);
@ -314,7 +311,7 @@ public class IncrementalChangesManager {
int elements = 0;
while (parser.next() != XmlPullParser.END_DOCUMENT) {
if (parser.getEventType() == XmlPullParser.START_TAG) {
elements ++;
elements++;
if (parser.getName().equals("update")) {
IncrementalUpdate dt = new IncrementalUpdate();
dt.date = parser.getAttributeValue("", "updateDate");
@ -332,21 +329,19 @@ public class IncrementalChangesManager {
conn.disconnect();
return lst;
}
public IncrementalUpdateList getUpdatesByMonth(String fileName) {
IncrementalUpdateList iul = new IncrementalUpdateList();
RegionUpdateFiles ruf = regions.get(fileName.toLowerCase());
iul.updateFiles = ruf;
if(ruf == null) {
if (ruf == null) {
iul.errorMessage = resourceManager.getContext().getString(R.string.no_updates_available);
return iul;
}
long timestamp = getTimestamp(ruf);
try {
List<IncrementalUpdate> lst = getIncrementalUpdates(fileName, timestamp);
for(IncrementalUpdate iu : lst) {
for (IncrementalUpdate iu : lst) {
iul.addUpdate(iu);
}
} catch (Exception e) {
@ -357,9 +352,9 @@ public class IncrementalChangesManager {
return iul;
}
public long getUpdatesSize(String fileName){
public long getUpdatesSize(String fileName) {
RegionUpdateFiles ruf = regions.get(fileName.toLowerCase());
if(ruf == null) {
if (ruf == null) {
return 0;
}
long size = 0;
@ -374,9 +369,9 @@ public class IncrementalChangesManager {
return size;
}
public void deleteUpdates(String fileName){
public void deleteUpdates(String fileName) {
RegionUpdateFiles ruf = regions.get(fileName.toLowerCase());
if(ruf == null) {
if (ruf == null) {
return;
}
for (List<RegionUpdate> regionUpdates : ruf.dayUpdates.values()) {
@ -399,7 +394,7 @@ public class IncrementalChangesManager {
public long getTimestamp(String fileName) {
RegionUpdateFiles ruf = regions.get(fileName.toLowerCase());
if(ruf == null) {
if (ruf == null) {
return System.currentTimeMillis();
}
return getTimestamp(ruf);
@ -407,7 +402,7 @@ public class IncrementalChangesManager {
public long getMapTimestamp(String fileName) {
RegionUpdateFiles ruf = regions.get(fileName.toLowerCase());
if(ruf == null) {
if (ruf == null) {
return System.currentTimeMillis();
}
return ruf.mainFileInit;

View file

@ -41,6 +41,7 @@ import net.osmand.plus.R;
import net.osmand.plus.Version;
import net.osmand.plus.download.DownloadOsmandIndexesHelper;
import net.osmand.plus.download.DownloadOsmandIndexesHelper.AssetEntry;
import net.osmand.plus.download.SrtmDownloadItem;
import net.osmand.plus.inapp.InAppPurchaseHelper;
import net.osmand.plus.render.MapRenderRepositories;
import net.osmand.plus.render.NativeOsmandLibrary;
@ -78,11 +79,11 @@ import java.util.concurrent.ConcurrentHashMap;
import static net.osmand.IndexConstants.VOICE_INDEX_DIR;
/**
* Resource manager is responsible to work with all resources
* Resource manager is responsible to work with all resources
* that could consume memory (especially with file resources).
* Such as indexes, tiles.
* Also it is responsible to create cache for that resources if they
* can't be loaded fully into memory & clear them on request.
* can't be loaded fully into memory & clear them on request.
*/
public class ResourceManager {
@ -91,10 +92,10 @@ public class ResourceManager {
public static final String DEFAULT_WIKIVOYAGE_TRAVEL_OBF = "Default_wikivoyage.travel.obf";
private static final Log log = PlatformUtil.getLog(ResourceManager.class);
protected static ResourceManager manager = null;
protected File dirWithTiles ;
protected File dirWithTiles;
private List<TilesCache> tilesCacheList = new ArrayList<>();
private BitmapTilesCache bitmapTilesCache;
@ -115,21 +116,22 @@ public class ResourceManager {
STREET_LOOKUP,
TRANSPORT,
ADDRESS,
QUICK_SEARCH,
QUICK_SEARCH,
ROUTING,
TRANSPORT_ROUTING
}
public static class BinaryMapReaderResource {
private BinaryMapIndexReader initialReader;
private File filename;
private List<BinaryMapIndexReader> readers = new ArrayList<>(BinaryMapReaderResourceType.values().length);
private boolean useForRouting;
private boolean useForPublicTransport;
public BinaryMapReaderResource(File f, BinaryMapIndexReader initialReader) {
this.filename = f;
this.initialReader = initialReader;
while(readers.size() < BinaryMapReaderResourceType.values().length) {
while (readers.size() < BinaryMapReaderResourceType.values().length) {
readers.add(null);
}
}
@ -173,7 +175,7 @@ public class ResourceManager {
}
initialReader = null;
}
public boolean isClosed() {
return initialReader == null;
}
@ -189,7 +191,7 @@ public class ResourceManager {
public void setUseForRouting(boolean useForRouting) {
this.useForRouting = useForRouting;
}
public boolean isUseForRouting() {
return useForRouting;
}
@ -202,34 +204,32 @@ public class ResourceManager {
this.useForPublicTransport = useForPublicTransport;
}
}
protected final Map<String, BinaryMapReaderResource> fileReaders = new ConcurrentHashMap<String, BinaryMapReaderResource>();
private final Map<String, RegionAddressRepository> addressMap = new ConcurrentHashMap<String, RegionAddressRepository>();
protected final Map<String, AmenityIndexRepository> amenityRepositories = new ConcurrentHashMap<String, AmenityIndexRepository>();
// protected final Map<String, BinaryMapIndexReader> routingMapFiles = new ConcurrentHashMap<String, BinaryMapIndexReader>();
protected final Map<String, AmenityIndexRepository> amenityRepositories = new ConcurrentHashMap<String, AmenityIndexRepository>();
// protected final Map<String, BinaryMapIndexReader> routingMapFiles = new ConcurrentHashMap<String, BinaryMapIndexReader>();
protected final Map<String, BinaryMapReaderResource> transportRepositories = new ConcurrentHashMap<String, BinaryMapReaderResource>();
protected final Map<String, BinaryMapReaderResource> travelRepositories = new ConcurrentHashMap<String, BinaryMapReaderResource>();
protected final Map<String, String> indexFileNames = new ConcurrentHashMap<String, String>();
protected final Map<String, String> basemapFileNames = new ConcurrentHashMap<String, String>();
protected final IncrementalChangesManager changesManager = new IncrementalChangesManager(this);
protected final MapRenderRepositories renderer;
protected final MapTileDownloader tileDownloader;
public final AsyncLoadingThread asyncLoadingThread = new AsyncLoadingThread(this);
private HandlerThread renderingBufferImageThread;
protected boolean internetIsNotAccessible = false;
private boolean depthContours;
public ResourceManager(OsmandApplication context) {
this.context = context;
this.renderer = new MapRenderRepositories(context);
@ -271,7 +271,7 @@ public class ResourceManager {
public MapTileDownloader getMapTileDownloader() {
return tileDownloader;
}
public HandlerThread getRenderingBufferImageThread() {
return renderingBufferImageThread;
}
@ -293,17 +293,17 @@ public class ResourceManager {
// ".nomedia" indicates there are no pictures and no music to list in this dir for the Gallery app
try {
context.getAppPath(".nomedia").createNewFile(); //$NON-NLS-1$
} catch( Exception e ) {
} catch (Exception e) {
}
for (TilesCache tilesCache : tilesCacheList) {
tilesCache.setDirWithTiles(dirWithTiles);
}
}
public java.text.DateFormat getDateFormat() {
return DateFormat.getDateFormat(context);
}
public OsmandApplication getContext() {
return context;
}
@ -323,7 +323,7 @@ public class ResourceManager {
return null;
}
public synchronized void tileDownloaded(DownloadRequest request){
public synchronized void tileDownloaded(DownloadRequest request) {
if (request instanceof TileLoadDownloadRequest) {
TileLoadDownloadRequest req = ((TileLoadDownloadRequest) request);
TilesCache cache = getTilesCache(req.tileSource);
@ -332,13 +332,13 @@ public class ResourceManager {
}
}
}
public synchronized boolean tileExistOnFileSystem(String file, ITileSource map, int x, int y, int zoom) {
TilesCache cache = getTilesCache(map);
return cache != null && cache.tileExistOnFileSystem(file, map, x, y, zoom);
}
public void clearTileForMap(String file, ITileSource map, int x, int y, int zoom){
public void clearTileForMap(String file, ITileSource map, int x, int y, int zoom) {
TilesCache cache = getTilesCache(map);
if (cache != null) {
cache.getTileForMap(file, map, x, y, zoom, true, false, true, true);
@ -376,7 +376,7 @@ public class ResourceManager {
////////////////////////////////////////////// Working with indexes ////////////////////////////////////////////////
public List<String> reloadIndexesOnStart(AppInitializer progress, List<String> warnings){
public List<String> reloadIndexesOnStart(AppInitializer progress, List<String> warnings) {
close();
// check we have some assets to copy to sdcard
warnings.addAll(checkAssets(progress, false));
@ -429,7 +429,7 @@ public class ResourceManager {
return warnings;
}
public List<String> indexFontFiles(IProgress progress){
public List<String> indexFontFiles(IProgress progress) {
File file = context.getAppPath(IndexConstants.FONT_INDEX_DIR);
file.mkdirs();
List<String> warnings = new ArrayList<String>();
@ -473,10 +473,10 @@ public class ResourceManager {
log.error("Error while loading tts files from assets", e);
}
}
public List<String> checkAssets(IProgress progress, boolean forceUpdate) {
String fv = Version.getFullVersion(context);
if(context.getAppInitializer().isAppVersionChanged()) {
if (context.getAppInitializer().isAppVersionChanged()) {
copyMissingJSAssets();
}
if (!fv.equalsIgnoreCase(context.getSettings().PREVIOUS_INSTALLED_VERSION.get()) || forceUpdate) {
@ -509,7 +509,7 @@ public class ResourceManager {
}
return Collections.emptyList();
}
private void copyRegionsBoundaries() {
try {
File file = context.getAppPath("regions.ocbf");
@ -522,7 +522,7 @@ public class ResourceManager {
log.error(e.getMessage(), e);
}
}
private void copyPoiTypes() {
try {
File file = context.getAppPath(IndexConstants.SETTINGS_DIR + "poi_types.xml");
@ -540,6 +540,7 @@ public class ResourceManager {
private final static String ASSET_COPY_MODE__overwriteOnlyIfExists = "overwriteOnlyIfExists";
private final static String ASSET_COPY_MODE__alwaysOverwriteOrCopy = "alwaysOverwriteOrCopy";
private final static String ASSET_COPY_MODE__copyOnlyIfDoesNotExist = "copyOnlyIfDoesNotExist";
private void unpackBundledAssets(AssetManager assetManager, File appDataDir, IProgress progress, boolean isFirstInstall) throws IOException, XmlPullParserException {
List<AssetEntry> assetEntries = DownloadOsmandIndexesHelper.getBundledAssets(assetManager);
for (AssetEntry asset : assetEntries) {
@ -581,7 +582,7 @@ public class ResourceManager {
}
public static void copyAssets(AssetManager assetManager, String assetName, File file) throws IOException {
if(file.exists()){
if (file.exists()) {
Algorithms.removeAllFiles(file);
}
file.getParentFile().mkdirs();
@ -593,9 +594,9 @@ public class ResourceManager {
}
private List<File> collectFiles(File dir, String ext, List<File> files) {
if(dir.exists() && dir.canRead()) {
if (dir.exists() && dir.canRead()) {
File[] lf = dir.listFiles();
if(lf == null || lf.length == 0) {
if (lf == null || lf.length == 0) {
return files;
}
for (File f : lf) {
@ -606,12 +607,10 @@ public class ResourceManager {
}
return files;
}
private void renameRoadsFiles(ArrayList<File> files, File roadsPath) {
Iterator<File> it = files.iterator();
while(it.hasNext()) {
while (it.hasNext()) {
File f = it.next();
if (f.getName().endsWith("-roads" + IndexConstants.BINARY_MAP_INDEX_EXT)) {
f.renameTo(new File(roadsPath, f.getName().replace("-roads" + IndexConstants.BINARY_MAP_INDEX_EXT,
@ -632,7 +631,7 @@ public class ResourceManager {
File appPath = context.getAppPath(null);
File roadsPath = context.getAppPath(IndexConstants.ROADS_INDEX_DIR);
roadsPath.mkdirs();
collectFiles(appPath, IndexConstants.BINARY_MAP_INDEX_EXT, files);
renameRoadsFiles(files, roadsPath);
collectFiles(roadsPath, IndexConstants.BINARY_MAP_INDEX_EXT, files);
@ -645,7 +644,7 @@ public class ResourceManager {
if (OsmandPlugin.getEnabledPlugin(SRTMPlugin.class) != null || InAppPurchaseHelper.isContourLinesPurchased(context)) {
collectFiles(context.getAppPath(IndexConstants.SRTM_INDEX_DIR), IndexConstants.BINARY_MAP_INDEX_EXT, files);
}
changesManager.collectChangesFiles(context.getAppPath(IndexConstants.LIVE_INDEX_DIR), IndexConstants.BINARY_MAP_INDEX_EXT, files);
Collections.sort(files, Algorithms.getFileVersionComparator());
@ -703,7 +702,7 @@ public class ResourceManager {
log.error(String.format("File %s could not be read", f.getName()), e);
}
boolean wikiMap = (f.getName().contains("_wiki") || f.getName().contains(IndexConstants.BINARY_WIKI_MAP_INDEX_EXT));
boolean srtmMap = f.getName().contains(IndexConstants.BINARY_SRTM_MAP_INDEX_EXT);
boolean srtmMap = SrtmDownloadItem.containsSrtmExtension(f.getName());
if (mapReader == null || (!Version.isPaidVersion(context) && wikiMap && !f.getName().equals(DEFAULT_WIKIVOYAGE_TRAVEL_OBF))) {
warnings.add(MessageFormat.format(context.getString(R.string.version_index_is_not_supported), f.getName())); //$NON-NLS-1$
} else {
@ -714,9 +713,9 @@ public class ResourceManager {
if (dateCreated == 0) {
dateCreated = f.lastModified();
}
if(f.getParentFile().getName().equals(liveDir.getName())) {
if (f.getParentFile().getName().equals(liveDir.getName())) {
boolean toUse = changesManager.index(f, dateCreated, mapReader);
if(!toUse) {
if (!toUse) {
try {
mapReader.close();
} catch (IOException e) {
@ -724,7 +723,7 @@ public class ResourceManager {
}
continue;
}
} else if(!wikiMap && !srtmMap) {
} else if (!wikiMap && !srtmMap) {
changesManager.indexMainMap(f, dateCreated);
}
indexFileNames.put(f.getName(), dateFormat.format(dateCreated)); //$NON-NLS-1$
@ -733,7 +732,7 @@ public class ResourceManager {
}
renderer.initializeNewResource(progress, f, mapReader);
BinaryMapReaderResource resource = new BinaryMapReaderResource(f, mapReader);
if (collectTravelFiles(resource)){
if (collectTravelFiles(resource)) {
//travel files are indexed
continue;
}
@ -746,7 +745,7 @@ public class ResourceManager {
transportRepositories.put(f.getName(), resource);
}
// disable osmc for routing temporarily due to some bugs
if (mapReader.containsRouteData() && (!f.getParentFile().equals(liveDir) ||
if (mapReader.containsRouteData() && (!f.getParentFile().equals(liveDir) ||
context.getSettings().USE_OSM_LIVE_FOR_ROUTING.get())) {
resource.setUseForRouting(true);
}
@ -789,7 +788,7 @@ public class ResourceManager {
}
}
Iterator<Entry<PoiCategory, Map<String, PoiType>>> it = toAddPoiTypes.entrySet().iterator();
while(it.hasNext()) {
while (it.hasNext()) {
Entry<PoiCategory, Map<String, PoiType>> next = it.next();
PoiCategory category = next.getKey();
category.addExtraPoiTypes(next.getValue());
@ -839,7 +838,7 @@ public class ResourceManager {
}
private boolean collectTravelFiles(BinaryMapReaderResource resource) {
if (resource.getFileName().contains(IndexConstants.BINARY_TRAVEL_GUIDE_MAP_INDEX_EXT)){
if (resource.getFileName().contains(IndexConstants.BINARY_TRAVEL_GUIDE_MAP_INDEX_EXT)) {
travelRepositories.put(resource.getFileName(), resource);
return true;
}
@ -855,7 +854,7 @@ public class ResourceManager {
}
}
}
////////////////////////////////////////////// Working with amenities ////////////////////////////////////////////////
public List<AmenityIndexRepository> getAmenityRepositories() {
@ -872,7 +871,7 @@ public class ResourceManager {
}
public List<Amenity> searchAmenities(SearchPoiTypeFilter filter,
double topLatitude, double leftLongitude, double bottomLatitude, double rightLongitude, int zoom, final ResultMatcher<Amenity> matcher) {
double topLatitude, double leftLongitude, double bottomLatitude, double rightLongitude, int zoom, final ResultMatcher<Amenity> matcher) {
final List<Amenity> amenities = new ArrayList<Amenity>();
searchAmenitiesInProgress = true;
try {
@ -901,8 +900,8 @@ public class ResourceManager {
return amenities;
}
public List<Amenity> searchAmenitiesOnThePath(List<Location> locations, double radius, SearchPoiTypeFilter filter,
ResultMatcher<Amenity> matcher) {
public List<Amenity> searchAmenitiesOnThePath(List<Location> locations, double radius, SearchPoiTypeFilter filter,
ResultMatcher<Amenity> matcher) {
searchAmenitiesInProgress = true;
final List<Amenity> amenities = new ArrayList<Amenity>();
try {
@ -921,9 +920,9 @@ public class ResourceManager {
if (!filter.isEmpty()) {
for (AmenityIndexRepository index : getAmenityRepositories()) {
if (index.checkContainsInt(
MapUtils.get31TileNumberY(topLatitude),
MapUtils.get31TileNumberX(leftLongitude),
MapUtils.get31TileNumberY(bottomLatitude),
MapUtils.get31TileNumberY(topLatitude),
MapUtils.get31TileNumberX(leftLongitude),
MapUtils.get31TileNumberY(bottomLatitude),
MapUtils.get31TileNumberX(rightLongitude))) {
repos.add(index);
}
@ -931,7 +930,7 @@ public class ResourceManager {
if (!repos.isEmpty()) {
for (AmenityIndexRepository r : repos) {
List<Amenity> res = r.searchAmenitiesOnThePath(locations, radius, filter, matcher);
if(res != null) {
if (res != null) {
amenities.addAll(res);
}
}
@ -943,12 +942,11 @@ public class ResourceManager {
}
return amenities;
}
public boolean containsAmenityRepositoryToSearch(boolean searchByName){
public boolean containsAmenityRepositoryToSearch(boolean searchByName) {
for (AmenityIndexRepository index : getAmenityRepositories()) {
if(searchByName){
if(index instanceof AmenityIndexRepositoryBinary){
if (searchByName) {
if (index instanceof AmenityIndexRepositoryBinary) {
return true;
}
} else {
@ -957,10 +955,10 @@ public class ResourceManager {
}
return false;
}
public List<Amenity> searchAmenitiesByName(String searchQuery,
double topLatitude, double leftLongitude, double bottomLatitude, double rightLongitude,
double lat, double lon, ResultMatcher<Amenity> matcher) {
double topLatitude, double leftLongitude, double bottomLatitude, double rightLongitude,
double lat, double lon, ResultMatcher<Amenity> matcher) {
List<Amenity> amenities = new ArrayList<Amenity>();
List<AmenityIndexRepositoryBinary> list = new ArrayList<AmenityIndexRepositoryBinary>();
int left = MapUtils.get31TileNumberX(leftLongitude);
@ -973,16 +971,16 @@ public class ResourceManager {
}
if (index instanceof AmenityIndexRepositoryBinary) {
if (index.checkContainsInt(top, left, bottom, right)) {
if(index.checkContains(lat, lon)){
if (index.checkContains(lat, lon)) {
list.add(0, (AmenityIndexRepositoryBinary) index);
} else {
list.add((AmenityIndexRepositoryBinary) index);
}
}
}
}
// Not using boundares results in very slow initial search if user has many maps installed
// int left = 0;
// int top = 0;
@ -1000,7 +998,7 @@ public class ResourceManager {
return amenities;
}
public Map<PoiCategory, List<String>> searchAmenityCategoriesByName(String searchQuery, double lat, double lon) {
Map<PoiCategory, List<String>> map = new LinkedHashMap<PoiCategory, List<String>>();
for (AmenityIndexRepository index : getAmenityRepositories()) {
@ -1016,17 +1014,17 @@ public class ResourceManager {
public AmenityIndexRepositoryBinary getAmenityRepositoryByFileName(String filename) {
return (AmenityIndexRepositoryBinary) amenityRepositories.get(filename);
}
////////////////////////////////////////////// Working with address ///////////////////////////////////////////
public RegionAddressRepository getRegionRepository(String name){
public RegionAddressRepository getRegionRepository(String name) {
return addressMap.get(name);
}
public Collection<RegionAddressRepository> getAddressRepositories(){
public Collection<RegionAddressRepository> getAddressRepositories() {
return addressMap.values();
}
public Collection<BinaryMapReaderResource> getFileReaders() {
List<String> fileNames = new ArrayList<>(fileReaders.keySet());
Collections.sort(fileNames, Algorithms.getStringVersionComparator());
@ -1039,8 +1037,7 @@ public class ResourceManager {
}
return res;
}
////////////////////////////////////////////// Working with transport ////////////////////////////////////////////////
private List<BinaryMapIndexReader> getTransportRepositories(double topLat, double leftLon, double bottomLat, double rightLon) {
@ -1059,7 +1056,7 @@ public class ResourceManager {
public List<TransportStop> searchTransportSync(double topLat, double leftLon, double bottomLat, double rightLon,
ResultMatcher<TransportStop> matcher) throws IOException {
ResultMatcher<TransportStop> matcher) throws IOException {
TransportStopsRouteReader readers =
new TransportStopsRouteReader(getTransportRepositories(topLat, leftLon, bottomLat, rightLon));
List<TransportStop> stops = new ArrayList<>();
@ -1076,7 +1073,7 @@ public class ResourceManager {
public List<TransportRoute> getRoutesForStop(TransportStop stop) {
List<TransportRoute> rts = stop.getRoutes();
if(rts != null) {
if (rts != null) {
return rts;
}
return Collections.emptyList();
@ -1086,26 +1083,26 @@ public class ResourceManager {
public boolean updateRenderedMapNeeded(RotatedTileBox rotatedTileBox, DrawSettings drawSettings) {
return renderer.updateMapIsNeeded(rotatedTileBox, drawSettings);
}
public void updateRendererMap(RotatedTileBox rotatedTileBox, OnMapLoadedListener mapLoadedListener){
public void updateRendererMap(RotatedTileBox rotatedTileBox, OnMapLoadedListener mapLoadedListener) {
renderer.interruptLoadingMap();
asyncLoadingThread.requestToLoadMap(new MapLoadRequest(rotatedTileBox, mapLoadedListener));
}
public void interruptRendering(){
public void interruptRendering() {
renderer.interruptLoadingMap();
}
public boolean isSearchAmenitiesInProgress() {
return searchAmenitiesInProgress;
}
public MapRenderRepositories getRenderer() {
return renderer;
}
////////////////////////////////////////////// Closing methods ////////////////////////////////////////////////
public void closeFile(String fileName) {
amenityRepositories.remove(fileName);
addressMap.remove(fileName);
@ -1114,12 +1111,12 @@ public class ResourceManager {
travelRepositories.remove(fileName);
renderer.closeConnection(fileName);
BinaryMapReaderResource resource = fileReaders.remove(fileName);
if(resource != null) {
if (resource != null) {
resource.close();
}
}
}
public synchronized void close(){
public synchronized void close() {
for (TilesCache tc : tilesCacheList) {
tc.close();
}
@ -1130,7 +1127,7 @@ public class ResourceManager {
travelRepositories.clear();
addressMap.clear();
amenityRepositories.clear();
for(BinaryMapReaderResource res : fileReaders.values()) {
for (BinaryMapReaderResource res : fileReaders.values()) {
res.close();
}
fileReaders.clear();
@ -1154,7 +1151,7 @@ public class ResourceManager {
Collection<BinaryMapReaderResource> fileReaders = getFileReaders();
List<BinaryMapIndexReader> readers = new ArrayList<>(fileReaders.size());
for (BinaryMapReaderResource r : fileReaders) {
if (r.isUseForPublicTransport()) {
if (r.isUseForPublicTransport()) {
BinaryMapIndexReader reader = r.getReader(BinaryMapReaderResourceType.TRANSPORT_ROUTING);
if (reader != null) {
readers.add(reader);
@ -1182,9 +1179,8 @@ public class ResourceManager {
public Map<String, String> getIndexFileNames() {
return new LinkedHashMap<String, String>(indexFileNames);
}
public boolean containsBasemap(){
public boolean containsBasemap() {
return !basemapFileNames.isEmpty();
}
@ -1218,13 +1214,13 @@ public class ResourceManager {
}
return map;
}
public synchronized void reloadTilesFromFS() {
for (TilesCache tc : tilesCacheList) {
tc.tilesOnFS.clear();
}
}
/// On low memory method ///
public void onLowMemory() {
log.info("On low memory");
@ -1233,10 +1229,10 @@ public class ResourceManager {
r.clearCache();
}
renderer.clearCache();
System.gc();
}
public GeoidAltitudeCorrection getGeoidAltitudeCorrection() {
return geoidAltitudeCorrection;
}
@ -1251,7 +1247,7 @@ public class ResourceManager {
tc.clearTiles();
}
}
public IncrementalChangesManager getChangesManager() {
return changesManager;
}

View file

@ -7,6 +7,7 @@ import androidx.annotation.Nullable;
import net.osmand.IndexConstants;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.download.SrtmDownloadItem;
import net.osmand.util.Algorithms;
import org.json.JSONException;
@ -92,7 +93,7 @@ public class FileSettingsItem extends StreamSettingsItem {
case OTHER:
break;
case SRTM_MAP:
if (name.endsWith(IndexConstants.BINARY_SRTM_MAP_INDEX_EXT)) {
if (SrtmDownloadItem.isSrtmFile(name)) {
return subtype;
}
break;
@ -257,6 +258,8 @@ public class FileSettingsItem extends StreamSettingsItem {
prefix = oldPath.substring(0, oldPath.lastIndexOf(IndexConstants.BINARY_WIKI_MAP_INDEX_EXT));
} else if (oldPath.endsWith(IndexConstants.BINARY_SRTM_MAP_INDEX_EXT)) {
prefix = oldPath.substring(0, oldPath.lastIndexOf(IndexConstants.BINARY_SRTM_MAP_INDEX_EXT));
} else if (oldPath.endsWith(IndexConstants.BINARY_SRTM_FEET_MAP_INDEX_EXT)) {
prefix = oldPath.substring(0, oldPath.lastIndexOf(IndexConstants.BINARY_SRTM_FEET_MAP_INDEX_EXT));
} else if (oldPath.endsWith(IndexConstants.BINARY_ROAD_MAP_INDEX_EXT)) {
prefix = oldPath.substring(0, oldPath.lastIndexOf(IndexConstants.BINARY_ROAD_MAP_INDEX_EXT));
} else {

View file

@ -200,7 +200,7 @@ public class DataStorageHelper {
terrainMemory = MemoryItem.builder()
.setKey(TERRAIN_MEMORY)
.setExtensions(IndexConstants.BINARY_SRTM_MAP_INDEX_EXT)
.setExtensions(IndexConstants.BINARY_SRTM_MAP_INDEX_EXT, IndexConstants.BINARY_SRTM_FEET_MAP_INDEX_EXT)
.setDirectories(
createDirectory(SRTM_INDEX_DIR, true, EXTENSIONS, true),
createDirectory(TILES_INDEX_DIR, false, PREFIX, false))
@ -323,7 +323,7 @@ public class DataStorageHelper {
public interface UpdateMemoryInfoUIAdapter {
void onMemoryInfoUpdate();
void onFinishUpdating(String tag);
}

View file

@ -36,6 +36,7 @@ import net.osmand.plus.base.bottomsheetmenu.BottomSheetItemWithCompoundButton.Bu
import net.osmand.plus.base.bottomsheetmenu.BottomSheetItemWithDescription;
import net.osmand.plus.base.bottomsheetmenu.SimpleBottomSheetItem;
import net.osmand.plus.base.bottomsheetmenu.simpleitems.SimpleDividerItem;
import net.osmand.plus.download.SrtmDownloadItem;
import net.osmand.plus.helpers.AvoidSpecificRoads.AvoidRoadInfo;
import net.osmand.plus.helpers.FileNameTranslationHelper;
import net.osmand.plus.helpers.GpxUiHelper;
@ -530,7 +531,7 @@ public class ExportItemsBottomSheet extends MenuBottomSheetDialogFragment {
return getString(R.string.download_roads_only_item);
} else if (file.getName().endsWith(IndexConstants.BINARY_WIKI_MAP_INDEX_EXT)) {
return getString(R.string.download_wikipedia_maps);
} else if (file.getName().endsWith(IndexConstants.BINARY_SRTM_MAP_INDEX_EXT)) {
} else if (SrtmDownloadItem.isSrtmFile(file.getName())) {
return getString(R.string.download_srtm_maps);
} else if (file.getName().endsWith(IndexConstants.BINARY_MAP_INDEX_EXT)) {
return getString(R.string.download_regular_maps);

View file

@ -18,6 +18,7 @@ import net.osmand.plus.UiUtilities;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
public class MultiStateToggleButton {
@ -37,6 +38,13 @@ public class MultiStateToggleButton {
this.nightMode = nightMode;
}
public void setItems(Collection<RadioItem> radioItems) {
if (radioItems == null || radioItems.size() < 2) return;
items.clear();
items.addAll(radioItems);
initView();
}
public void setItems(RadioItem firstBtn, RadioItem secondBtn, RadioItem... other) {
items.clear();
items.add(firstBtn);