如何在 android google map v2 实现上为 geoserver 瓦片重新加载 TileOverlay

Posted

技术标签:

【中文标题】如何在 android google map v2 实现上为 geoserver 瓦片重新加载 TileOverlay【英文标题】:How to reload TileOverlay for geoserver tiles on android google map v2 implementation 【发布时间】:2015-05-28 10:02:12 【问题描述】:

我正在使用 geoserve 实现来检索我的地图图块。 我请求切片的方式是,当相机更改地图上的视图时,它会触发我的 api 调用,然后发送地图中心视图的纬度和经度,然后 api 响应 TileOverlay 的 getTileUrl 所需的地理服务器层列表。

但不幸的是,当我的 Api 返回图层列表时,getTileUrl 已经被触发并且我的图块没有呈现。

简而言之,我的地理服务器请求的图层参数是动态变化的。所以我的问题是如何触发再次加载地图叠加层,以便当我的 Api 返回列表时,它会重新加载带有适当图层的叠加层。

这是我对 OnCameraChangeListener 的实现:

private GoogleMap.OnCameraChangeListener cameraChange = new GoogleMap.OnCameraChangeListener() 
    @Override
    public void onCameraChange(CameraPosition cameraPosition) 
        LatLng latLng = map.getCameraPosition().target;
        getLayerLists(latLng);
    
;

这里是getLayerList方法:

private void getLayerList(LatLng latLng) 
    nigsApi.getLayerForArea(TAG_FLOOD_MAP_REQUEST,
            String.valueOf(latLng.latitude), String.valueOf(latLng.longitude),
            onApiResponse);

这是返回层列表的 onApiResponse 回调:

private OnApiResponse<NigsApi.ResponsePair<List<String>>> onApiResponse = new OnApiResponse<NigsApi.ResponsePair<List<String>>>() 
    @Override
    public void onRequestSuccessful(NigsApi.ResponsePair<List<String>> result) 
        tileProviderFactory.setLayerArea(result.getResult());
    

    @Override
    public void onRequestFailed(String errorMessage, Object tag) 
        Log.e("Maps", errorMessage);
    

    @Override
    public void onRequestError(RetrofitError error, Object tag) 
        Log.e("Maps", error.getMessage());
    
;

响应后它转到 My TileProviderFactory 类并设置 getTileUrl 所需的层列表。

这里是 getTileUrl 的块:

public void setLayerArea(List<String> listLayer)
    this.listLayer = listLayer;
    

public WmsTileProvider getOsgeoWmsTileProvider() 

    //This is configured for:
    // http://beta.sedac.ciesin.columbia.edu/maps/services
    // (TODO check that this WMS service still exists at the time you try to run this demo,
    // if it doesn't, find another one that supports EPSG:900913
    final String WMS_FORMAT_STRING =
            "http://202.90.153.87:8080/geoserver/flood_100/wms?" +
                    "service=WMS" +
                    "&version=1.1.0" +
                    "&request=GetMap" +
                    "&bbox=%f,%f,%f,%f" +
                    "&width=256" +
                    "&height=256" +
                    "&srs=EPSG:900913" +
                    "&format=image/png" +
                    "&transparent=true" +
                    "&tiled=true";

    WmsTileProvider tileProvider = new WmsTileProvider(256,256) 
        @Override
        public synchronized URL getTileUrl(int x, int y, int zoom) 
            double[] bbox = getBoundingBox(x, y, zoom);

            String layerTitles = getLayerTitles();

            String s = String.format(Locale.US, WMS_FORMAT_STRING, bbox[MINX],
                    bbox[MINY], bbox[MAXX], bbox[MAXY]);

            s = s + layerTitles;

            Log.e("MapLayers", s);
            URL url = null;

            try 
                url = new URL(s);
             catch (MalformedURLException e) 
                throw new AssertionError(e);
            
            return url;
        
    ;

    return tileProvider;

getLayerTitles() 方法将所有图层连接成一个字符串并将其附加到 WMS_FORMAT_STRING url..

private String getLayerTitles()
    if (listLayer.size() == 0) 
        return layers;
     else 
        layers = "&layers=";
        for (String location : listLayer) 
            if (layers.equals("&layers="))
                layers = layers + location;
            else
                layers = layers + "," + location;
        
        return layers;
    

【问题讨论】:

【参考方案1】:

你需要渲染多少层?您是否需要一次渲染所有这些?

如果可以的话,最好每层创建一个WmsTileProvider;这将使您能够精细地启用或禁用图层。

如果您需要(或想要)一次渲染所有这些,您可以以更智能的方式使用您的 getTileUrl:

在您的 WmsTileProvider 中创建一个允许您设置图层的方法(您可以在类中创建一个 mLayers String 变量并更改 getLayersTitles 方法以更改此变量而不是返回它),然后在需要时调用此方法更改图层列表并调用 clearTileCache:

https://developers.google.com/android/reference/com/google/android/gms/maps/model/TileOverlay#clearTileCache%28%29

您的图块将重新加载新图层...

代码(抱歉格式错误):

public void setLayerArea(List<String> listLayer)
  this.mLayers = getLayerTitles(listLayer);
   

private String getLayerTitles(List<String> listLayer)
if (listLayer.size() == 0) 
    return "DEFAULT LAYERS";
 else 
    layers = "&layers=";
    for (String location : listLayer) 
        if (layers.equals("&layers="))
            layers = layers + location;
        else
            layers = layers + "," + location;
    
    return layers;

 

public WmsTileProvider getOsgeoWmsTileProvider() 

//This is configured for:
// http://beta.sedac.ciesin.columbia.edu/maps/services
// (TODO check that this WMS service still exists at the time you try to run this demo,
// if it doesn't, find another one that supports EPSG:900913
final String WMS_FORMAT_STRING =
        "http://202.90.153.87:8080/geoserver/flood_100/wms?" +
                "service=WMS" +
                "&version=1.1.0" +
                "&request=GetMap" +
                "&bbox=%f,%f,%f,%f" +
                "&width=256" +
                "&height=256" +
                "&srs=EPSG:900913" +
                "&format=image/png" +
                "&transparent=true" +
                "&tiled=true";

WmsTileProvider tileProvider = new WmsTileProvider(256,256) 
    @Override
    public synchronized URL getTileUrl(int x, int y, int zoom) 
        double[] bbox = getBoundingBox(x, y, zoom);

        String s = String.format(Locale.US, WMS_FORMAT_STRING, bbox[MINX],
                bbox[MINY], bbox[MAXX], bbox[MAXY]);

        s = s + this.mLayers;

        Log.e("MapLayers", s);
        URL url = null;

        try 
            url = new URL(s);
         catch (MalformedURLException e) 
            throw new AssertionError(e);
        
        return url;
    
;

return tileProvider;

【讨论】:

以上是关于如何在 android google map v2 实现上为 geoserver 瓦片重新加载 TileOverlay的主要内容,如果未能解决你的问题,请参考以下文章

如何设置 Android Google Maps API v2 地图以显示全球地图?

Android,如何从 Google Map V2 中删除所有标记?

如何在 Android Google Maps API v2 中将 LatLng 和半径转换为 ​​LatLngBounds?

如何在 android 上使用 google maps api v2 很好地管理标记

如何使用字符串地址在 google maps API V2 android 中获取地理坐标?

在 Google Maps Android SDK (v2) 中更改建筑物颜色