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
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.