diff --git a/OsmAnd/res/layout/settings_group_title.xml b/OsmAnd/res/layout/settings_group_title.xml index 43fedb8440..4ac7fbfe05 100644 --- a/OsmAnd/res/layout/settings_group_title.xml +++ b/OsmAnd/res/layout/settings_group_title.xml @@ -97,12 +97,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"> getLocalIndexInfos(String downloadName) { List list = new ArrayList<>(); LocalIndexInfo info = getLocalIndexInfo(LocalIndexType.MAP_DATA, downloadName, false, false); @@ -313,7 +311,7 @@ public class LocalIndexHelper { } } } - + private void loadTravelData(File mapPath, List result, AbstractLoadLocalIndexTask loadTask) { if (mapPath.canRead()) { for (File mapFile : listFilesSorted(mapPath)) { @@ -334,7 +332,8 @@ public class LocalIndexHelper { for (File mapFile : listFilesSorted(mapPath)) { if (mapFile.isFile() && mapFile.getName().endsWith(IndexConstants.BINARY_MAP_INDEX_EXT)) { LocalIndexType lt = LocalIndexType.MAP_DATA; - if (mapFile.getName().endsWith(IndexConstants.BINARY_SRTM_MAP_INDEX_EXT)) { + if (mapFile.getName().endsWith(IndexConstants.BINARY_SRTM_MAP_INDEX_EXT) + || mapFile.getName().endsWith(IndexConstants.BINARY_SRTM_FEET_MAP_INDEX_EXT)) { lt = LocalIndexType.SRTM_DATA; } else if (mapFile.getName().endsWith(IndexConstants.BINARY_WIKI_MAP_INDEX_EXT)) { lt = LocalIndexType.WIKI_DATA; @@ -403,7 +402,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 +429,4 @@ public class LocalIndexHelper { return fileName; } } - } diff --git a/OsmAnd/src/net/osmand/plus/base/SelectMultipleItemsBottomSheet.java b/OsmAnd/src/net/osmand/plus/base/SelectMultipleItemsBottomSheet.java index 60b507c972..d09c4a3d6c 100644 --- a/OsmAnd/src/net/osmand/plus/base/SelectMultipleItemsBottomSheet.java +++ b/OsmAnd/src/net/osmand/plus/base/SelectMultipleItemsBottomSheet.java @@ -5,6 +5,7 @@ import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.LinearLayout; import android.widget.TextView; import androidx.annotation.NonNull; @@ -21,8 +22,14 @@ 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.BottomSheetItemWithDescription; import net.osmand.plus.base.bottomsheetmenu.SimpleBottomSheetItem; import net.osmand.plus.base.bottomsheetmenu.simpleitems.SimpleDividerItem; +import net.osmand.plus.download.MultipleIndexesUiHelper.SelectedItemsListener; +import net.osmand.plus.helpers.AndroidUiHelper; +import net.osmand.plus.widgets.MultiStateToggleButton; +import net.osmand.plus.widgets.MultiStateToggleButton.OnRadioItemClickListener; +import net.osmand.plus.widgets.MultiStateToggleButton.RadioItem; import net.osmand.util.Algorithms; import net.osmand.view.ThreeStateCheckbox; @@ -35,6 +42,8 @@ import static net.osmand.view.ThreeStateCheckbox.State.UNCHECKED; public class SelectMultipleItemsBottomSheet extends MenuBottomSheetDialogFragment { + public static final String TAG = SelectMultipleItemsBottomSheet.class.getSimpleName(); + private OsmandApplication app; private UiUtilities uiUtilities; @@ -45,15 +54,57 @@ public class SelectMultipleItemsBottomSheet extends MenuBottomSheetDialogFragmen private TextView selectedSize; private ThreeStateCheckbox checkBox; + private int sizeAboveList = 0; private int activeColorRes; private int secondaryColorRes; + private String addDescriptionText; + private String leftRadioButtonText; + private String rightRadioButtonText; + private boolean customOptionsVisible; + private boolean leftButtonSelected; private final List allItems = new ArrayList<>(); private final List selectedItems = new ArrayList<>(); private SelectionUpdateListener selectionUpdateListener; private OnApplySelectionListener onApplySelectionListener; + private OnRadioButtonSelectListener onRadioButtonSelectListener; + private SelectedItemsListener selectedItemsListener; - public static final String TAG = SelectMultipleItemsBottomSheet.class.getSimpleName(); + public static SelectMultipleItemsBottomSheet showInstance(@NonNull AppCompatActivity activity, + @NonNull List items, + @Nullable List 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 static SelectMultipleItemsBottomSheet showInstance(@NonNull AppCompatActivity activity, + @NonNull List items, + @Nullable List selected, + boolean usedOnMap, + String addDescription, + boolean customOptionsVisible, + boolean leftButtonSelected, + String leftRadioButtonText, + String rightRadioButtonText) { + SelectMultipleItemsBottomSheet fragment = new SelectMultipleItemsBottomSheet(); + fragment.setUsedOnMap(usedOnMap); + fragment.setItems(items); + fragment.setSelectedItems(selected); + fragment.setAddDescriptionText(addDescription); + fragment.setCustomOptionsVisible(customOptionsVisible); + fragment.setLeftButtonSelected(leftButtonSelected); + fragment.setLeftRadioButtonText(leftRadioButtonText); + fragment.setRightRadioButtonText(rightRadioButtonText); + FragmentManager fm = activity.getSupportFragmentManager(); + fragment.show(fm, TAG); + return fragment; + } @Nullable @Override @@ -72,9 +123,18 @@ public class SelectMultipleItemsBottomSheet extends MenuBottomSheetDialogFragmen items.add(createTitleItem()); items.add(new SimpleDividerItem(app)); + sizeAboveList = items.size(); createListItems(); } + @Override + public void onPause() { + super.onPause(); + if (requireActivity().isChangingConfigurations()) { + dismiss(); + } + } + private BaseBottomSheetItem createTitleItem() { LayoutInflater themedInflater = UiUtilities.getInflater(requireContext(), nightMode); View view = themedInflater.inflate(R.layout.settings_group_title, null); @@ -85,66 +145,111 @@ public class SelectMultipleItemsBottomSheet extends MenuBottomSheetDialogFragmen 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(); + TextView addDescription = view.findViewById(R.id.additional_description); + LinearLayout customRadioButtons = view.findViewById(R.id.custom_radio_buttons); + + if (!isMultipleItem()) { + AndroidUiHelper.setVisibility(View.GONE, description, selectedSize, selectAllButton); + } else { + 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); } - onSelectedItemsChanged(); - updateItems(checked); - } - }); + }); + } + + if (!Algorithms.isEmpty(addDescriptionText)) { + addDescription.setText(addDescriptionText); + AndroidUiHelper.setVisibility(View.VISIBLE, addDescription); + } + + if (customOptionsVisible) { + AndroidUiHelper.setVisibility(View.VISIBLE, customRadioButtons); + RadioItem leftRadioButton = new RadioItem(leftRadioButtonText); + RadioItem rightRadioButton = new RadioItem(rightRadioButtonText); + MultiStateToggleButton toggleButtons = + new MultiStateToggleButton(app, customRadioButtons, nightMode); + toggleButtons.setItems(leftRadioButton, rightRadioButton); + toggleButtons.updateView(true); + leftRadioButton.setOnClickListener(new OnRadioItemClickListener() { + @Override + public boolean onRadioItemClick(RadioItem radioItem, View view) { + onRadioButtonSelectListener.onSelect(leftButtonSelected = true); + updateSelectedSizeView(); + updateSelectAllButton(); + updateApplyButtonEnable(); + return true; + } + }); + rightRadioButton.setOnClickListener(new OnRadioItemClickListener() { + @Override + public boolean onRadioItemClick(RadioItem radioItem, View view) { + onRadioButtonSelectListener.onSelect(leftButtonSelected = false); + updateSelectedSizeView(); + updateSelectAllButton(); + updateApplyButtonEnable(); + return true; + } + }); + toggleButtons.setSelectedItem(leftButtonSelected ? leftRadioButton : rightRadioButton); + } + 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); + if (isMultipleItem()) { + for (int i = 0; i < allItems.size(); i++) { + final SelectableItem item = allItems.get(i); + boolean checked = selectedItems.contains(item); + final int finalI = i; + items.add(new Builder() + .setChecked(checked) + .setButtonTintList(AndroidUtils.createCheckedColorStateList(app, secondaryColorRes, activeColorRes)) + .setDescription(item.description) + .setIcon(uiUtilities.getIcon(item.iconId, activeColorRes)) + .setTitle(item.title) + .setLayoutId(R.layout.bottom_sheet_item_with_descr_and_checkbox_56dp) + .setTag(item) + .setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + BottomSheetItemWithCompoundButton item = (BottomSheetItemWithCompoundButton) items.get(finalI + sizeAboveList); + boolean checked = item.isChecked(); + item.setChecked(!checked); + SelectableItem tag = (SelectableItem) item.getTag(); + if (!checked) { + selectedItems.add(tag); + } else { + selectedItems.remove(tag); + } + onSelectedItemsChanged(); } - onSelectedItemsChanged(); - } - }) - .setTag(item); - setupListItem(builder, item); - uiItem[0] = builder.create(); - items.add(uiItem[0]); + }) + .create()); + } + } else if (allItems.size() == 1) { + final SelectableItem item = allItems.get(0); + items.add(new Builder() + .setDescription(item.description) + .setDescriptionColorId(AndroidUtils.getSecondaryTextColorId(nightMode)) + .setIcon(uiUtilities.getIcon(item.iconId, activeColorRes)) + .setTitle(item.title) + .setLayoutId(R.layout.bottom_sheet_item_with_descr_56dp) + .setTag(item) + .create()); } } - @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(); @@ -154,48 +259,32 @@ public class SelectMultipleItemsBottomSheet extends MenuBottomSheetDialogFragmen } } - @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); + if (isMultipleItem()) { + 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); } - 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)); + if (isMultipleItem()) { + 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); - } + rightButton.setEnabled(!Algorithms.isEmpty(selectedItems)); } private void updateItems(boolean checked) { @@ -206,6 +295,59 @@ public class SelectMultipleItemsBottomSheet extends MenuBottomSheetDialogFragmen } } + public void setItems(List allItems) { + this.allItems.clear(); + if (!Algorithms.isEmpty(allItems)) { + this.allItems.addAll(allItems); + } + } + + private void setSelectedItems(List selected) { + this.selectedItems.clear(); + if (!Algorithms.isEmpty(selected)) { + /*List prevDownloadItems = new ArrayList<>(this.selectedItems); + for (SelectableItem prevDownloadItem : selected) { + Object object = prevDownloadItem.getObject(); + if (object instanceof IndexItem && ((IndexItem) object).isDownloaded()) { + prevDownloadItems.add(prevDownloadItem); + } + } + selected.removeAll(prevDownloadItems);*/ + this.selectedItems.addAll(selected); + } + } + + public void recreateList(List allItems) { + setItems(allItems); + if (selectedItemsListener != null) { + setSelectedItems(selectedItemsListener.createSelectedItems(this.allItems, leftButtonSelected)); + } + if (items.size() > sizeAboveList) { + for (int i = 0; i < this.allItems.size(); i++) { + SelectableItem item = this.allItems.get(i); + BottomSheetItemWithDescription button = (BottomSheetItemWithDescription) items.get(i + sizeAboveList); + button.setDescription(item.description); + button.setTitle(item.title); + button.setTag(item); + if (isMultipleItem()) { + ((BottomSheetItemWithCompoundButton) button).setChecked(selectedItems.contains(item)); + } + } + } + } + + public boolean isMultipleItem() { + return allItems.size() > 1; + } + + public List getSelectedItems() { + return selectedItems; + } + + public void setConfirmButtonTitle(@NonNull String confirmButtonTitle) { + applyButtonTitle.setText(confirmButtonTitle); + } + public void setTitle(@NonNull String title) { this.title.setText(title); } @@ -214,45 +356,24 @@ public class SelectMultipleItemsBottomSheet extends MenuBottomSheetDialogFragmen this.description.setText(description); } - public void setConfirmButtonTitle(@NonNull String confirmButtonTitle) { - applyButtonTitle.setText(confirmButtonTitle); + public void setAddDescriptionText(String addDescriptionText) { + this.addDescriptionText = addDescriptionText; } - private void setItems(List allItems) { - if (!Algorithms.isEmpty(allItems)) { - this.allItems.addAll(allItems); - } + public void setLeftRadioButtonText(String leftRadioButtonText) { + this.leftRadioButtonText = leftRadioButtonText; } - private void setSelectedItems(List selected) { - if (!Algorithms.isEmpty(selected)) { - this.selectedItems.addAll(selected); - } + public void setRightRadioButtonText(String rightRadioButtonText) { + this.rightRadioButtonText = rightRadioButtonText; } - public List getSelectedItems() { - return selectedItems; + public void setCustomOptionsVisible(boolean customOptionsVisible) { + this.customOptionsVisible = customOptionsVisible; } - @Override - public void onPause() { - super.onPause(); - if (requireActivity().isChangingConfigurations()) { - dismiss(); - } - } - - public static SelectMultipleItemsBottomSheet showInstance(@NonNull AppCompatActivity activity, - @NonNull List items, - @Nullable List 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 setLeftButtonSelected(boolean leftButtonSelected) { + this.leftButtonSelected = leftButtonSelected; } public void setSelectionUpdateListener(SelectionUpdateListener selectionUpdateListener) { @@ -263,6 +384,14 @@ public class SelectMultipleItemsBottomSheet extends MenuBottomSheetDialogFragmen this.onApplySelectionListener = onApplySelectionListener; } + public void setOnRadioButtonSelectListener(OnRadioButtonSelectListener onRadioButtonSelectListener) { + this.onRadioButtonSelectListener = onRadioButtonSelectListener; + } + + public void setSelectedItemsListener(SelectedItemsListener selectedItemsListener) { + this.selectedItemsListener = selectedItemsListener; + } + public interface SelectionUpdateListener { void onSelectionUpdate(); } @@ -271,6 +400,10 @@ public class SelectMultipleItemsBottomSheet extends MenuBottomSheetDialogFragmen void onSelectionApplied(List selectedItems); } + public interface OnRadioButtonSelectListener { + void onSelect(boolean leftButton); + } + public static class SelectableItem { private String title; private String description; @@ -281,6 +414,10 @@ public class SelectMultipleItemsBottomSheet extends MenuBottomSheetDialogFragmen this.title = title; } + public String getDescription() { + return description; + } + public void setDescription(String description) { this.description = description; } @@ -298,4 +435,27 @@ public class SelectMultipleItemsBottomSheet extends MenuBottomSheetDialogFragmen } } + @Override + protected void setupRightButton() { + super.setupRightButton(); + applyButtonTitle = rightButton.findViewById(R.id.button_text); + } + + @Override + protected void onRightBottomButtonClick() { + if (onApplySelectionListener != null) { + onApplySelectionListener.onSelectionApplied(selectedItems); + } + dismiss(); + } + + @Override + protected int getRightBottomButtonTextId() { + return R.string.shared_string_apply; + } + + @Override + protected boolean useVerticalButtons() { + return true; + } } diff --git a/OsmAnd/src/net/osmand/plus/base/bottomsheetmenu/BaseBottomSheetItem.java b/OsmAnd/src/net/osmand/plus/base/bottomsheetmenu/BaseBottomSheetItem.java index 1914756d21..f77fc8503f 100644 --- a/OsmAnd/src/net/osmand/plus/base/bottomsheetmenu/BaseBottomSheetItem.java +++ b/OsmAnd/src/net/osmand/plus/base/bottomsheetmenu/BaseBottomSheetItem.java @@ -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, diff --git a/OsmAnd/src/net/osmand/plus/download/DownloadActivityType.java b/OsmAnd/src/net/osmand/plus/download/DownloadActivityType.java index 071a856454..5c84250d07 100644 --- a/OsmAnd/src/net/osmand/plus/download/DownloadActivityType.java +++ b/OsmAnd/src/net/osmand/plus/download/DownloadActivityType.java @@ -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,13 @@ 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; +import static net.osmand.plus.download.MultipleIndexesUiHelper.getSRTMExt; public class DownloadActivityType { private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd.MM.yyyy", Locale.US); private static Map 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 +86,7 @@ public class DownloadActivityType { iconResource = R.drawable.ic_map; } - public int getStringResource(){ + public int getStringResource() { return stringResource; } @@ -101,7 +104,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 +123,17 @@ public class DownloadActivityType { public static Collection 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 +148,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 +164,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 +200,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 +221,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 +231,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 getSRTMExt(indexItem); } else if (WIKIPEDIA_FILE == this) { return IndexConstants.BINARY_WIKI_MAP_INDEX_EXT; } else if (WIKIVOYAGE_FILE == this) { @@ -249,9 +253,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 +284,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 += "®ion=" + encode(region); @@ -343,7 +347,7 @@ public class DownloadActivityType { } return ""; } - + public String getVisibleName(DownloadItem downloadItem, Context ctx, OsmandRegions osmandRegions, boolean includingParent) { if (this == VOICE_FILE) { String fileName = downloadItem.getFileName(); @@ -383,7 +387,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) || @@ -423,7 +427,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 + getSRTMExt(item); } if (this == WIKIPEDIA_FILE) { return baseNameWithoutVersion + IndexConstants.BINARY_WIKI_MAP_INDEX_EXT; @@ -487,7 +491,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; @@ -495,10 +499,20 @@ 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; } -} \ No newline at end of file + public static boolean isSRTMItem(Object item) { + if (item instanceof IndexItem) { + return ((IndexItem) item).getType() == SRTM_COUNTRY_FILE; + } else if (item instanceof DownloadItem) { + return ((DownloadItem) item).getType() == SRTM_COUNTRY_FILE; + } else if (item instanceof LocalIndexInfo) { + return ((LocalIndexInfo) item).getType() == SRTM_DATA; + } + return false; + } +} diff --git a/OsmAnd/src/net/osmand/plus/download/DownloadOsmandIndexesHelper.java b/OsmAnd/src/net/osmand/plus/download/DownloadOsmandIndexesHelper.java index d77245cecb..8af9f9eb6b 100644 --- a/OsmAnd/src/net/osmand/plus/download/DownloadOsmandIndexesHelper.java +++ b/OsmAnd/src/net/osmand/plus/download/DownloadOsmandIndexesHelper.java @@ -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 indexFiles = new ArrayList(); private String mapversion; - - private Comparator comparator = new Comparator(){ + + private Comparator comparator = new Comparator() { @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 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,15 @@ 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) { + if (tp == DownloadActivityType.SRTM_COUNTRY_FILE) { + log.debug("strUrl = " + strUrl); + } IndexItem it = tp.parseIndexItem(ctx, parser); - if(it != null) { + if (it != null) { result.add(it); } } else if ("osmand_regions".equals(parser.getName())) { @@ -226,7 +230,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 +243,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 +265,7 @@ public class DownloadOsmandIndexesHelper { return new DownloadEntry(assetName, destFile, dateModified); } - public String getDestFile(){ + public String getDestFile() { return destFile; } } diff --git a/OsmAnd/src/net/osmand/plus/download/DownloadResources.java b/OsmAnd/src/net/osmand/plus/download/DownloadResources.java index 40f4a7488a..7293d46659 100644 --- a/OsmAnd/src/net/osmand/plus/download/DownloadResources.java +++ b/OsmAnd/src/net/osmand/plus/download/DownloadResources.java @@ -264,7 +264,7 @@ public class DownloadResources extends DownloadResourceGroup { } private Map listWithAlternatives(final java.text.DateFormat dateFormat, File file, - final String ext, final Map files) { + final String ext, final Map files) { if (file.isDirectory()) { file.list(new FilenameFilter() { @Override @@ -518,7 +518,7 @@ public class DownloadResources extends DownloadResourceGroup { @Nullable private List collectIndexesOfType(@NonNull List regions, - @NonNull DownloadActivityType type) { + @NonNull DownloadActivityType type) { List collectedIndexes = new ArrayList<>(); for (WorldRegion region : regions) { List regionIndexes = getIndexItems(region); @@ -528,7 +528,6 @@ public class DownloadResources extends DownloadResourceGroup { if (index.getType() == type) { found = true; collectedIndexes.add(index); - break; } } } @@ -646,10 +645,10 @@ public class DownloadResources extends DownloadResourceGroup { } public static List findIndexItemsAt(OsmandApplication app, - List names, - DownloadActivityType type, - boolean includeDownloaded, - int limit) { + List names, + DownloadActivityType type, + boolean includeDownloaded, + int limit) { List res = new ArrayList<>(); OsmandRegions regions = app.getRegions(); DownloadIndexesThread downloadThread = app.getDownloadThread(); @@ -666,9 +665,9 @@ public class DownloadResources extends DownloadResourceGroup { } private static boolean isIndexItemDownloaded(DownloadIndexesThread downloadThread, - DownloadActivityType type, - WorldRegion downloadRegion, - List res) { + DownloadActivityType type, + WorldRegion downloadRegion, + List res) { List otherIndexItems = new ArrayList<>(downloadThread.getIndexes().getIndexItems(downloadRegion)); for (IndexItem indexItem : otherIndexItems) { @@ -681,7 +680,7 @@ public class DownloadResources extends DownloadResourceGroup { } private boolean doesListContainIndexWithType(List indexItems, - DownloadActivityType type) { + DownloadActivityType type) { if (indexItems != null) { for (IndexItem indexItem : indexItems) { if (indexItem.getType() == type) { @@ -693,9 +692,9 @@ public class DownloadResources extends DownloadResourceGroup { } private static boolean addIndexItem(DownloadIndexesThread downloadThread, - DownloadActivityType type, - WorldRegion downloadRegion, - List res) { + DownloadActivityType type, + WorldRegion downloadRegion, + List res) { List otherIndexItems = new ArrayList<>(downloadThread.getIndexes().getIndexItems(downloadRegion)); for (IndexItem indexItem : otherIndexItems) { diff --git a/OsmAnd/src/net/osmand/plus/download/MultipleIndexItem.java b/OsmAnd/src/net/osmand/plus/download/MultipleIndexItem.java index 5f5ff9c297..309f5210b9 100644 --- a/OsmAnd/src/net/osmand/plus/download/MultipleIndexItem.java +++ b/OsmAnd/src/net/osmand/plus/download/MultipleIndexItem.java @@ -1,5 +1,7 @@ package net.osmand.plus.download; +import android.content.Context; + import androidx.annotation.NonNull; import net.osmand.map.WorldRegion; @@ -9,13 +11,16 @@ import java.io.File; import java.util.ArrayList; import java.util.List; +import static net.osmand.plus.download.DownloadActivityType.SRTM_COUNTRY_FILE; +import static net.osmand.plus.download.MultipleIndexesUiHelper.isBaseSRTMItem; + public class MultipleIndexItem extends DownloadItem { private final List items; public MultipleIndexItem(@NonNull WorldRegion region, - @NonNull List items, - @NonNull DownloadActivityType type) { + @NonNull List items, + @NonNull DownloadActivityType type) { super(type); this.items = items; } @@ -110,6 +115,22 @@ public class MultipleIndexItem extends DownloadItem { return totalSizeMb; } + @NonNull + public String getSizeDescription(Context ctx, boolean baseSRTM) { + double totalSizeMb = 0.0d; + if (this.type == SRTM_COUNTRY_FILE) { + for (IndexItem item : items) { + if (item.hasActualDataToDownload()) { + if (baseSRTM && isBaseSRTMItem(item) || !baseSRTM && !isBaseSRTMItem(item)) { + totalSizeMb += item.getSizeToDownloadInMb(); + } + } + } + return getFormattedMb(ctx, totalSizeMb); + } + return getFormattedMb(ctx, getSizeToDownloadInMb()); + } + @Override public double getArchiveSizeMB() { double result = 0.0d; @@ -118,5 +139,4 @@ public class MultipleIndexItem extends DownloadItem { } return result; } - } diff --git a/OsmAnd/src/net/osmand/plus/download/MultipleIndexesUiHelper.java b/OsmAnd/src/net/osmand/plus/download/MultipleIndexesUiHelper.java index f84da0a74a..575507d7d8 100644 --- a/OsmAnd/src/net/osmand/plus/download/MultipleIndexesUiHelper.java +++ b/OsmAnd/src/net/osmand/plus/download/MultipleIndexesUiHelper.java @@ -1,28 +1,52 @@ package net.osmand.plus.download; +import android.content.Context; + import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; +import net.osmand.IndexConstants; import net.osmand.map.OsmandRegions; import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; +import net.osmand.plus.activities.LocalIndexInfo; import net.osmand.plus.base.SelectMultipleItemsBottomSheet; import net.osmand.plus.base.SelectMultipleItemsBottomSheet.OnApplySelectionListener; +import net.osmand.plus.base.SelectMultipleItemsBottomSheet.OnRadioButtonSelectListener; import net.osmand.plus.base.SelectMultipleItemsBottomSheet.SelectableItem; import net.osmand.plus.base.SelectMultipleItemsBottomSheet.SelectionUpdateListener; +import net.osmand.plus.helpers.enums.MetricsConstants; +import net.osmand.util.Algorithms; 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.download.DownloadActivityType.SRTM_COUNTRY_FILE; + 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) { + public static void showDialog(@NonNull DownloadItem item, + @NonNull AppCompatActivity activity, + @NonNull final OsmandApplication app, + @NonNull DateFormat dateFormat, + boolean showRemoteDate, + @NonNull final SelectItemsToDownloadListener listener) { + if (item.getType() == SRTM_COUNTRY_FILE) { + showSRTMDialog(item, activity, app, dateFormat, showRemoteDate, listener); + } else if (item instanceof MultipleIndexItem) { + showBaseDialog((MultipleIndexItem) item, activity, app, dateFormat, showRemoteDate, listener); + } + } + + public static void showBaseDialog(@NonNull MultipleIndexItem multipleIndexItem, + @NonNull AppCompatActivity activity, + @NonNull final OsmandApplication app, + @NonNull DateFormat dateFormat, + boolean showRemoteDate, + @NonNull final SelectItemsToDownloadListener listener) { List indexesToDownload = getIndexesToDownload(multipleIndexItem); List allItems = new ArrayList<>(); List selectedItems = new ArrayList<>(); @@ -30,12 +54,10 @@ public class MultipleIndexesUiHelper { 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); @@ -51,22 +73,102 @@ public class MultipleIndexesUiHelper { 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); + updateSize(app, dialog); } }); + dialog.setOnApplySelectionListener(getOnApplySelectionListener(listener)); + } - dialog.setOnApplySelectionListener(new OnApplySelectionListener() { + public static void showSRTMDialog(@NonNull final DownloadItem downloadItem, + @NonNull AppCompatActivity activity, + @NonNull final OsmandApplication app, + @NonNull final DateFormat dateFormat, + final boolean showRemoteDate, + @NonNull final SelectItemsToDownloadListener listener) { + List selectedItems = new ArrayList<>(); + final List leftItems = new ArrayList<>(); + final List rightItems = new ArrayList<>(); + List indexesToDownload = getIndexesToDownload(downloadItem); + boolean baseSRTM = isBaseSRTMMetricSystem(app); + + List allIndexes = new ArrayList<>(); + if (downloadItem instanceof MultipleIndexItem) { + allIndexes.addAll(((MultipleIndexItem) downloadItem).getAllIndexes()); + } else { + for (IndexItem indexItem : downloadItem.getRelatedGroup().getIndividualResources()) { + if (indexItem.getType() == SRTM_COUNTRY_FILE) { + allIndexes.add(indexItem); + } + } + } + + for (IndexItem indexItem : allIndexes) { + boolean baseItem = isBaseSRTMItem(indexItem); + SelectableItem selectableItem = new SelectableItem(); + selectableItem.setTitle(indexItem.getVisibleName(app, app.getRegions(), false)); + String size = indexItem.getSizeDescription(app); + size += " (" + getSRTMAbbrev(app, baseItem) + ")"; + 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); + + if (baseItem) { + leftItems.add(selectableItem); + } else { + rightItems.add(selectableItem); + } + + if (indexesToDownload.contains(indexItem) + && (baseSRTM && baseItem || !baseSRTM && !baseItem)) { + selectedItems.add(selectableItem); + } + } + + String addDescription = app.getString(isListDialog(app, leftItems, rightItems) + ? R.string.srtm_download_list_help_message : R.string.srtm_download_single_help_message); + final SelectMultipleItemsBottomSheet dialog = SelectMultipleItemsBottomSheet.showInstance( + activity, baseSRTM ? leftItems : rightItems, selectedItems, true, + addDescription, true, baseSRTM, + Algorithms.capitalizeFirstLetter(app.getString(R.string.shared_string_meters)), + Algorithms.capitalizeFirstLetter(app.getString(R.string.shared_string_feets))); + + dialog.setSelectionUpdateListener(new SelectionUpdateListener() { + @Override + public void onSelectionUpdate() { + updateSize(app, dialog); + } + }); + dialog.setOnApplySelectionListener(getOnApplySelectionListener(listener)); + dialog.setOnRadioButtonSelectListener(new OnRadioButtonSelectListener() { + @Override + public void onSelect(boolean leftButton) { + dialog.recreateList(leftButton ? leftItems : rightItems); + updateSize(app, dialog); + } + }); + dialog.setSelectedItemsListener(new SelectedItemsListener() { + @Override + public List createSelectedItems(List currentAllItems, boolean baseSRTM) { + List indexesToDownload = getIndexesToDownload(downloadItem); + List selectedItems = new ArrayList<>(); + + for (SelectableItem currentItem : currentAllItems) { + IndexItem indexItem = (IndexItem) currentItem.getObject(); + boolean baseItem = isBaseSRTMItem(indexItem); + if (indexesToDownload.contains(indexItem) + && (baseSRTM && baseItem || !baseSRTM && !baseItem)) { + selectedItems.add(currentItem); + } + } + return selectedItems; + } + }); + } + + private static OnApplySelectionListener getOnApplySelectionListener(final SelectItemsToDownloadListener listener) { + return new OnApplySelectionListener() { @Override public void onSelectionApplied(List selectedItems) { List indexItems = new ArrayList<>(); @@ -78,16 +180,70 @@ public class MultipleIndexesUiHelper { } listener.onItemsToDownloadSelected(indexItems); } - }); + }; } - private static List getIndexesToDownload(MultipleIndexItem multipleIndexItem) { - if (multipleIndexItem.hasActualDataToDownload()) { - // download left regions - return multipleIndexItem.getIndexesToDownload(); + private static void updateSize(OsmandApplication app, SelectMultipleItemsBottomSheet dialog) { + boolean isListDialog = dialog.isMultipleItem(); + dialog.setTitle(app.getString(isListDialog ? R.string.welmode_download_maps : R.string.srtm_unit_format)); + double sizeToDownload = getDownloadSizeInMb(dialog.getSelectedItems()); + String size = DownloadItem.getFormattedMb(app, sizeToDownload); + if (isListDialog) { + String total = app.getString(R.string.shared_string_total); + 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); + } + + private static boolean isListDialog(OsmandApplication app, + List leftItems, List rightItems) { + return (isBaseSRTMMetricSystem(app) ? leftItems : rightItems).size() > 1; + } + + public static String getSRTMAbbrev(Context context, boolean base) { + return context.getString(base ? R.string.m : R.string.foot); + } + + public static String getSRTMExt(IndexItem indexItem) { + return isBaseSRTMItem(indexItem) + ? IndexConstants.BINARY_SRTM_MAP_INDEX_EXT : IndexConstants.BINARY_SRTM_FEET_MAP_INDEX_EXT; + } + + public static boolean isBaseSRTMItem(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); + } + return false; + } + + public static boolean isBaseSRTMMetricSystem(OsmandApplication app) { + return app.getSettings().METRIC_SYSTEM.get() != MetricsConstants.MILES_AND_FEET; + } + + private static List getIndexesToDownload(DownloadItem downloadItem) { + if (downloadItem instanceof MultipleIndexItem) { + if (downloadItem.hasActualDataToDownload()) { + // download left regions + return ((MultipleIndexItem) downloadItem).getIndexesToDownload(); + } else { + // download all regions again + return ((MultipleIndexItem) downloadItem).getAllIndexes(); + } } else { - // download all regions again - return multipleIndexItem.getAllIndexes(); + List indexesToDownload = new ArrayList<>(); + for (IndexItem indexItem : downloadItem.getRelatedGroup().getIndividualResources()) { + if (indexItem.getType() == SRTM_COUNTRY_FILE && indexItem.hasActualDataToDownload()) { + indexesToDownload.add(indexItem); + } + } + return indexesToDownload; } } @@ -110,4 +266,7 @@ public class MultipleIndexesUiHelper { void onItemsToDownloadSelected(List items); } + public interface SelectedItemsListener { + List createSelectedItems(List currentAllItems, boolean base); + } } diff --git a/OsmAnd/src/net/osmand/plus/download/ui/ItemViewHolder.java b/OsmAnd/src/net/osmand/plus/download/ui/ItemViewHolder.java index a24e2c5b2a..767f116dda 100644 --- a/OsmAnd/src/net/osmand/plus/download/ui/ItemViewHolder.java +++ b/OsmAnd/src/net/osmand/plus/download/ui/ItemViewHolder.java @@ -51,8 +51,15 @@ 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.plus.download.DownloadActivityType.SRTM_COUNTRY_FILE; +import static net.osmand.plus.download.DownloadActivityType.isSRTMItem; +import static net.osmand.plus.download.MultipleIndexesUiHelper.getSRTMAbbrev; +import static net.osmand.plus.download.MultipleIndexesUiHelper.isBaseSRTMItem; +import static net.osmand.plus.download.MultipleIndexesUiHelper.isBaseSRTMMetricSystem; + public class ItemViewHolder { protected final TextView nameTextView; @@ -160,20 +167,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); } @@ -189,6 +196,8 @@ public class ItemViewHolder { } descrTextView.setTextColor(textColorSecondary); if (!isDownloading) { + boolean srtmItem = isSRTMItem(downloadItem); + boolean baseMetricSystem = isBaseSRTMMetricSystem(context.getMyApplication()); progressBar.setVisibility(View.GONE); descrTextView.setVisibility(View.VISIBLE); if (downloadItem instanceof CustomIndexItem && (((CustomIndexItem) downloadItem).getSubName(context) != null)) { @@ -207,31 +216,55 @@ public class ItemViewHolder { MultipleIndexItem item = (MultipleIndexItem) 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 allRegionsCountStr; + String leftToDownloadCountStr; + if (isSRTMItem(item)) { + List items = new ArrayList<>(); + for (IndexItem indexItem : item.getAllIndexes()) { + boolean baseItem = isBaseSRTMItem(indexItem); + if (baseMetricSystem && baseItem || !baseMetricSystem && !baseItem) { + items.add(indexItem); + } + } + allRegionsCountStr = String.valueOf(items.size()); + items.clear(); + for (IndexItem indexItem : item.getIndexesToDownload()) { + boolean baseItem = isBaseSRTMItem(indexItem); + if (!indexItem.isDownloaded() + && (baseMetricSystem && baseItem || !baseMetricSystem && !baseItem)) { + items.add(indexItem); + } + } + leftToDownloadCountStr = String.valueOf(items.size()); + } else { + allRegionsCountStr = String.valueOf(item.getAllIndexes().size()); + leftToDownloadCountStr = String.valueOf(item.getIndexesToDownload().size()); + } String header; String count; if (item.hasActualDataToDownload()) { if (!item.isDownloaded()) { header = allRegionsHeader; - count = leftToDownloadCount; + count = leftToDownloadCountStr; } else { header = regionsHeader; count = String.format( context.getString(R.string.ltr_or_rtl_combine_via_slash), - leftToDownloadCount, - allRegionsCount); + leftToDownloadCountStr, + allRegionsCountStr); } } else { header = allRegionsHeader; - count = allRegionsCount; + count = allRegionsCountStr; + } + String fullDescription = context.getString(R.string.ltr_or_rtl_combine_via_colon, header, count); + if (srtmItem) { + fullDescription += " (" + getSRTMAbbrev(context, baseMetricSystem) + ")"; } - String fullDescription = - context.getString(R.string.ltr_or_rtl_combine_via_colon, header, count); if (item.hasActualDataToDownload()) { fullDescription = context.getString( - R.string.ltr_or_rtl_combine_via_bold_point, fullDescription, - item.getSizeDescription(context)); + R.string.ltr_or_rtl_combine_via_bold_point, fullDescription, srtmItem + ? item.getSizeDescription(context, baseMetricSystem) : item.getSizeDescription(context)); } descrTextView.setText(fullDescription); } else { @@ -239,6 +272,9 @@ public class ItemViewHolder { String pattern = context.getString(R.string.ltr_or_rtl_combine_via_bold_point); String type = item.getType().getString(context); String size = item.getSizeDescription(context); + if (srtmItem) { + size += " (" + getSRTMAbbrev(context, isBaseSRTMItem(item)) + ")"; + } String date = item.getDate(dateFormat, showRemoteDate); String fullDescription = String.format(pattern, size, date); if (showTypeInDesc) { @@ -254,14 +290,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); } @@ -302,7 +338,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 { @@ -318,7 +354,7 @@ public class ItemViewHolder { private int getDownloadActionIconId(@NonNull DownloadItem item) { return item instanceof MultipleIndexItem ? R.drawable.ic_action_multi_download : - R.drawable.ic_action_import; + R.drawable.ic_action_gsave_dark; } @SuppressLint("DefaultLocale") @@ -389,13 +425,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 +442,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 +491,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,15 +513,15 @@ public class ItemViewHolder { } private void startDownload(DownloadItem item) { - if (item instanceof MultipleIndexItem) { - selectIndexesToDownload((MultipleIndexItem) item); + if (item instanceof MultipleIndexItem || item.getType() == SRTM_COUNTRY_FILE) { + selectIndexesToDownload(item); } else if (item instanceof IndexItem) { IndexItem indexItem = (IndexItem) item; context.startDownload(indexItem); } } - private void selectIndexesToDownload(MultipleIndexItem item) { + private void selectIndexesToDownload(DownloadItem item) { OsmandApplication app = context.getMyApplication(); MultipleIndexesUiHelper.showDialog(item, context, app, dateFormat, showRemoteDate, new SelectItemsToDownloadListener() { @@ -498,7 +535,7 @@ public class ItemViewHolder { } private void confirmRemove(@NonNull final DownloadItem downloadItem, - @NonNull final List downloadedFiles) { + @NonNull final List downloadedFiles) { OsmandApplication app = context.getMyApplication(); AlertDialog.Builder confirm = new AlertDialog.Builder(context); @@ -526,7 +563,7 @@ public class ItemViewHolder { } private void remove(@NonNull LocalIndexType type, - @NonNull List filesToDelete) { + @NonNull List filesToDelete) { OsmandApplication app = context.getMyApplication(); LocalIndexOperationTask removeTask = new LocalIndexOperationTask( context, diff --git a/OsmAnd/src/net/osmand/plus/download/ui/LocalIndexesFragment.java b/OsmAnd/src/net/osmand/plus/download/ui/LocalIndexesFragment.java index 3b259ab241..f67f4de704 100644 --- a/OsmAnd/src/net/osmand/plus/download/ui/LocalIndexesFragment.java +++ b/OsmAnd/src/net/osmand/plus/download/ui/LocalIndexesFragment.java @@ -74,6 +74,10 @@ import java.util.List; import java.util.Map; import java.util.Set; +import static net.osmand.plus.download.DownloadActivityType.isSRTMItem; +import static net.osmand.plus.download.MultipleIndexesUiHelper.getSRTMAbbrev; +import static net.osmand.plus.download.MultipleIndexesUiHelper.isBaseSRTMItem; + public class LocalIndexesFragment extends OsmandExpandableListFragment implements DownloadEvents, OnMapSourceUpdateListener, RenameCallback { private LoadLocalIndexTask asyncLoader; @@ -351,10 +355,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 +374,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 +423,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 { @@ -878,8 +882,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 +967,8 @@ 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() && (child.getFileName().endsWith(IndexConstants.BINARY_SRTM_MAP_INDEX_EXT) + || child.getFileName().endsWith(IndexConstants.BINARY_SRTM_FEET_MAP_INDEX_EXT))) { return ctx.getString(R.string.download_srtm_maps); } return ""; @@ -1029,6 +1034,10 @@ public class LocalIndexesFragment extends OsmandExpandableListFragment implement builder.append(AndroidUtils.formatSize(ctx, child.getSize() * 1024l)); } + if (isSRTMItem(child)) { + builder.append(" (").append(getSRTMAbbrev(ctx, isBaseSRTMItem(child))).append(")"); + } + if (!Algorithms.isEmpty(child.getDescription())) { if (builder.length() > 0) { builder.append(" • "); @@ -1150,5 +1159,4 @@ public class LocalIndexesFragment extends OsmandExpandableListFragment implement private DownloadActivity getDownloadActivity() { return (DownloadActivity) getActivity(); } - } diff --git a/OsmAnd/src/net/osmand/plus/resources/ResourceManager.java b/OsmAnd/src/net/osmand/plus/resources/ResourceManager.java index e48e37878a..33bddc97a6 100644 --- a/OsmAnd/src/net/osmand/plus/resources/ResourceManager.java +++ b/OsmAnd/src/net/osmand/plus/resources/ResourceManager.java @@ -78,11 +78,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 +91,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 tilesCacheList = new ArrayList<>(); private BitmapTilesCache bitmapTilesCache; @@ -115,21 +115,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 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 +174,7 @@ public class ResourceManager { } initialReader = null; } - + public boolean isClosed() { return initialReader == null; } @@ -189,7 +190,7 @@ public class ResourceManager { public void setUseForRouting(boolean useForRouting) { this.useForRouting = useForRouting; } - + public boolean isUseForRouting() { return useForRouting; } @@ -202,34 +203,32 @@ public class ResourceManager { this.useForPublicTransport = useForPublicTransport; } } - + protected final Map fileReaders = new ConcurrentHashMap(); - - + private final Map addressMap = new ConcurrentHashMap(); - protected final Map amenityRepositories = new ConcurrentHashMap(); -// protected final Map routingMapFiles = new ConcurrentHashMap(); + protected final Map amenityRepositories = new ConcurrentHashMap(); + // protected final Map routingMapFiles = new ConcurrentHashMap(); protected final Map transportRepositories = new ConcurrentHashMap(); protected final Map travelRepositories = new ConcurrentHashMap(); protected final Map indexFileNames = new ConcurrentHashMap(); protected final Map basemapFileNames = new ConcurrentHashMap(); - - + 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 +270,7 @@ public class ResourceManager { public MapTileDownloader getMapTileDownloader() { return tileDownloader; } - + public HandlerThread getRenderingBufferImageThread() { return renderingBufferImageThread; } @@ -293,17 +292,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 +322,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 +331,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 +375,7 @@ public class ResourceManager { ////////////////////////////////////////////// Working with indexes //////////////////////////////////////////////// - public List reloadIndexesOnStart(AppInitializer progress, List warnings){ + public List reloadIndexesOnStart(AppInitializer progress, List warnings) { close(); // check we have some assets to copy to sdcard warnings.addAll(checkAssets(progress, false)); @@ -429,7 +428,7 @@ public class ResourceManager { return warnings; } - public List indexFontFiles(IProgress progress){ + public List indexFontFiles(IProgress progress) { File file = context.getAppPath(IndexConstants.FONT_INDEX_DIR); file.mkdirs(); List warnings = new ArrayList(); @@ -473,10 +472,10 @@ public class ResourceManager { log.error("Error while loading tts files from assets", e); } } - + public List 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 +508,7 @@ public class ResourceManager { } return Collections.emptyList(); } - + private void copyRegionsBoundaries() { try { File file = context.getAppPath("regions.ocbf"); @@ -522,7 +521,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 +539,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 assetEntries = DownloadOsmandIndexesHelper.getBundledAssets(assetManager); for (AssetEntry asset : assetEntries) { @@ -581,7 +581,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 +593,9 @@ public class ResourceManager { } private List collectFiles(File dir, String ext, List 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 +606,10 @@ public class ResourceManager { } return files; } - - - + private void renameRoadsFiles(ArrayList files, File roadsPath) { Iterator 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 +630,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 +643,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 +701,8 @@ 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 = f.getName().contains(IndexConstants.BINARY_SRTM_MAP_INDEX_EXT) + || f.getName().contains(IndexConstants.BINARY_SRTM_FEET_MAP_INDEX_EXT); 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>> it = toAddPoiTypes.entrySet().iterator(); - while(it.hasNext()) { + while (it.hasNext()) { Entry> 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 getAmenityRepositories() { @@ -872,7 +871,7 @@ public class ResourceManager { } public List searchAmenities(SearchPoiTypeFilter filter, - double topLatitude, double leftLongitude, double bottomLatitude, double rightLongitude, int zoom, final ResultMatcher matcher) { + double topLatitude, double leftLongitude, double bottomLatitude, double rightLongitude, int zoom, final ResultMatcher matcher) { final List amenities = new ArrayList(); searchAmenitiesInProgress = true; try { @@ -901,8 +900,8 @@ public class ResourceManager { return amenities; } - public List searchAmenitiesOnThePath(List locations, double radius, SearchPoiTypeFilter filter, - ResultMatcher matcher) { + public List searchAmenitiesOnThePath(List locations, double radius, SearchPoiTypeFilter filter, + ResultMatcher matcher) { searchAmenitiesInProgress = true; final List amenities = new ArrayList(); 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 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 searchAmenitiesByName(String searchQuery, - double topLatitude, double leftLongitude, double bottomLatitude, double rightLongitude, - double lat, double lon, ResultMatcher matcher) { + double topLatitude, double leftLongitude, double bottomLatitude, double rightLongitude, + double lat, double lon, ResultMatcher matcher) { List amenities = new ArrayList(); List list = new ArrayList(); 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> searchAmenityCategoriesByName(String searchQuery, double lat, double lon) { Map> map = new LinkedHashMap>(); 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 getAddressRepositories(){ + + public Collection getAddressRepositories() { return addressMap.values(); } - + public Collection getFileReaders() { List fileNames = new ArrayList<>(fileReaders.keySet()); Collections.sort(fileNames, Algorithms.getStringVersionComparator()); @@ -1039,8 +1037,7 @@ public class ResourceManager { } return res; } - - + ////////////////////////////////////////////// Working with transport //////////////////////////////////////////////// private List getTransportRepositories(double topLat, double leftLon, double bottomLat, double rightLon) { @@ -1076,7 +1073,7 @@ public class ResourceManager { public List getRoutesForStop(TransportStop stop) { List 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 fileReaders = getFileReaders(); List 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 getIndexFileNames() { return new LinkedHashMap(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; } diff --git a/OsmAnd/src/net/osmand/plus/settings/datastorage/DataStorageHelper.java b/OsmAnd/src/net/osmand/plus/settings/datastorage/DataStorageHelper.java index 67fd73897e..bd424210f9 100644 --- a/OsmAnd/src/net/osmand/plus/settings/datastorage/DataStorageHelper.java +++ b/OsmAnd/src/net/osmand/plus/settings/datastorage/DataStorageHelper.java @@ -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)) @@ -302,9 +302,9 @@ public class DataStorageHelper { } public DirectoryItem createDirectory(@NonNull String relativePath, - boolean processInternalDirectories, - CheckingType checkingType, - boolean addUnmatchedToOtherMemory) { + boolean processInternalDirectories, + CheckingType checkingType, + boolean addUnmatchedToOtherMemory) { String path = app.getAppPath(relativePath).getAbsolutePath(); return new DirectoryItem(path, processInternalDirectories, checkingType, addUnmatchedToOtherMemory); } @@ -323,7 +323,7 @@ public class DataStorageHelper { public interface UpdateMemoryInfoUIAdapter { void onMemoryInfoUpdate(); - + void onFinishUpdating(String tag); }