Merge branch 'android_http_server' of https://github.com/osmandapp/Osmand into android_http_server
This commit is contained in:
commit
2442759d07
1 changed files with 68 additions and 19 deletions
|
@ -9,41 +9,62 @@ import net.osmand.data.RotatedTileBox;
|
|||
import net.osmand.plus.activities.MapActivity;
|
||||
import net.osmand.plus.resources.AsyncLoadingThread;
|
||||
import net.osmand.plus.server.OsmAndHttpServer;
|
||||
import net.osmand.plus.views.OsmandMapTileView;
|
||||
import net.osmand.util.MapUtils;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Scanner;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
|
||||
import static fi.iki.elonen.NanoHTTPD.newFixedLengthResponse;
|
||||
|
||||
public class TileEndpoint implements OsmAndHttpServer.ApiEndpoint {
|
||||
private static final int TILE_SIZE_PX = 512;
|
||||
private static final int TILE_SIZE_PX = 256;
|
||||
private static final int TILE_DENSITY = 2;
|
||||
private static final int TIMEOUT_STEP = 500;
|
||||
private static final int TIMEOUT = 5000;
|
||||
private static final int METATILE_SIZE = 2;
|
||||
private static final int MAX_CACHE_SIZE = 4;
|
||||
|
||||
private static final Log LOG = PlatformUtil.getLog(TileEndpoint.class);
|
||||
private final MapActivity mapActivity;
|
||||
private final List<MetaTileCache> cache = new ArrayList<>();
|
||||
// TODO store on file system
|
||||
private final ConcurrentLinkedQueue<MetaTileCache> cache = new ConcurrentLinkedQueue<>();
|
||||
|
||||
private static class MetaTileCache {
|
||||
Bitmap bmp;
|
||||
int x;
|
||||
int y;
|
||||
int sx;
|
||||
int sy;
|
||||
int ex;
|
||||
int ey;
|
||||
int zoom;
|
||||
|
||||
// to be used in file name
|
||||
public String getTileId() {
|
||||
return zoom + "_" + METATILE_SIZE + "_" + sx + "_" + sy;
|
||||
}
|
||||
|
||||
public Bitmap getSubtile(int x, int y) {
|
||||
// TODO cut subtitle
|
||||
return bmp;
|
||||
}
|
||||
}
|
||||
|
||||
public TileEndpoint(MapActivity mapActivity) {
|
||||
this.mapActivity = mapActivity;
|
||||
}
|
||||
|
||||
private void addToMemoryCache(MetaTileCache res) {
|
||||
while (cache.size() > MAX_CACHE_SIZE) {
|
||||
cache.poll();
|
||||
}
|
||||
cache.add(res);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NanoHTTPD.Response process(NanoHTTPD.IHTTPSession session, String url) {
|
||||
// https://tile.osmand.net/hd/6/55/25.png
|
||||
|
@ -61,12 +82,24 @@ public class TileEndpoint implements OsmAndHttpServer.ApiEndpoint {
|
|||
int zoom = Integer.parseInt(prms[1]);
|
||||
int x = Integer.parseInt(prms[2]);
|
||||
int y = Integer.parseInt(prms[3]);
|
||||
Bitmap bitmap = requestTile(x, y, zoom);
|
||||
if (bitmap == null) {
|
||||
MetaTileCache res = null;
|
||||
for (MetaTileCache r : cache) {
|
||||
if (r.zoom == zoom && r.ex >= x && r.ey >= y && r.sx <= x && r.sy <= y) {
|
||||
res = r;
|
||||
}
|
||||
}
|
||||
if(res == null) {
|
||||
res = requestMetatile(x, y, zoom);
|
||||
}
|
||||
if (res == null) {
|
||||
return OsmAndHttpServer.ErrorResponses.response500;
|
||||
}
|
||||
ByteArrayOutputStream stream = new ByteArrayOutputStream();
|
||||
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
|
||||
Bitmap bmp = res.getSubtile(x, y);
|
||||
if (bmp == null) {
|
||||
return OsmAndHttpServer.ErrorResponses.response500;
|
||||
}
|
||||
bmp.compress(Bitmap.CompressFormat.PNG, 100, stream);
|
||||
byte[] byteArray = stream.toByteArray();
|
||||
ByteArrayInputStream str = new ByteArrayInputStream(byteArray);
|
||||
return newFixedLengthResponse(
|
||||
|
@ -74,28 +107,42 @@ public class TileEndpoint implements OsmAndHttpServer.ApiEndpoint {
|
|||
str, str.available());
|
||||
}
|
||||
|
||||
private synchronized Bitmap requestTile(int x, int y, int zoom) {
|
||||
double lat = MapUtils.getLatitudeFromTile(zoom, y);
|
||||
double lon = MapUtils.getLongitudeFromTile(zoom, x);
|
||||
private synchronized MetaTileCache requestMetatile(int x, int y, int zoom) {
|
||||
int mx = (x / METATILE_SIZE) * METATILE_SIZE;
|
||||
int my = (y / METATILE_SIZE) * METATILE_SIZE;
|
||||
double lat = MapUtils.getLatitudeFromTile(zoom, my + 0.5 * METATILE_SIZE);
|
||||
double lon = MapUtils.getLongitudeFromTile(zoom, mx + 0.5 * METATILE_SIZE);
|
||||
final RotatedTileBox cp = mapActivity.getMapView().getCurrentRotatedTileBox();
|
||||
final RotatedTileBox rotatedTileBox = new RotatedTileBox.RotatedTileBoxBuilder()
|
||||
.setLocation(lat, lon)
|
||||
.setMapDensity(cp.getMapDensity()).density(cp.getDensity())
|
||||
.setMapDensity(cp.getMapDensity()).density(TILE_DENSITY)
|
||||
.setZoom(zoom)
|
||||
.setPixelDimensions(TILE_SIZE_PX, TILE_SIZE_PX, 0.5f, 0.5f).build();
|
||||
.setPixelDimensions(TILE_SIZE_PX * TILE_DENSITY * METATILE_SIZE, TILE_SIZE_PX * TILE_DENSITY * METATILE_SIZE, 0.5f, 0.5f).build();
|
||||
mapActivity.getMapView().setCurrentViewport(rotatedTileBox);
|
||||
|
||||
|
||||
int timeout = 0;
|
||||
try {
|
||||
AsyncLoadingThread athread = mapActivity.getMyApplication().getResourceManager().getAsyncLoadingThread();
|
||||
Thread.sleep(TIMEOUT_STEP); // line not correct
|
||||
Bitmap res = null;
|
||||
Thread.sleep(TIMEOUT_STEP); // TODO line should be removed in future
|
||||
MetaTileCache res = null;
|
||||
while (athread.areResourcesLoading() && timeout < TIMEOUT) {
|
||||
Thread.sleep(TIMEOUT_STEP);
|
||||
timeout += TIMEOUT_STEP;
|
||||
}
|
||||
if(!athread.areResourcesLoading()) {
|
||||
res = mapActivity.getMapView().getBufferBitmap();
|
||||
if (!athread.areResourcesLoading()) {
|
||||
res = new MetaTileCache();
|
||||
res.sx = mx;
|
||||
res.ex = mx + METATILE_SIZE - 1;
|
||||
res.sy = my;
|
||||
res.ey = my + METATILE_SIZE - 1;
|
||||
res.zoom = zoom;
|
||||
RotatedTileBox tilebox = mapActivity.getMapView().getBufferImgLoc();
|
||||
// TODO here we need to properly cut image according to tilebox
|
||||
res.bmp = mapActivity.getMapView().getBufferBitmap();
|
||||
LOG.debug(mapActivity.getMapView().getBufferImgLoc());
|
||||
|
||||
addToMemoryCache(res);
|
||||
}
|
||||
return res;
|
||||
} catch (InterruptedException e) {
|
||||
|
@ -103,4 +150,6 @@ public class TileEndpoint implements OsmAndHttpServer.ApiEndpoint {
|
|||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue