【问题标题】:Using getTileURL in Android Application with GeoServer在带有 GeoServer 的 Android 应用程序中使用 getTileURL
【发布时间】:2013-03-11 07:52:34
【问题描述】:

我们刚刚开始在 Android 上使用 Google 地图,并设置了一个 GeoServer 来提供我们希望添加为地图上的叠加层的图块。到目前为止,我已经按照一些教程和参考资料开始学习。

问题:当我设置断点并将该 url 复制并粘贴到浏览器,它不会作为 Android 设备上的叠加层加载到地图上。从我所看到的内容中没有抛出任何错误,并且在阅读 this 之后,我不确定是否会有任何错误,因为他们表示错误正在被忽略。

我想知道是您是否可以在我的代码中看到任何直接问题,或者对调试有任何建议,我将能够判断应用程序是否实际上正在与我的 GeoServer 通信以检索图像与否。我查看了 GeoServer 上的日志,似乎只有我的浏览器请求正在通过,并且没有收到来自 Android 的任何请求(这有点难以分辨,因为我们还有其他应用程序也在使用该服务器)。 Android手机通过wifi和手机连接,并启用了gps。作为最后的手段,我尝试更改平铺覆盖 zIndex 并将其设置为可见,但这似乎没有任何区别。

编辑:Android 设备此时肯定没有与 GeoServer 通信。

编辑 2:能够从网站加载静态图像 (如this)作为覆盖,发现我在测试对形成的URL的HTTP请求时遇到以下异常:

W/System.err(10601): java.net.SocketException: The operation timed out
W/System.err(10601): at org.apache.harmony.luni.platform.OSNetworkSystem
     .connectStreamWithTimeoutSocketImpl(Native Method)
W/System.err(10601): at org.apache.harmony.luni.net.PlainSocketImpl
     .connect(PlainSocketImpl.java:244)
W/System.err(10601): at org.apache.harmony.luni.net.PlainSocketImpl
     .connect(PlainSocketImpl.java:533)
W/System.err(10601): at java.net.Socket
     .connect(Socket.java:1074)
W/System.err(10601): at org.apache.http.conn.scheme.PlainSocketFactory
     .connectSocket(PlainSocketFactory.java:119)

谢谢。

地图测试活动

public class MapTestActivity extends FragmentActivity
    implements LocationListener, LocationSource{

    private GoogleMap mMap;
    private OnLocationChangedListener mListener;
    private LocationManager locationManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_map_test);     
        setupLocationManager();     
        setupMapIfNeeded();
    }

    private void setupLocationManager() {
        this.locationManager = 
            (LocationManager) getSystemService(LOCATION_SERVICE);

        if (locationManager != null) {
            boolean gpsIsEnabled = locationManager.isProviderEnabled(
                    LocationManager.GPS_PROVIDER);
            boolean networkIsEnabled = locationManager.isProviderEnabled(
                    LocationManager.NETWORK_PROVIDER);

            if(gpsIsEnabled) {
                this.locationManager.requestLocationUpdates(
                    LocationManager.GPS_PROVIDER, 5000L, 10F, this);
            }
            else if(networkIsEnabled) {
                this.locationManager.requestLocationUpdates(
                    LocationManager.NETWORK_PROVIDER, 5000L, 10F, this);
            }
            else {
                //Show an error dialog that GPS is disabled...
            }
        }
        else {
            // Show some generic error dialog because 
            // something must have gone wrong with location manager.
        }
    }

    private void setupMapIfNeeded() {
        // Do a null check to confirm that we have not already instantiated the
        // map.
        if (mMap == null) {
            // Try to obtain the map from the SupportMapFragment.
            mMap = ((SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(R.id.map)).getMap();
            // Check if we were successful in obtaining the map.
            if (mMap != null) {
                setUpMap();
            }
            mMap.setLocationSource(this);
        }
    }

    private void setUpMap() {
        // TODO Auto-generated method stub
        mMap.setMyLocationEnabled(true);
        TileProvider geoServerTileProvider = TileProviderFactory
            .getGeoServerTileProvider();
        TileOverlay geoServerTileOverlay = mMap.addTileOverlay(
            new TileOverlayOptions()
                .tileProvider(geoServerTileProvider)
                .zIndex(10000)
                .visible(true));
    }
    // Non-relevant listener methods removed
}

