Home » Android » overlay – Using getTileURL in Android Application with GeoServer

overlay – Using getTileURL in Android Application with GeoServer

Posted by: admin June 16, 2020 Leave a comment


We are just starting to work with Google Maps on Android and have a GeoServer set up to provide tiles which we would like to add as overlay on the map. So far, I have followed a few tutorials and references to get started.

The problem: While the url that I am generating in the getTileUrl function in the TileProviderFactory does indeed return a png image when I set a breakpoint and copy and paste the url into a browser, it does not load onto the map as an overlay on the Android device. There are no errors being thrown from what I can see and after reading this I am not sure if there will be any as they have indicated that the errors are being muted.

What I am wondering is if you can see any immediate issues in my code or have any suggestions for debugging where I will be able to tell if the application is actually communicating with my GeoServer to retrieve the image or not. I’ve looked at the log on the GeoServer and it seems as though only my browser requests are going through and it’s not receiving any requests from Android (it’s a bit difficult to tell because we have other applications using the server as well). The Android phone is connected by both wifi and cell and has gps enabled. As a last resort I have tried changing the tile overlay zIndex and setting it to visible but this didn’t seem to make any difference.

EDIT: Android device is definitely NOT communicating with GeoServer at this point.

EDIT 2: Able to load static images from websites
(like this) as overlays and found that I am getting the following exception on testing out an HTTP Request to the formed URL:

W/System.err(10601): java.net.SocketException: The operation timed out
W/System.err(10601): at org.apache.harmony.luni.platform.OSNetworkSystem
     .connectStreamWithTimeoutSocketImpl(Native Method)
W/System.err(10601): at org.apache.harmony.luni.net.PlainSocketImpl
W/System.err(10601): at org.apache.harmony.luni.net.PlainSocketImpl
W/System.err(10601): at java.net.Socket
W/System.err(10601): at org.apache.http.conn.scheme.PlainSocketFactory



public class MapTestActivity extends FragmentActivity
    implements LocationListener, LocationSource{

    private GoogleMap mMap;
    private OnLocationChangedListener mListener;
    private LocationManager locationManager;

    protected void onCreate(Bundle savedInstanceState) {

    private void setupLocationManager() {
        this.locationManager = 
            (LocationManager) getSystemService(LOCATION_SERVICE);

        if (locationManager != null) {
            boolean gpsIsEnabled = locationManager.isProviderEnabled(
            boolean networkIsEnabled = locationManager.isProviderEnabled(

            if(gpsIsEnabled) {
                    LocationManager.GPS_PROVIDER, 5000L, 10F, this);
            else if(networkIsEnabled) {
                    LocationManager.NETWORK_PROVIDER, 5000L, 10F, this);
            else {
                //Show an error dialog that GPS is disabled...
        else {
            // Show some generic error dialog because 
            // something must have gone wrong with location manager.

    private void setupMapIfNeeded() {
        // Do a null check to confirm that we have not already instantiated the
        // map.
        if (mMap == null) {
            // Try to obtain the map from the SupportMapFragment.
            mMap = ((SupportMapFragment) getSupportFragmentManager()
            // Check if we were successful in obtaining the map.
            if (mMap != null) {

    private void setUpMap() {
        // TODO Auto-generated method stub
        TileProvider geoServerTileProvider = TileProviderFactory
        TileOverlay geoServerTileOverlay = mMap.addTileOverlay(
            new TileOverlayOptions()
    // Non-relevant listener methods removed


public class TileProviderFactory {

    public static GeoServerTileProvider getGeoServerTileProvider() {

        String baseURL = "mytileserver.com";
        String version = "1.3.0";
        String request = "GetMap";
        String format = "image/png";
        String srs = "EPSG:900913";
        String service = "WMS";
        String width = "256";
        String height = "256";
        String styles = "";
        String layers = "wtx:road_hazards";

        final String URL_STRING = baseURL + 
                "&LAYERS=" + layers + 
                "&VERSION=" + version + 
                "&SERVICE=" + service + 
                "&REQUEST=" + request + 
                "&TRANSPARENT=TRUE&STYLES=" + styles + 
                "&FORMAT=" + format + 
                "&SRS=" + srs + 
                "&BBOX=%f,%f,%f,%f" + 
                "&WIDTH=" + width + 
                "&HEIGHT=" + height;

        GeoServerTileProvider tileProvider = 
            new GeoServerTileProvider(256,256) {

            public synchronized URL getTileUrl(int x, int y, int zoom) {
                try {       

                    double[] bbox = getBoundingBox(x, y, zoom);

                    String s = String.format(Locale.US, URL_STRING, bbox[MINX], 
                            bbox[MINY], bbox[MAXX], bbox[MAXY]);

                    Log.d("GeoServerTileURL", s);

                    URL url = null;

                    try {
                        url = new URL(s);
                    catch (MalformedURLException e) {
                        throw new AssertionError(e);

                    return url;
                catch (RuntimeException e) {
                        "getTile x=" + x + ", y=" + y + 
                        ", zoomLevel=" + zoom + 
                        " raised an exception", e);
                    throw e;

        return tileProvider;


public abstract class GeoServerTileProvider extends UrlTileProvider{

    // Web Mercator n/w corner of the map.
    private static final double[] TILE_ORIGIN = 
        {-20037508.34789244, 20037508.34789244};
    //array indexes for that data
    private static final int ORIG_X = 0; 
    private static final int ORIG_Y = 1; // "

    // Size of square world map in meters, using WebMerc projection.
    private static final double MAP_SIZE = 20037508.34789244 * 2;

    // array indexes for array to hold bounding boxes.
    protected static final int MINX = 0;
    protected static final int MINY = 1;
    protected static final int MAXX = 2;
    protected static final int MAXY = 3;

    public GeoServerTileProvider(int width, int height) {
        super(width, height);

    // Return a web Mercator bounding box given tile x/y indexes and a zoom
    // level.
    protected double[] getBoundingBox(int x, int y, int zoom) {
        double tileSize = MAP_SIZE / Math.pow(2, zoom);
        double minx = TILE_ORIGIN[ORIG_X] + x * tileSize;
        double maxx = TILE_ORIGIN[ORIG_X] + (x+1) * tileSize;
        double miny = TILE_ORIGIN[ORIG_Y] - (y+1) * tileSize;
        double maxy = TILE_ORIGIN[ORIG_Y] - y * tileSize;

        double[] bbox = new double[4];
        bbox[MINX] = minx;
        bbox[MINY] = miny;
        bbox[MAXX] = maxx;
        bbox[MAXY] = maxy;
        return bbox;
How to&Answers:

This turned out to be a network issue and completely unrelated to my implementation which is “correct”. I guess this question will serve well as an example for others who are getting started with Android + GeoServer implementation so I will leave it up.