TianDiTuTiledMapServiceLayer.java 8.16 KB
package com.pashanhoo.landsurvey.layers.tianditu;

import android.content.ContentValues;
import android.database.Cursor;
import android.util.Log;

import com.esri.android.map.TiledServiceLayer;
import com.esri.core.geometry.Envelope;
import com.esri.core.geometry.Point;
import com.esri.core.geometry.SpatialReference;
import com.esri.core.internal.io.handler.ResponseListener;
import com.esri.core.internal.io.handler.a;
import com.esri.core.io.UserCredentials;
import com.pashanhoo.landsurvey.utils.AppInfo;
import com.pashanhoo.landsurvey.utils.GADBHelper;

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Random;
import java.util.concurrent.RejectedExecutionException;

/**
 * Created by jiangbotao on 2018/3/23.
 */

public class TianDiTuTiledMapServiceLayer extends TiledServiceLayer {

    private static final Point originalPoint = new Point(-180, 90);

    private static final double[] res = {
            1.40625,
            0.703125,
            0.3515625,
            0.17578125,
            0.087890625,
            0.0439453125,
            0.02197265625,
            0.010986328125,
            0.0054931640625,
            0.00274658203125,
            0.001373291015625,
            0.0006866455078125,
            0.00034332275390625,
            0.000171661376953125,
            8.58306884765629E-05,
            4.29153442382814E-05,
            2.14576721191407E-05,
            1.07288360595703E-05,
            5.36441802978515E-06,
            2.68220901489258E-06,
            1.34110450744629E-06
    };
    private static final double[] scale = {
            400000000,
            295497598.5708346,
            147748799.285417,
            73874399.6427087,
            36937199.8213544,
            18468599.9106772,
            9234299.95533859,
            4617149.97766929,
            2308574.98883465,
            1154287.49441732,
            577143.747208662,
            288571.873604331,
            144285.936802165,
            72142.9684010827,
            36071.4842005414,
            18035.7421002707,
            9017.87105013534,
            4508.93552506767,
            2254.467762533835,
            1127.2338812669175,
            563.616940
    };
    private static final int levels = 21;
    private static final int dpi = 96;
    private static final int tileWidth = 256;
    private static final int tileHeight = 256;

    private ResponseListener responseListener;

    private TianDiTuLayerTypes _mapType;
    private TileInfo tiandituTileInfo;

    public TianDiTuTiledMapServiceLayer() {
        this(null, null, true);
    }

    public TianDiTuTiledMapServiceLayer(TianDiTuLayerTypes mapType) {
        this(mapType, null, true);
        GADBHelper.createTable(AppInfo.mapcachedb, _mapType.getName());
    }

    public TianDiTuTiledMapServiceLayer(TianDiTuLayerTypes mapType, UserCredentials usercredentials) {
        this(mapType, usercredentials, true);
    }

    public TianDiTuTiledMapServiceLayer(TianDiTuLayerTypes mapType, UserCredentials usercredentials, boolean flag) {
        super("");
        this._mapType = mapType;
        setCredentials(usercredentials);

        if (flag)
            try {
                getServiceExecutor().submit(new Runnable() {

                    public final void run() {
                        a.initLayer();
                    }

                    final TianDiTuTiledMapServiceLayer a;

                    {
                        a = TianDiTuTiledMapServiceLayer.this;
                        //super();
                    }
                });
                return;
            } catch (RejectedExecutionException _ex) {
            }
    }

    public static double[] getRes() {
        return res;
    }

    public TianDiTuLayerTypes getMapType() {
        return this._mapType;
    }

    protected void initLayer() {
        this.tiandituTileInfo = new com.esri.android.map.TiledServiceLayer.TileInfo(originalPoint, scale, res, levels, dpi, tileWidth, tileHeight);
        this.setTileInfo(this.tiandituTileInfo);
        this.setFullExtent(new Envelope(-180, -90, 180, 90));
        this.setDefaultSpatialReference(SpatialReference.create(4490));   //CGCS2000
        //this.setDefaultSpatialReference(SpatialReference.create(4326));
        this.setInitialExtent(new Envelope(90.52, 33.76, 113.59, 42.88));
        super.initLayer();
    }

    public void refresh() {
        try {
            getServiceExecutor().submit(new Runnable() {

                public final void run() {
                    if (a.isInitialized())
                        try {
                            a.b();
                            a.clearTiles();
                            return;
                        } catch (Exception exception) {
                            Log.e("ArcGIS", "Re-initialization of the layer failed.", exception);
                        }
                }

                final TianDiTuTiledMapServiceLayer a;

                {
                    a = TianDiTuTiledMapServiceLayer.this;
                    //super();
                }
            });
            return;
        } catch (RejectedExecutionException _ex) {
            return;
        }
    }

    final void b()
            throws Exception {

    }

    @Override
    protected byte[] getTile(int level, int col, int row) throws Exception {
        byte[] result = null;

        StringBuilder url = new StringBuilder("http://t");
        Random random = new Random();
        int subdomain = (random.nextInt(6) + 1);
        url.append(subdomain);
        switch (this._mapType) {
            case VEC_C:
                url.append(".tianditu.com/DataServer?T=vec_c&X=").append(col).append("&Y=").append(row).append("&L=").append(level);
                break;
            case CVA_C:
                url.append(".tianditu.com/DataServer?T=cva_c&X=").append(col).append("&Y=").append(row).append("&L=").append(level);
                break;
            case CIA_C:
                url.append(".tianditu.com/DataServer?T=cia_c&X=").append(col).append("&Y=").append(row).append("&L=").append(level);
                break;
            case IMG_C:
                url.append(".tianditu.com/DataServer?T=img_c&X=").append(col).append("&Y=").append(row).append("&L=").append(level);
                break;
            default:
                return null;
        }

        try {
            // 首先从离线数据库中读取
            result = getOfflineCacheDB(level, col, row);
            // 如果没有就直接从web上读取
            if (result == null) {
                result = com.esri.core.internal.io.handler.a.a(url.toString(), null, null, this.responseListener);
                // 将读取的数据存入mbtiles中
                AddOfflineCacheDB(level, col, row, result);
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        return result;
    }

    private void AddOfflineCacheDB(int level, int col, int row, byte[] bytes) {
        ContentValues values = new ContentValues();
        values.put("TILELEVEL", level);
        values.put("TILECOL", col);
        values.put("TILEROW", row);
        values.put("TILEDATA", bytes);

        AppInfo.mapcachedb.insert(_mapType.getName(), null, values);
    }


    private byte[] getOfflineCacheDB(int level, int col, int row) throws Exception {

        byte[] result = null;
        String sql = "select * from " + _mapType.getName() + " where TILELEVEL = " + level + " and TILECOL = " + col + " and TILEROW = " + row;
        Cursor mCursor = AppInfo.mapcachedb.rawQuery(sql, null);
        boolean hasData = false;

        while (mCursor.moveToNext()) {//判断是否存在数据
            hasData = true;
        }
        if (hasData) {//数据库中有数据
            try {
                if (mCursor.moveToFirst()) {
                    result = mCursor.getBlob(mCursor.getColumnIndex("TILEDATA"));
                }
                mCursor.close();
            } catch (Exception e) {
                e.printStackTrace();
                result = null;
            }
        }
        return result;
    }

    @Override
    public TileInfo getTileInfo() {
        return this.tiandituTileInfo;
    }


}