首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用本地瓷砖的TileProvider

使用本地瓷砖的TileProvider
EN

Stack Overflow用户
提问于 2013-02-09 04:06:30
回答 3查看 67.6K关注 0票数 73

我想使用最新的Android (v2)的新TileProvider功能在GoogleMap上覆盖一些定制的瓷砖。但是,由于我的用户在很多时候不会有互联网,所以我希望将这些瓷砖保存在设备上的lot文件/文件夹结构中。我将使用Maptilergeotiffs生成我的瓷砖。我的问题是:

  1. 在设备上储存瓷砖的最好方法是什么?
  2. 如何创建返回本地瓷砖的TileProvider?
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-02-12 13:05:00

  1. 您可以将瓷砖放入资产文件夹(如果应用程序大小是可以接受的),或者在第一次启动时将其全部下载并放入设备存储(SD卡)。
  2. 您可以这样实现TileProvider:

代码语言:javascript
复制
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实例中使用它:

代码语言:javascript
复制
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生成的tiles的y坐标也有问题,但是我通过将这个方法添加到CustomMapTileProvider中来管理它:

代码语言:javascript
复制
/**
 * 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()方法中得到如下所示:

代码语言:javascript
复制
@Override
public Tile getTile(int x, int y, int zoom) {
    y = fixYCoordinate(y, zoom);
    ...
}

Upd

如果您知道自定义映射的exac区域,则应该返回NO_TILE,以查找getTile(...)方法中缺少的瓷砖。

我就是这样做的:

代码语言:javascript
复制
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);
}
票数 177
EN

Stack Overflow用户

发布于 2013-03-04 09:56:28

在新的API (v2)中添加自定义的贴片提供程序的可能性很大,但是您提到您的用户大多是脱机的。如果用户在第一次启动应用程序时处于脱机状态,则不能使用新的API,因为它要求用户在线(似乎至少有一次)--否则它只会显示一个黑色屏幕。

编辑2/22-14:我最近又遇到了同样的问题-为一个必须脱机工作的应用程序定制瓷砖。通过在初始视图中添加一个不可见的(w/h0/0)映射来解决这个问题,在这个视图中,客户端必须下载一些内容。这似乎是可行的,并且允许我稍后在脱机模式下使用mapview。

票数 8
EN

Stack Overflow用户

发布于 2022-01-20 16:47:20

这是我在Kotlin中实现的:

代码语言:javascript
复制
class LocalTileProvider : TileProvider
{

override fun getTile(x: Int, y: Int, zoom: Int): Tile?
{
    // This is for my case only
    if (zoom > 11)
        return TileProvider.NO_TILE

    val path = "${getImagesFolder()}/tiles/$zoom/$x/$y/filled.png"
    val file = File(path)
    if (!file.exists())
        return TileProvider.NO_TILE
    return try {
        Tile(TILE_SIZE, TILE_SIZE, file.readBytes())
    }
    catch (e: Exception)
    {
        TileProvider.NO_TILE
    }
}

companion object {
    const val TILE_SIZE = 512
}

}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14784841

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档