From 1b33de3543c60d2cb4fa09d7f37f1f97b735427d Mon Sep 17 00:00:00 2001 From: Emux Date: Tue, 11 Mar 2025 11:15:55 +0200 Subject: [PATCH] Online tiles support multiple servers --- docs/Changelog.md | 1 + .../src/org/oscim/test/BitmapTileTest.java | 20 ++++++++--- .../oscim/tiling/source/UrlTileSource.java | 36 ++++++++++--------- .../tiling/source/bitmap/DefaultSources.java | 2 +- 4 files changed, 38 insertions(+), 21 deletions(-) diff --git a/docs/Changelog.md b/docs/Changelog.md index 824c7687f..897385d04 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -4,6 +4,7 @@ - Hillshading from HGT digital elevation model data [#1189](https://github.com/mapsforge/vtm/pull/1189) - `vtm-hillshading` module +- Online tiles support multiple servers [#1196](https://github.com/mapsforge/vtm/pull/1196) - Motorider map theme improvements [#1183](https://github.com/mapsforge/vtm/issues/1183) - Biker map theme improvements [#1192](https://github.com/mapsforge/vtm/issues/1192) - Rename `MapDatabase` to `MapFile` [#1184](https://github.com/mapsforge/vtm/pull/1184) diff --git a/vtm-playground/src/org/oscim/test/BitmapTileTest.java b/vtm-playground/src/org/oscim/test/BitmapTileTest.java index 4a74c17db..5f47098f0 100644 --- a/vtm-playground/src/org/oscim/test/BitmapTileTest.java +++ b/vtm-playground/src/org/oscim/test/BitmapTileTest.java @@ -20,7 +20,9 @@ import org.oscim.gdx.GdxMapApp; import org.oscim.layers.tile.bitmap.BitmapTileLayer; import org.oscim.renderer.MapRenderer; +import org.oscim.tiling.source.OkHttpEngine; import org.oscim.tiling.source.UrlTileSource; +import org.oscim.tiling.source.bitmap.BitmapTileSource; import org.oscim.tiling.source.bitmap.DefaultSources; import java.util.Collections; @@ -36,7 +38,9 @@ protected boolean onKeyDown(int keycode) { mMap.layers().remove(mShaded); mShaded = null; mMap.layers().remove(mLayer); - UrlTileSource tileSource = DefaultSources.OPENSTREETMAP.build(); + UrlTileSource tileSource = DefaultSources.OPENSTREETMAP + .httpFactory(new OkHttpEngine.OkHttpFactory()) + .build(); tileSource.setHttpRequestHeaders(Collections.singletonMap("User-Agent", "vtm-playground")); mLayer = new BitmapTileLayer(mMap, tileSource); mMap.layers().add(mLayer); @@ -46,7 +50,10 @@ protected boolean onKeyDown(int keycode) { mMap.layers().remove(mShaded); mShaded = null; mMap.layers().remove(mLayer); - mLayer = new BitmapTileLayer(mMap, DefaultSources.STAMEN_TONER.build()); + final BitmapTileSource tileSource = DefaultSources.STAMEN_TONER + .httpFactory(new OkHttpEngine.OkHttpFactory()) + .build(); + mLayer = new BitmapTileLayer(mMap, tileSource); mMap.layers().add(mLayer); mMap.clearMap(); return true; @@ -55,7 +62,10 @@ protected boolean onKeyDown(int keycode) { mMap.layers().remove(mShaded); mShaded = null; } else { - mShaded = new BitmapTileLayer(mMap, DefaultSources.HIKEBIKE_HILLSHADE.build()); + final BitmapTileSource tileSource = DefaultSources.HIKEBIKE_HILLSHADE + .httpFactory(new OkHttpEngine.OkHttpFactory()) + .build(); + mShaded = new BitmapTileLayer(mMap, tileSource); mMap.layers().add(mShaded); } mMap.clearMap(); @@ -69,7 +79,9 @@ protected boolean onKeyDown(int keycode) { public void createLayers() { MapRenderer.setBackgroundColor(0xff888888); - UrlTileSource tileSource = DefaultSources.OPENSTREETMAP.build(); + UrlTileSource tileSource = DefaultSources.OPENSTREETMAP + .httpFactory(new OkHttpEngine.OkHttpFactory()) + .build(); tileSource.setHttpRequestHeaders(Collections.singletonMap("User-Agent", "vtm-playground")); mLayer = new BitmapTileLayer(mMap, tileSource); mMap.layers().add(mLayer); diff --git a/vtm/src/org/oscim/tiling/source/UrlTileSource.java b/vtm/src/org/oscim/tiling/source/UrlTileSource.java index 4dde3adbb..33fb8d411 100644 --- a/vtm/src/org/oscim/tiling/source/UrlTileSource.java +++ b/vtm/src/org/oscim/tiling/source/UrlTileSource.java @@ -27,12 +27,13 @@ import java.net.URL; import java.util.Collections; import java.util.Map; +import java.util.Random; public abstract class UrlTileSource extends TileSource { public abstract static class Builder> extends TileSource.Builder { protected String tilePath; - protected String url; + protected String[] urls; private HttpEngine.Factory engineFactory; private String keyName = "key"; private String apiKey; @@ -41,7 +42,7 @@ protected Builder() { } protected Builder(String url, String tilePath) { - this.url = url; + this.urls = new String[]{url}; this.tilePath = tilePath; } @@ -66,8 +67,8 @@ public T tilePath(String tilePath) { return self(); } - public T url(String url) { - this.url = url; + public T url(String... urls) { + this.urls = urls; return self(); } @@ -79,7 +80,8 @@ public T httpFactory(HttpEngine.Factory factory) { } public static final TileUrlFormatter URL_FORMATTER = new DefaultTileUrlFormatter(); - private final URL mUrl; + private final Random mRandom = new Random(); + private final URL[] mUrls; private final String[] mTilePath; private HttpEngine.Factory mHttpFactory; @@ -96,7 +98,7 @@ protected UrlTileSource(Builder builder) { super(builder); mKeyName = builder.keyName; mApiKey = builder.apiKey; - mUrl = makeUrl(builder.url); + mUrls = makeUrl(builder.urls); mTilePath = builder.tilePath.split("\\{|\\}"); mHttpFactory = builder.engineFactory; } @@ -107,7 +109,7 @@ protected UrlTileSource(String urlString, String tilePath) { protected UrlTileSource(String urlString, String tilePath, int zoomMin, int zoomMax) { super(zoomMin, zoomMax); - mUrl = makeUrl(urlString); + mUrls = makeUrl(urlString); mTilePath = makeTilePath(tilePath); } @@ -118,14 +120,16 @@ private String[] makeTilePath(String tilePath) { return tilePath.split("\\{|\\}"); } - private URL makeUrl(String urlString) { - URL url; - try { - url = new URL(urlString); - } catch (MalformedURLException e) { - throw new IllegalArgumentException(e); + private URL[] makeUrl(String... urlStrings) { + URL[] urls = new URL[urlStrings.length]; + for (int i = 0; i < urlStrings.length; i++) { + try { + urls[i] = new URL(urlStrings[i]); + } catch (MalformedURLException e) { + throw new IllegalArgumentException(e); + } } - return url; + return urls; } @Override @@ -143,12 +147,12 @@ public void setApiKey(String apiKey) { } public URL getUrl() { - return mUrl; + return mUrls[mRandom.nextInt(mUrls.length)]; } public String getTileUrl(Tile tile) { StringBuilder sb = new StringBuilder(); - sb.append(mUrl).append(mTileUrlFormatter.formatTilePath(this, tile)); + sb.append(getUrl()).append(mTileUrlFormatter.formatTilePath(this, tile)); if (mApiKey != null) { sb.append("?").append(mKeyName).append("=").append(mApiKey); } diff --git a/vtm/src/org/oscim/tiling/source/bitmap/DefaultSources.java b/vtm/src/org/oscim/tiling/source/bitmap/DefaultSources.java index df8fdda7a..8e0ebbd5e 100644 --- a/vtm/src/org/oscim/tiling/source/bitmap/DefaultSources.java +++ b/vtm/src/org/oscim/tiling/source/bitmap/DefaultSources.java @@ -37,7 +37,7 @@ public class DefaultSources { // Requires a valid HTTP User-Agent identifying application // https://operations.osmfoundation.org/policies/tiles/ public static Builder OPENSTREETMAP = BitmapTileSource.builder() - .url("https://tile.openstreetmap.org") + .url("https://a.tile.openstreetmap.org", "https://b.tile.openstreetmap.org", "https://c.tile.openstreetmap.org") .zoomMax(18); public static Builder STAMEN_TONER = BitmapTileSource.builder()