Merge pull request #8856 from osmandapp/dynamic_downloads
Dynamic downloads
This commit is contained in:
commit
764f413196
3 changed files with 168 additions and 4 deletions
|
@ -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<SuggestedDownloadItem> items) {
|
public void updateSuggestedDownloads(List<SuggestedDownloadItem> items) {
|
||||||
|
|
|
@ -6,6 +6,8 @@ import androidx.annotation.ColorInt;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import net.osmand.AndroidNetworkUtils;
|
||||||
|
import net.osmand.AndroidNetworkUtils.OnRequestResultListener;
|
||||||
import net.osmand.JsonUtils;
|
import net.osmand.JsonUtils;
|
||||||
import net.osmand.PlatformUtil;
|
import net.osmand.PlatformUtil;
|
||||||
import net.osmand.map.WorldRegion;
|
import net.osmand.map.WorldRegion;
|
||||||
|
@ -24,6 +26,7 @@ import java.io.File;
|
||||||
import java.text.DecimalFormat;
|
import java.text.DecimalFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
@ -38,6 +41,9 @@ public class CustomRegion extends WorldRegion {
|
||||||
private String subfolder;
|
private String subfolder;
|
||||||
|
|
||||||
private JSONArray downloadItemsJson;
|
private JSONArray downloadItemsJson;
|
||||||
|
private JSONArray dynamicItemsJson;
|
||||||
|
|
||||||
|
private DynamicDownloadItems dynamicDownloadItems;
|
||||||
|
|
||||||
private DownloadDescriptionInfo descriptionInfo;
|
private DownloadDescriptionInfo descriptionInfo;
|
||||||
|
|
||||||
|
@ -102,6 +108,12 @@ public class CustomRegion extends WorldRegion {
|
||||||
region.headers = JsonUtils.getLocalizedMapFromJson("header", object);
|
region.headers = JsonUtils.getLocalizedMapFromJson("header", object);
|
||||||
|
|
||||||
region.downloadItemsJson = object.optJSONArray("items");
|
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);
|
String headerColor = object.optString("header-color", null);
|
||||||
try {
|
try {
|
||||||
|
@ -130,16 +142,26 @@ public class CustomRegion extends WorldRegion {
|
||||||
jsonObject.putOpt("description", descriptionInfo.toJson());
|
jsonObject.putOpt("description", descriptionInfo.toJson());
|
||||||
}
|
}
|
||||||
jsonObject.putOpt("items", downloadItemsJson);
|
jsonObject.putOpt("items", downloadItemsJson);
|
||||||
|
jsonObject.putOpt("dynamic-items", dynamicItemsJson);
|
||||||
|
if (dynamicDownloadItems != null) {
|
||||||
|
jsonObject.putOpt("items-url", dynamicDownloadItems.toJson());
|
||||||
|
}
|
||||||
return jsonObject;
|
return jsonObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<IndexItem> loadIndexItems() {
|
public List<IndexItem> loadIndexItems() {
|
||||||
List<IndexItem> items = new ArrayList<>();
|
List<IndexItem> items = new ArrayList<>();
|
||||||
if (downloadItemsJson != null) {
|
items.addAll(loadIndexItems(downloadItemsJson));
|
||||||
|
items.addAll(loadIndexItems(dynamicItemsJson));
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<IndexItem> loadIndexItems(JSONArray itemsJson) {
|
||||||
|
List<IndexItem> items = new ArrayList<>();
|
||||||
|
if (itemsJson != null) {
|
||||||
try {
|
try {
|
||||||
for (int i = 0; i < downloadItemsJson.length(); i++) {
|
for (int i = 0; i < itemsJson.length(); i++) {
|
||||||
JSONObject itemJson = downloadItemsJson.getJSONObject(i);
|
JSONObject itemJson = itemsJson.getJSONObject(i);
|
||||||
|
|
||||||
long timestamp = itemJson.optLong("timestamp") * 1000;
|
long timestamp = itemJson.optLong("timestamp") * 1000;
|
||||||
long contentSize = itemJson.optLong("contentSize");
|
long contentSize = itemJson.optLong("contentSize");
|
||||||
|
@ -182,4 +204,131 @@ public class CustomRegion extends WorldRegion {
|
||||||
}
|
}
|
||||||
return items;
|
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<String> 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<String> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -851,6 +851,9 @@ public class ImportHelper {
|
||||||
((ProfileSettingsItem) item).applyAdditionalPrefs();
|
((ProfileSettingsItem) item).applyAdditionalPrefs();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!Algorithms.isEmpty(plugin.getDownloadMaps())) {
|
||||||
|
app.getDownloadThread().runReloadIndexFilesSilent();
|
||||||
|
}
|
||||||
if (activity != null) {
|
if (activity != null) {
|
||||||
plugin.onInstall(app, activity);
|
plugin.onInstall(app, activity);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue