ArcGIS for Android Runtime 100 Advanced Functions (I) - Internet Map Loading Reference and Caching

Keywords: Mobile Google Android network

The last version of arcgis for android is 10.2.9. It is said that the version will not be updated and maintained after that, but will jump directly to the 100 series, which is quite different from the previous version. But it also adds more functions and optimizes performance a lot. Specific differences are not repeated here, more than 100 versions will be able to feel.

This section mainly talks about the new version of the Internet map reference, mainly refers to the commonly used sky map, Google Map. In fact, loading Baidu and Golden Maps is the same principle, but because their map coordinate data are Mars coordinates, for professional GIS development, it can not be used.

1. Overload ImageTiled Layer. There are two main methods to implement.

One is the constructor: protected Image Tiled Layer (Tile Info tileInfo, Envelope full Extent)

One is tile download function: protected abstract byte[] getTile(TileKey var1)

2. According to our previous experience, the constructor is mainly the TileInfo parameter construction, which can be carried over.

Code directly

BaseMapLayer class

public class BaseMapLayer extends ImageTiledLayer {

    //Sky-Earth, Google Vector Map and Image Map Constants
    public static final int MAPLAYER_TIANDI_VECTOR = 1;
    public static final int MAPLAYER_TIANDI_IMAGE = 2;
    public static final int MAPLAYER_GOOGLE_VECTOR = 3;
    public static final int MAPLAYER_GOOGLE_IMAGE = 4;
    //Image map labeling constants
    public static final int MAPLAYER_TIANDI_IMAGE_LABEL = 5;
    public static final int MAPLAYER_TIANDI_VECTOR_LABEL = 6;



    private static double[] scales = new double[]{591657527.591555,
            295828763.79577702, 147914381.89788899, 73957190.948944002,
            36978595.474472001, 18489297.737236001, 9244648.8686180003,
            4622324.4343090001, 2311162.217155, 1155581.108577, 577790.554289,
            288895.277144, 144447.638572, 72223.819286, 36111.909643,
            18055.954822, 9027.9774109999998, 4513.9887049999998, 2256.994353,
            1128.4971760000001};
    private static double[] resolutions = new double[]{156543.03392800014,
            78271.516963999937, 39135.758482000092, 19567.879240999919,
            9783.9396204999593, 4891.9698102499797, 2445.9849051249898,
            1222.9924525624949, 611.49622628138, 305.748113140558,
            152.874056570411, 76.4370282850732, 38.2185141425366,
            19.1092570712683, 9.55462853563415, 4.7773142679493699,
            2.3886571339746849, 1.1943285668550503, 0.59716428355981721,
            0.29858214164761665};
    private static Point origin = new Point(-20037508.342787, 20037508.342787, SpatialReference.create(3857));

    int type = 0;

    protected BaseMapLayer(TileInfo tileInfo, Envelope fullExtent) {
        super(tileInfo, fullExtent);
    }

    protected BaseMapLayer(CoreImageTiledLayer coreTiledLayer, boolean addToCache) {
        super(coreTiledLayer, addToCache);
    }