TileProviderFactory

​​>
public class TileProviderFactory {

    public static GeoServerTileProvider getGeoServerTileProvider() {

        String baseURL = "mytileserver.com";
        String version = "1.3.0";
        String request = "GetMap";
        String format = "image/png";
        String srs = "EPSG:900913";
        String service = "WMS";
        String width = "256";
        String height = "256";
        String styles = "";
        String layers = "wtx:road_hazards";

        final String URL_STRING = baseURL + 
                "&LAYERS=" + layers + 
                "&VERSION=" + version + 
                "&SERVICE=" + service + 
                "&REQUEST=" + request + 
                "&TRANSPARENT=TRUE&STYLES=" + styles + 
                "&FORMAT=" + format + 
                "&SRS=" + srs + 
                "&BBOX=%f,%f,%f,%f" + 
                "&WIDTH=" + width + 
                "&HEIGHT=" + height;


        GeoServerTileProvider tileProvider = 
            new GeoServerTileProvider(256,256) {

            @Override
            public synchronized URL getTileUrl(int x, int y, int zoom) {
                try {       

                    double[] bbox = getBoundingBox(x, y, zoom);

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

                    Log.d("GeoServerTileURL", s);

                    URL url = null;

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

                    return url;
                }
                catch (RuntimeException e) {
                    Log.d("GeoServerTileException", 
                        "getTile x=" + x + ", y=" + y + 
                        ", zoomLevel=" + zoom + 
                        " raised an exception", e);
                    throw e;
                }

            }
        };
        return tileProvider;
    }
}

GeoServerTileProvider

public abstract class GeoServerTileProvider extends UrlTileProvider{

    // Web Mercator n/w corner of the map.
    private static final double[] TILE_ORIGIN = 
        {-20037508.34789244, 20037508.34789244};
    //array indexes for that data
    private static final int ORIG_X = 0; 
    private static final int ORIG_Y = 1; // "

    // Size of square world map in meters, using WebMerc projection.
    private static final double MAP_SIZE = 20037508.34789244 * 2;

    // array indexes for array to hold bounding boxes.
    protected static final int MINX = 0;
    protected static final int MINY = 1;
    protected static final int MAXX = 2;
    protected static final int MAXY = 3;

    public GeoServerTileProvider(int width, int height) {
        super(width, height);
    }

    // Return a web Mercator bounding box given tile x/y indexes and a zoom
    // level.
    protected double[] getBoundingBox(int x, int y, int zoom) {
        double tileSize = MAP_SIZE / Math.pow(2, zoom);
        double minx = TILE_ORIGIN[ORIG_X] + x * tileSize;
        double maxx = TILE_ORIGIN[ORIG_X] + (x+1) * tileSize;
        double miny = TILE_ORIGIN[ORIG_Y] - (y+1) * tileSize;
        double maxy = TILE_ORIGIN[ORIG_Y] - y * tileSize;

        double[] bbox = new double[4];
        bbox[MINX] = minx;
        bbox[MINY] = miny;
        bbox[MAXX] = maxx;
        bbox[MAXY] = maxy;
        return bbox;
    }
}

【问题讨论】:

    标签: android overlay google-maps-android-api-2 geoserver wms


    【解决方案1】:

    结果证明这是一个网络问题,与我的“正确”实现完全无关。我想这个问题对于开始使用 Android + GeoServer 实现的其他人来说是一个很好的例子,所以我将保留它。

    【讨论】:

    • 您好,您能指导我实现一个切片缓存过程以在 android 应用程序中离线显示 google 地图吗,我根据我的专业知识进行了谷歌搜索,发现使用资产文件夹实现 customTileProvider()上下文,但我不知道应该放置任何类型的切片文件,否则一旦地图在线加载,切片将自动下载,然后将被缓存并可供离线使用。
    • @AbdulWahab 抱歉,我自 2013 年以来就没有从事过这方面的工作,并且已经忘记了大部分实施细节。你最好找一个掌握最新技术的人。祝你好运:)。
    • 您是否能够将 osmdroid 用于问题中提到的用例?
    猜你喜欢
    • 2020-09-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-22
    相关资源
    最近更新 更多