diff --git a/OsmAnd/src/net/osmand/plus/CustomOsmandPlugin.java b/OsmAnd/src/net/osmand/plus/CustomOsmandPlugin.java index 9b25c4accc..238d80c952 100644 --- a/OsmAnd/src/net/osmand/plus/CustomOsmandPlugin.java +++ b/OsmAnd/src/net/osmand/plus/CustomOsmandPlugin.java @@ -415,6 +415,18 @@ public class CustomOsmandPlugin extends OsmandPlugin { } } } + for (WorldRegion region : customRegions) { + loadSubregionIndexItems(region); + } + } + + private void loadSubregionIndexItems(WorldRegion region) { + if (region instanceof CustomRegion) { + ((CustomRegion) region).loadDynamicIndexItems(app); + } + for (WorldRegion subregion : region.getSubregions()) { + loadSubregionIndexItems(subregion); + } } public void updateSuggestedDownloads(List items) { diff --git a/OsmAnd/src/net/osmand/plus/CustomRegion.java b/OsmAnd/src/net/osmand/plus/CustomRegion.java index fc433a7a5e..c2357f1c82 100644 --- a/OsmAnd/src/net/osmand/plus/CustomRegion.java +++ b/OsmAnd/src/net/osmand/plus/CustomRegion.java @@ -6,6 +6,8 @@ import androidx.annotation.ColorInt; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import net.osmand.AndroidNetworkUtils; +import net.osmand.AndroidNetworkUtils.OnRequestResultListener; import net.osmand.JsonUtils; import net.osmand.PlatformUtil; import net.osmand.map.WorldRegion; @@ -24,6 +26,7 @@ import java.io.File; import java.text.DecimalFormat; import java.util.ArrayList; import java.util.HashMap; +import java.util.Iterator; import java.util.List; import java.util.Map; @@ -38,6 +41,9 @@ public class CustomRegion extends WorldRegion { private String subfolder; private JSONArray downloadItemsJson; + private JSONArray dynamicItemsJson; + + private DynamicDownloadItems dynamicDownloadItems; private DownloadDescriptionInfo descriptionInfo; @@ -102,6 +108,12 @@ public class CustomRegion extends WorldRegion { region.headers = JsonUtils.getLocalizedMapFromJson("header", object); region.downloadItemsJson = object.optJSONArray("items"); + region.dynamicItemsJson = object.optJSONArray("dynamic-items"); + + JSONObject urlItemsJson = object.optJSONObject("items-url"); + if (urlItemsJson != null) { + region.dynamicDownloadItems = DynamicDownloadItems.fromJson(urlItemsJson); + } String headerColor = object.optString("header-color", null); try { @@ -130,16 +142,26 @@ public class CustomRegion extends WorldRegion { jsonObject.putOpt("description", descriptionInfo.toJson()); } jsonObject.putOpt("items", downloadItemsJson); - + jsonObject.putOpt("dynamic-items", dynamicItemsJson); + if (dynamicDownloadItems != null) { + jsonObject.putOpt("items-url", dynamicDownloadItems.toJson()); + } return jsonObject; } public List loadIndexItems() { List items = new ArrayList<>(); - if (downloadItemsJson != null) { + items.addAll(loadIndexItems(downloadItemsJson)); + items.addAll(loadIndexItems(dynamicItemsJson)); + return items; + } + + private List loadIndexItems(JSONArray itemsJson) { + List items = new ArrayList<>(); + if (itemsJson != null) { try { - for (int i = 0; i < downloadItemsJson.length(); i++) { - JSONObject itemJson = downloadItemsJson.getJSONObject(i); + for (int i = 0; i < itemsJson.length(); i++) { + JSONObject itemJson = itemsJson.getJSONObject(i); long timestamp = itemJson.optLong("timestamp") * 1000; long contentSize = itemJson.optLong("contentSize"); @@ -182,4 +204,131 @@ public class CustomRegion extends WorldRegion { } return items; } + + void loadDynamicIndexItems(final OsmandApplication app) { + if (dynamicItemsJson == null && dynamicDownloadItems != null + && !Algorithms.isEmpty(dynamicDownloadItems.url) + && app.getSettings().isInternetConnectionAvailable()) { + OnRequestResultListener resultListener = new OnRequestResultListener() { + @Override + public void onResult(String result) { + if (!Algorithms.isEmpty(result)) { + if ("json".equalsIgnoreCase(dynamicDownloadItems.format)) { + dynamicItemsJson = mapJsonItems(result); + } + } + } + }; + + AndroidNetworkUtils.sendRequestAsync(app, dynamicDownloadItems.getUrl(), null, + null, false, false, resultListener); + } + } + + private JSONArray mapJsonItems(String jsonStr) { + try { + JSONObject json = new JSONObject(jsonStr); + JSONArray jsonArray = json.optJSONArray(dynamicDownloadItems.itemsPath); + if (jsonArray != null) { + JSONArray itemsJson = new JSONArray(); + for (int i = 0; i < jsonArray.length(); i++) { + JSONObject jsonObject = jsonArray.getJSONObject(i); + JSONObject itemJson = mapDynamicJsonItem(jsonObject, dynamicDownloadItems.mapping); + + itemsJson.put(itemJson); + } + return itemsJson; + } + } catch (JSONException e) { + LOG.error(e); + } + return null; + } + + private JSONObject mapDynamicJsonItem(JSONObject jsonObject, JSONObject mapping) throws JSONException { + JSONObject itemJson = new JSONObject(); + for (Iterator it = mapping.keys(); it.hasNext(); ) { + String key = it.next(); + Object value = checkMappingValue(mapping.opt(key), jsonObject); + itemJson.put(key, value); + } + return itemJson; + } + + private Object checkMappingValue(Object value, JSONObject json) throws JSONException { + if (value instanceof String) { + String key = (String) value; + int index = key.indexOf("@"); + if (index != -1) { + key = key.substring(index + 1); + } + return json.opt(key); + } else if (value instanceof JSONObject) { + JSONObject checkedJsonObject = (JSONObject) value; + JSONObject objectJson = new JSONObject(); + + for (Iterator iterator = checkedJsonObject.keys(); iterator.hasNext(); ) { + String key = iterator.next(); + Object checkedValue = checkMappingValue(checkedJsonObject.opt(key), json); + objectJson.put(key, checkedValue); + } + return objectJson; + } else if (value instanceof JSONArray) { + JSONArray checkedJsonArray = new JSONArray(); + JSONArray jsonArray = (JSONArray) value; + + for (int i = 0; i < jsonArray.length(); i++) { + Object checkedValue = checkMappingValue(jsonArray.opt(i), json); + checkedJsonArray.put(i, checkedValue); + } + return checkedJsonArray; + } + return value; + } + + public static class DynamicDownloadItems { + + private String url; + private String format; + private String itemsPath; + private JSONObject mapping; + + public String getUrl() { + return url; + } + + public String getFormat() { + return format; + } + + public String getItemsPath() { + return itemsPath; + } + + public JSONObject getMapping() { + return mapping; + } + + public static DynamicDownloadItems fromJson(JSONObject object) { + DynamicDownloadItems dynamicDownloadItems = new DynamicDownloadItems(); + + dynamicDownloadItems.url = object.optString("url", null); + dynamicDownloadItems.format = object.optString("format", null); + dynamicDownloadItems.itemsPath = object.optString("items-path", null); + dynamicDownloadItems.mapping = object.optJSONObject("mapping"); + + return dynamicDownloadItems; + } + + public JSONObject toJson() throws JSONException { + JSONObject jsonObject = new JSONObject(); + + jsonObject.putOpt("url", url); + jsonObject.putOpt("format", format); + jsonObject.putOpt("items-path", itemsPath); + jsonObject.putOpt("mapping", mapping); + + return jsonObject; + } + } } \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/helpers/ImportHelper.java b/OsmAnd/src/net/osmand/plus/helpers/ImportHelper.java index f20b51dfc2..8a29d2ea1f 100644 --- a/OsmAnd/src/net/osmand/plus/helpers/ImportHelper.java +++ b/OsmAnd/src/net/osmand/plus/helpers/ImportHelper.java @@ -851,6 +851,9 @@ public class ImportHelper { ((ProfileSettingsItem) item).applyAdditionalPrefs(); } } + if (!Algorithms.isEmpty(plugin.getDownloadMaps())) { + app.getDownloadThread().runReloadIndexFilesSilent(); + } if (activity != null) { plugin.onInstall(app, activity); }