使用TileOverlay

时间:2017-12-12 15:12:12

标签: android google-maps

大家好,我正在尝试创建一个游戏地图,为此我正在使用TileOverlay。一般来说,我有两种方法:

  • 使用UrlTileProvider()从地理服务器检索Tiles;
  • 使用CustomMapTileProvider(),我试图从应用程序本身的资产中检索Tiles。

我尝试了两种方式,包括我做的第一种方法,但是通过访问我想要的游戏地图的现有地理服务器。但是,当应用程序运行时,我无法访问此服务器,它就像是“竞争对手”的服务器。 使用第一种方式的代码是:

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;
    }
}

这种创建地图的方法的问题是,我需要一个地理服务器来存储切片,或者某种形式的存储它们随时可以访问。当我现在开始使用它时,我不知道是否有免费服务器使用此服务,并且很遗憾购买服务器以实现此功能。

此代码适用于实现此目的的第二种方式。我在此question中找到了此代码,它适用于某些人。但是在我的代码中,“imageByte”日志返回null并且“nRead”和“tileFile”日志甚至没有出现,我相信这表明它没有得到这个。

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

这是我的资产文件夹

的打印件

Assets folder

我只是想知道第二个代码发生了什么,我花了一整天的时间调试它并找不到任何东西。也许有一些方法来存储这些瓷砖,但由于我对geoservers缺乏知识,我不知道。非常感谢你在这里阅读。

1 个答案:

答案 0 :(得分:0)

我能够弄明白我的问题。

代码开始通过将缩放1计为缩放2来请求print(animal2, new CheckTrait() { public boolean test(Animal a) { return a.canHop(); } }); 文件夹中的切片,并且由于我在缩放文件夹2中没有切片,因此它不显示它们。

代码完美无缺。