oleg97
oleg97

Reputation: 87

Gluon Maps doesn't load the map and throws an exception

When using Gluon Maps on android the actual map doesn't get loaded. Instead the empty white space is shown, and I can see this in logs:

05-31 14:20:34.041 E/CachedOsmTileRetriever(18834): null
05-31 14:20:34.041 E/CachedOsmTileRetriever(18834): java.io.FileNotFoundException: http://tile.openstreetmap.org/16/33497/22228.png
05-31 14:20:34.041 E/CachedOsmTileRetriever(18834):     at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:251)
05-31 14:20:34.041 E/CachedOsmTileRetriever(18834):     at com.gluonhq.impl.maps.tile.osm.CachedOsmTileRetriever$CacheThread.doCache(CachedOsmTileRetriever.java:189)
05-31 14:20:34.041 E/CachedOsmTileRetriever(18834):     at com.gluonhq.impl.maps.tile.osm.CachedOsmTileRetriever$CacheThread.run(CachedOsmTileRetriever.java:157)

The code itself is trivial:

private void showMap(Double lat, Double lon) {
    mapView = new MapView();
    PoiLayer poiLayer = new PoiLayer();
    MapPoint mapPoint = new MapPoint(lat, lon);
    poiLayer.addPoint(mapPoint, new Circle(7, Color.RED));
    mapView.setZoom(16);
    mapView.addLayer(poiLayer);
    mapView.flyTo(0.1, mapPoint, 0.1);
    tabMap.setContent(mapView);
}

The same code works just fine on iOS: the map is loaded as expected.

Using

compile 'com.gluonhq:maps:1.0.2'

in build.gradle (same thing with 1.0.3)

Note, that if I enter the URL (from the exception mentioned above) in browser, I get redirected to https:

http://tile.openstreetmap.org/16/33497/22228.png to https://tile.openstreetmap.org/16/33497/22228.png

Any ideas why the exception on android?

Upvotes: 2

Views: 831

Answers (1)

José Pereda
José Pereda

Reputation: 45476

It looks like something has changed recently from the OpenStreetMaps servers. Gluon Maps fails on desktop as well.

I've tested with http, and I get the reported 403 error:

java.io.IOException: Server returned HTTP response code: 403 for URL: http://tile.openstreetmap.org/5/19/10.png
        at java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1913)
        at java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1509)
        at com.gluonhq.maps/com.gluonhq.impl.maps.tile.osm.CachedOsmTileRetriever$CacheThread.doCache(CachedOsmTileRetriever.java:190)
        at com.gluonhq.maps/com.gluonhq.impl.maps.tile.osm.CachedOsmTileRetriever$CacheThread.run(CachedOsmTileRetriever.java:157)

and also with https, and now I get a different error:

java.io.IOException: Server returned HTTP response code: 429 for URL: https://tile.openstreetmap.org/6/37/22.png
        at java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1913)
        at java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1509)
        at java.base/sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:245)
        at com.gluonhq.maps/com.gluonhq.impl.maps.tile.osm.CachedOsmTileRetriever$CacheThread.doCache(CachedOsmTileRetriever.java:190)
        at com.gluonhq.maps/com.gluonhq.impl.maps.tile.osm.CachedOsmTileRetriever$CacheThread.run(CachedOsmTileRetriever.java:157)

In both cases (http or https), the URL works fine on a browser, which might suggest the need of adding "User-agent" to the URLConnection request.

Initially this seemed to solve the issue, as there were no more http errors. However the tiles were blank.

Finally, the solution that fully worked for me, at least on desktop, was this one:

static {
    System.setProperty("http.agent", "Gluon Mobile/1.0.3");
}

Since this is a system property, it can be added to the project that uses Gluon Maps, so it can be tested before a new release is done to solve this issue.

Android

On Android it looks like you need to set a valid agent.

Again, this is far from a solution, but it is a quick fix.

Add to your project, and deploy to your Android device:

static {
    String userAgent = System.getProperty("http.agent");
    System.out.println("HTTP.AGENT: " + userAgent);
    System.setProperty("http.agent", userAgent);
}

With your device plugged, open a terminal, go to the Android SDK folder, and type:

cd platform-tools
adb logcat -v threadtime

And now launch the application and see the console for the output.

In my case, I see:

06-10 09:57:40.784 32630 32656 I System.out: HTTP.AGENT: Dalvik/2.1.0 (Linux; U; Android 9; Pixel XL Build/PQ3A.190505.001)

which means Android provides a valid agent, but somehow it has to be explicitly set.

Now the tiles are downloaded.

However, once this is working, I can remove this static block from my app, and install it again fresh. And the tiles are downloaded as well. It looks like it has to be done only once. Maybe the OSM servers include that agent/device/app bundle/IP in a whitelist, but this is just a pure speculation.

iOS

As mentioned, on iOS it works just fine, even if user.agent returns null.

EDIT

Finally, a proper solution can be this:

static {
    String httpAgent = System.getProperty("http.agent");
    if (httpAgent == null) {
        httpAgent = "(" + System.getProperty("os.name") + " / " + System.getProperty("os.version") + " / " + System.getProperty("os.arch") + ")";
    }
    System.setProperty("http.agent", "Gluon Mobile/1.0.3 " + httpAgent);
}

Upvotes: 1

Related Questions