1

Hello everyone, I'm trying to create a map of a game, and for this I'm using TileOverlay. Generally speaking, I have two ways of doing this:

  • Using UrlTileProvider (), which retrieves the Tiles from a geoserver;
  • Using the CustomMapTileProvider (), whose I was trying to retrieve the Tiles from the assets of the application itself.

I tried both ways, including the first one I did, however by accessing an existing geoserver for the map of the game I want. But I can not access this server when the application is working, it's like the server of a "competitor". The code that worked with the first way was this:

public class MainActivity extends AppCompatActivity 
        implements OnMapReadyCallback {

    //This returns game map tiles.
    private static final String GAME_MAP_URL_FORMAT =
            "https://gamemapurl.com/map/%d/%d/%d.jpg";
    private TileOverlay overTiles;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        SupportMapFragment mapFragment =
                (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);
    }

    @Override
    public void onMapReady(GoogleMap map) {
        map.setMapType(GoogleMap.MAP_TYPE_NONE);

        TileProvider tileProvider = new UrlTileProvider(256, 256) {
            @Override
            public synchronized URL getTileUrl(int x, int y, int zoom) {
                int reversedY = (1 << zoom) - y - 1;
                String s = String.format(Locale.US, GAME_MAP_URL_FORMAT, zoom, x, reversedY);
                URL url = null;

                if (!checkTileExists(x, y, zoom)) {
                    return null;
                }

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

        overTiles = map.addTileOverlay(new TileOverlayOptions().tileProvider(tileProvider));
    }

    private boolean checkTileExists(int x, int y, int zoom) {
        int minZoom = 1;
        int maxZoom = 6;

        if ((zoom < minZoom || zoom > maxZoom)) {
            return false;
        }

        return true;
    }
}

The problem with this way of creating the map, is that I need a geoserver to store the tiles, or some form of storing them to be accessed at any time. And as I'm starting to work with it now, I do not know if there are free servers with this service, and buying a server for this functionality is unfortunately not an option.

This code works with the second way to implement this. This code I found in this question, and it worked for some people. But in my code, the "imageByte" log returns null and the "nRead" and "tileFile" logs do not even appear, which I believe indicates that it is not getting this while.

public class MainActivity extends AppCompatActivity implements OnMapReadyCallback {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        SupportMapFragment mapFragment =
                (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);
    }

    @Override
    public void onMapReady(GoogleMap mMap) {
        mMap.setMapType(GoogleMap.MAP_TYPE_NONE);
        Log.d("mapReady", "OK");
        mMap.addTileOverlay(new TileOverlayOptions().tileProvider(new CustomMapTileProvider(getResources().getAssets())));

        //CameraUpdate upd = CameraUpdateFactory.newLatLngZoom(new LatLng(LAT, LON), Zoom);
        //mMap.moveCamera(upd);
    }

    public class CustomMapTileProvider implements TileProvider {
        private static final int TILE_WIDTH = 256;
        private static final int TILE_HEIGHT = 256;
        private static final int BUFFER_SIZE = 16 * 1024;
        private AssetManager mAssets;

        public CustomMapTileProvider(AssetManager assets) {
            mAssets = assets;
            try {
                String[] files = assets.list("");
                Log.d("CustomASSET", files + "");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        @Override
        public Tile getTile(int x, int y, int zoom) {
            byte[] image = readTileImage(x, y, zoom);
            Log.d("imageByte", "ImgByte = " + image);
            return image == null ? null : new Tile(TILE_WIDTH, TILE_HEIGHT, image);
        }

        private byte[] readTileImage(int x, int y, int zoom) {
            InputStream in = null;
            ByteArrayOutputStream buffer = null;

            try {
                in = mAssets.open(getTileFilename(x, y, zoom));
                buffer = new ByteArrayOutputStream();

                int nRead;
                byte[] data = new byte[BUFFER_SIZE];

                while ((nRead = in.read(data, 0, BUFFER_SIZE)) != -1) {
                    buffer.write(data, 0, nRead);
                    Log.d("nRead", "nREAD = " + nRead);
                    Log.d("tileFile", "tileFilename = " + in);
                }
                buffer.flush();

                return buffer.toByteArray();
            } catch (IOException e) {
                e.printStackTrace();
                return null;
            } catch (OutOfMemoryError e) {
                e.printStackTrace();
                return null;
            } finally {
                if (in != null) try { in.close(); } catch (Exception ignored) {}
                if (buffer != null) try { buffer.close(); } catch (Exception ignored) {}
            }
        }

        private String getTileFilename(int x, int y, int zoom) {
            return "map/" + zoom + '/' + x + '/' + y + ".jpg";
            // ---> map/0/0/0.png
        }
    }
}

Here is a print from my assets folder

Assets folder

I just want to know what's happening with the second code, I spent a whole day debugging it and can not find anything. Maybe there is some way to store these tiles but for my lack of knowledge in geoservers I do not know. Thank you so much for reading here.

1 Answers1

0

I was able to figure out my problem.

The code was beginning to request the tiles from the map folder by counting zoom 1 as zoom 2, and since I had no tiles in the zoom folder 2 it did not display them.

The code works perfectly.