로컬 타일을 사용하는 TileProvider
TileProvider
최신 Android Maps API (v2) 의 새로운 기능 을 사용 하여 GoogleMap
. 그러나 내 사용자가 인터넷을 많이 사용하지 않기 때문에 타일을 장치의 zip 파일 / 폴더 구조에 저장하고 싶습니다. Maptiler
와 함께 사용하여 타일을 생성 geotiffs
합니다. 내 질문은 다음과 달라집니다.
- 장치에 타일을 저장하는 가장 좋은 방법은 무엇입니까?
- 로컬 타일을 반환하는 TileProvider를 만드는 방법은 무엇입니까?
타일을 자산 폴더에 넣거나 (앱 크기에 허용되는 경우) 처음 시작할 때 모두 다운로드하여 장치 저장소 (SD 카드)에 넣을 수 있습니다.
다음과 같이 TileProvider를 구현할 수 있습니다.
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;
}
@Override
public Tile getTile(int x, int y, int zoom) {
byte[] image = readTileImage(x, y, zoom);
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);
}
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 + ".png";
}
}
이제 GoogleMap 인스턴스와 함께 사용할 수 있습니다.
private void setUpMap() {
mMap.setMapType(GoogleMap.MAP_TYPE_NONE);
mMap.addTileOverlay(new TileOverlayOptions().tileProvider(new CustomMapTileProvider(getResources().getAssets())));
CameraUpdate upd = CameraUpdateFactory.newLatLngZoom(new LatLng(LAT, LON), ZOOM);
mMap.moveCamera(upd);
}
제 경우에는 MapTiler에서 생성 한 타일의 y 좌표에도 문제가 있었지만 CustomMapTileProvider에이 메서드를 추가하여 관리했습니다.
/**
* Fixing tile's y index (reversing order)
*/
private int fixYCoordinate(int y, int zoom) {
int size = 1 << zoom; // size = 2^zoom
return size - 1 - y;
}
다음과 같이 getTile () 메서드에서 호출합니다.
@Override
public Tile getTile(int x, int y, int zoom) {
y = fixYCoordinate(y, zoom);
...
}
[업데이트]
사용자 지정지도의 정확한 영역을 알고있는 경우 메서드 NO_TILE
에서 누락 된 타일을 반환해야합니다 getTile(...)
.
이것이 내가 한 방법입니다.
private static final SparseArray<Rect> TILE_ZOOMS = new SparseArray<Rect>() {{
put(8, new Rect(135, 180, 135, 181 ));
put(9, new Rect(270, 361, 271, 363 ));
put(10, new Rect(541, 723, 543, 726 ));
put(11, new Rect(1082, 1447, 1086, 1452));
put(12, new Rect(2165, 2894, 2172, 2905));
put(13, new Rect(4330, 5789, 4345, 5810));
put(14, new Rect(8661, 11578, 8691, 11621));
}};
@Override
public Tile getTile(int x, int y, int zoom) {
y = fixYCoordinate(y, zoom);
if (hasTile(x, y, zoom)) {
byte[] image = readTileImage(x, y, zoom);
return image == null ? null : new Tile(TILE_WIDTH, TILE_HEIGHT, image);
} else {
return NO_TILE;
}
}
private boolean hasTile(int x, int y, int zoom) {
Rect b = TILE_ZOOMS.get(zoom);
return b == null ? false : (b.left <= x && x <= b.right && b.top <= y && y <= b.bottom);
}
새 API (v2)에 사용자 지정 타일 제공 업체를 추가 할 수있는 가능성은 훌륭하지만 사용자가 대부분 오프라인이라고 언급했습니다. 사용자가 응용 프로그램을 처음 시작할 때 오프라인 상태 인 경우 사용자가 온라인 상태 여야하므로 새 API를 사용할 수 없습니다 (캐시를 구축하려면 적어도 한 번은 보임). 그렇지 않으면 검은 색 화면 만 표시됩니다.
2 / 22-14 편집 : 최근에 오프라인으로 작업해야하는 앱에 대한 사용자 지정 타일이있는 동일한 문제가 다시 발생했습니다. 클라이언트가 일부 콘텐츠를 다운로드해야하는 초기보기에 보이지 않는 (w / h 0/0) 맵뷰를 추가하여 문제를 해결했습니다. 이것은 작동하는 것처럼 보이며 나중에 오프라인 모드에서 맵 뷰를 사용할 수 있습니다.
참고 URL : https://stackoverflow.com/questions/14784841/tileprovider-using-local-tiles
'ProgramingTip' 카테고리의 다른 글
텍스트 정렬 : 오른쪽에 (0) | 2020.10.31 |
---|---|
PHP를 사용하여 JQuery .ajax ()에 대한 적절한 성공 / 오류 메시지를 어떻게 반환합니까? (0) | 2020.10.31 |
액션에 대한 클릭 가능한 링크가있는 iOS UITextView 또는 UILabel (0) | 2020.10.31 |
UTC 날짜와 함께 AngularJS 날짜 필터 사용 (0) | 2020.10.31 |
Math.ceil이 왜 double을 반환합니까? (0) | 2020.10.30 |