    public static BaseMapLayer CreateBaseMapLayer(int type) {

        List<LevelOfDetail> levelOfDetails = MapTilesTool.getLevelOfDetails();

        try {
            TileInfo tileInfo = new TileInfo(96, TileInfo.ImageFormat.MIXED, levelOfDetails
                    , origin
                    , SpatialReference.create(3857)
                    , 256, 256);

            Envelope fullExtent = new Envelope(-22041257.773878,
                    -32673939.6727517, 22041257.773878, 20851350.0432886, SpatialReference.create(3857));
            BaseMapLayer layer = new BaseMapLayer(tileInfo, fullExtent);
            layer.type = type;
            return layer;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }


    public static String getUrl(int type) {
        String[] subDomains = null;
        String urlPart = "";
        String flag = "";

        switch (type) {
            case MAPLAYER_TIANDI_VECTOR://Sky Map Vector Map
                subDomains = new String[]{"t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7"};
                urlPart = ".tianditu.com/DataServer?T=vec_w";
                flag = "l";

                break;
            case MAPLAYER_TIANDI_IMAGE://Sky Map Image Map
                subDomains = new String[]{"t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7"};
                urlPart = ".tianditu.com/DataServer?T=img_w";
                flag = "l";

                break;
            case MAPLAYER_GOOGLE_VECTOR://Google Vector Map
                subDomains = new String[]{"mt0", "mt1", "mt2", "mt3"};
                urlPart = ".google.cn/vt/hl=zh-CN";
                flag = "z";

                break;
            case MAPLAYER_GOOGLE_IMAGE://Google Image Map
                subDomains = new String[]{"mt0", "mt1", "mt2", "mt3"};
                urlPart = ".google.cn/vt/lyrs=s@105&hl=zh-CN";
                flag = "z";

                break;
            case MAPLAYER_TIANDI_IMAGE_LABEL://Sky Map Image Map Labeling
                subDomains = new String[]{"t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7"};
                urlPart = ".tianditu.com/DataServer?T=cia_w";
                flag = "l";

                break;
            case MAPLAYER_TIANDI_VECTOR_LABEL://Vector Map Labeling of Sky Map
                subDomains = new String[]{"t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7"};
                urlPart = ".tianditu.com/DataServer?T=cva_w";
                flag = "l";
                break;
        }
        if (subDomains != null) {
            String subDomain = subDomains[new Random().nextInt(100) % subDomains.length];

            String url = "http://" + subDomain + urlPart + "&x=%d&" + "y=%d&" + flag + "=%d";
            return url;
        }
        return null;
    }

    public static double getResolution(int level) {
        if (level < resolutions.length)
            return resolutions[level];
        else
            return 1;
    }

    @Override
    protected byte[] getTile(TileKey tileKey) {
        byte[] iResult = null;
        String mapCache = CacheUtil.getMapCache() + "//";
        mapCache += type + "//";
        mapCache += tileKey.getLevel();
        File f0 = new File(mapCache);
        if (!f0.exists()) {
            f0.mkdirs();
        }
        String fileName = String.format("%d_%d.dat", tileKey.getColumn(), tileKey.getRow());
        File f = new File(mapCache + "//" + fileName);
        if (f.exists()) {
            iResult = CacheUtil.ReadFile(f.getPath());
        }
        if (iResult == null || iResult.length == 0) {
            try {
                boolean hasNetwork = MapTilesTool.isNetworkConnected();
                if (!hasNetwork) return null;
                String baseUrl = getUrl(type);
                if (baseUrl == null) return new byte[0];
                String url = String.format(baseUrl, tileKey.getColumn(), tileKey.getRow(), tileKey.getLevel());
                iResult = downTile(url);
                if (iResult != null)
                    CacheUtil.WriteFile(f.getPath(), iResult);
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
        return iResult;
    }

    private byte[] downTile(String iPath) {
        try {
            //Links to resources
            URL url = new URL(iPath);

            InputStream inputStream = url.openStream();
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            // Start reading data
            byte[] buffer = new byte[1024];
            int len = 0;// Length of data read at a time
            while ((len = inputStream.read(buffer)) != -1) {// When len is - 1, it means there is no data.
                // append method adds data to sb object
                outputStream.write(buffer, 0, len);
            }
            inputStream.close();
            // Output string
            return outputStream.toByteArray();

        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return new byte[0];
    }
}

 

MapTilesTool class

public class MapTilesTool {

    private static double[] scales = new double[]{591657527.591555,
            295828763.79577702, 147914381.89788899, 73957190.948944002,
            36978595.474472001, 18489297.737236001, 9244648.8686180003,
            4622324.4343090001, 2311162.217155, 1155581.108577, 577790.554289,
            288895.277144, 144447.638572, 72223.819286, 36111.909643,
            18055.954822, 9027.9774109999998, 4513.9887049999998, 2256.994353,
            1128.4971760000001};

    private static double[] resolutions = new double[]{156543.03392800014,
            78271.516963999937, 39135.758482000092, 19567.879240999919,
            9783.9396204999593, 4891.9698102499797, 2445.9849051249898,
            1222.9924525624949, 611.49622628138, 305.748113140558,
            152.874056570411, 76.4370282850732, 38.2185141425366,
            19.1092570712683, 9.55462853563415, 4.7773142679493699,
            2.3886571339746849, 1.1943285668550503, 0.59716428355981721,
            0.29858214164761665};

    public static MapServerTileInfo PJson2MapServerInfo(MapServerPJson pJson) {

        if (pJson == null || pJson.getTileInfo() == null) {
            return null;
        }
        MapServerTileInfo tileInfo = new MapServerTileInfo();
        tileInfo.dpi = pJson.getTileInfo().getDpi();
        tileInfo.tileHeight = pJson.getTileInfo().getCols();
        tileInfo.tileWidth = pJson.getTileInfo().getRows();
        int wkid = pJson.getTileInfo().getSpatialReference().getWkid();
        tileInfo.spatialReference = SpatialReference.create(wkid);
        tileInfo.origin = new Point(pJson.getTileInfo().getOrigin().getX()
                , pJson.getTileInfo().getOrigin().getY()
                , SpatialReference.create(wkid));

        MapServerPJson.FullExtentBean fullExtentBean = pJson.getFullExtent();
        tileInfo.fullExtent = new Envelope(fullExtentBean.getXmin(), fullExtentBean.getYmin(), fullExtentBean.getXmax(),
                fullExtentBean.getYmax(), SpatialReference.create(wkid));
        int i = 0;
        List<LevelOfDetail> levelOfDetails = new ArrayList<>();
        for (MapServerPJson.TileInfoBean.LodsBean lodsBean : pJson.getTileInfo().getLods()) {
            LevelOfDetail detail = new LevelOfDetail(i, lodsBean.getResolution(), lodsBean.getScale());
            levelOfDetails.add(detail);
            i++;
        }
        tileInfo.levelOfDetails = levelOfDetails;
        tileInfo.minScale = pJson.getMinScale();
        tileInfo.maxScale = pJson.getMaxScale();
        return tileInfo;
    }

    public static List<LevelOfDetail> getLevelOfDetails() {

        List<LevelOfDetail> levelOfDetails = new ArrayList<>();
        int level = 0;
        for (; level < scales.length; level++) {
            LevelOfDetail detail = new LevelOfDetail(level, resolutions[level], scales[level]);
            levelOfDetails.add(detail);
        }
        return levelOfDetails;
    }

    public static int getLevel(double scale) {
        int level = scales.length - 1;
        double minStep = Double.MAX_VALUE;
        for (int i = 0; i < scales.length; i++) {
            double sca = scales[i];
            if (Math.abs(scale - sca) < minStep) {
                minStep = Math.abs(scale - sca);
                level = i;
            }
        }
        return level;
    }

    public static double getResolution(int level) {
        if (level < resolutions.length)
            return resolutions[level];
        else
            return 1;
    }
    //Is there a network?
    public static boolean isNetworkConnected() {

        ConnectivityManager mConnectivityManager = (ConnectivityManager) NSCApplication.mContext
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo mNetworkInfo = mConnectivityManager.getActiveNetworkInfo();
        if (mNetworkInfo != null) {
            return mNetworkInfo.isAvailable();
        }
        return false;

    }

}

Load to map

  final BaseMapLayer webTiledLayer = BaseMapLayer.CreateBaseMapLayer(OtherMapLayer.MAPLAYER_TIANDI_VECTOR);
        webTiledLayer.loadAsync();
        webTiledLayer.addDoneLoadingListener(new Runnable() {
            @Override
            public void run() {
                if (webTiledLayer.getLoadStatus() == LoadStatus.LOADED) {
                    ArcGISMap map = new ArcGISMap(new Basemap(webTiledLayer));
                    mMapView.setMap(map);
                    mMapView.getGraphicsOverlays().add(overlay);
                }
            }
        });

 

The getTile in BaseMapLayer has implemented the downloading, loading and management of cache tiles.

Posted by shinephp on Thu, 31 Jan 2019 10:09:15 -0800