今天搞了一个ArcGIS API For Android离线地图的实现。
效果如下:
Android的版本是2.1
main.xml,这里要说明的,初始化范围一定要有,不然会不能显示的。
<?xml version="1.0" encoding="utf-8"?> <com.esri.android.map.MapView xmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/map"android:layout_width="fill_parent"android:layout_height="fill_parent"initExtent="120.64101459999999 31.280566089 120.6769494 31.303135911"> <com.esri.arcgis.sample.AgsOfflineTiledLayer android:id="@+id/layer"/> </com.esri.android.map.MapView>
AgsLOD.java
packagecom.esri.arcgis.sample; importcom.esri.core.internal.d.c; public class AgsLOD extendsc { private static final long serialVersionUID = 4341699179151728883L; private intlevel; private doubleresolution; private doublescale; public AgsLOD(int level, double scale, doubleresolution) { super(); this.level =level; this.scale =scale; this.resolution =resolution; } public inta() { return this.level; } public doubleb() { return this.resolution; } public doublec() { return this.scale; } }
AgsOfflineTiledLayer.java
packagecom.esri.arcgis.sample; importjava.io.File; importjava.util.ArrayList; importjavax.xml.parsers.DocumentBuilder; importjavax.xml.parsers.DocumentBuilderFactory; importorg.w3c.dom.Document; importorg.w3c.dom.Node; importorg.w3c.dom.NodeList; importandroid.content.Context; importandroid.util.AttributeSet; importandroid.util.Log; importcom.esri.android.map.TiledLayer; importcom.esri.core.geometry.Envelope; importcom.esri.core.geometry.Point; importcom.esri.core.geometry.SpatialReference; importcom.esri.core.internal.d.c; importcom.esri.core.internal.d.k; importcom.esri.core.map.TiledLayerModel; public class AgsOfflineTiledLayer extendsTiledLayer { //瓦片文件的路径呀 private String location = "/sdcard/BaseMap/Layers"; //REST里面的空间参考 private SpatialReference spatialReference = SpatialReference.create(4326); //全图范围 private Envelope fullExtent = new Envelope(120.64101459999999, 31.280566089, 120.6769494, 31.303135911); privatek tileInfo; publicAgsOfflineTiledLayer(Context context, AttributeSet attrs) { super(context, attrs); try{ init(); } catch(Exception ex) { ex.printStackTrace(); } } @Override protected TiledLayerModel initModel() throwsException { return newAgsOfflineTiledLayerModel(location, spatialReference, fullExtent, tileInfo); } private voidinit() { String confPath = location + File.separator + "conf.xml"; Log.i("conf", confPath); try{ tileInfo = newk(); DocumentBuilderFactory docBuilderFactory =DocumentBuilderFactory .newInstance(); DocumentBuilder docBuilder =docBuilderFactory.newDocumentBuilder(); File file = newFile(confPath); Document doc =docBuilder.parse(file); NodeList nsX = doc.getElementsByTagName("X"); double originX = Double.valueOf(nsX.item(0).getFirstChild() .getNodeValue()); NodeList nsY = doc.getElementsByTagName("Y"); double originY = Double.valueOf(nsY.item(0).getFirstChild() .getNodeValue()); tileInfo.f = newPoint(originX, originY); NodeList nsTileRows = doc.getElementsByTagName("TileRows"); tileInfo.a = Integer.valueOf(nsTileRows.item(0).getFirstChild() .getNodeValue()); NodeList nsTileCols = doc.getElementsByTagName("TileCols"); tileInfo.b = Integer.valueOf(nsTileCols.item(0).getFirstChild() .getNodeValue()); NodeList nsLODInfos = doc.getElementsByTagName("LODInfos"); tileInfo.h = new ArrayList<c>(); NodeList lodInfos = nsLODInfos.item(0).getChildNodes(); for (int j = 0, jcount = lodInfos.getLength(); j < jcount; j++) { Node lod =lodInfos.item(j); NodeList list =lod.getChildNodes(); int level = Integer.valueOf(list.item(0).getFirstChild() .getNodeValue()); double scale = Double.valueOf(list.item(1).getFirstChild() .getNodeValue()); double resolution = Double.valueOf(list.item(2).getFirstChild() .getNodeValue()); tileInfo.h.add(newAgsLOD(level, scale, resolution)); } } catch(Exception e) { e.printStackTrace(); } } }
AgsOfflineTiledLayerModel.java
packagecom.esri.arcgis.sample; importjava.io.File; importjava.io.FileInputStream; importandroid.util.Log; importcom.esri.core.geometry.Envelope; importcom.esri.core.geometry.SpatialReference; importcom.esri.core.internal.d.k; importcom.esri.core.map.TiledLayerModel; public class AgsOfflineTiledLayerModel extendsTiledLayerModel { private static final long serialVersionUID = 7726567118839553087L; privateString location; publicAgsOfflineTiledLayerModel(String location, SpatialReference sr, Envelope full, k tileInfo) { super(sr, full, tileInfo); this.location =location; } @Override public byte[] getTile(int level, int row, int col) throwsException { byte[] result = null; try{ String bundlesDir = location + File.separator + "_alllayers"; Log.i("location", bundlesDir); String l = "0" +level; int lLength =l.length(); if (lLength > 2) { l = l.substring(lLength - 2); } l = "L" +l; int rGroup = 128 * (row / 128); String r = "000" +Integer.toHexString(rGroup); int rLength =r.length(); if (rLength > 4) { r = r.substring(rLength - 4); } r = "R" +r; int cGroup = 128 * (col / 128); String c = "000" +Integer.toHexString(cGroup); int cLength =c.length(); if (cLength > 4) { c = c.substring(cLength - 4); } c = "C" +c; String bundleBase =String .format("%s/%s/%s%s", bundlesDir, l, r, c); String bundlxFileName = bundleBase + ".bundlx"; String bundleFileName = bundleBase + ".bundle"; int index = 128 * (col - cGroup) + (row -rGroup); FileInputStream isBundlx = newFileInputStream(bundlxFileName); isBundlx.skip(16 + 5 *index); byte[] buffer = new byte[5]; isBundlx.read(buffer); long offset = (long) (buffer[0] & 0xff) + (long) (buffer[1] & 0xff) * 256 + (long) (buffer[2] & 0xff) * 65536 + (long) (buffer[3] & 0xff) * 16777216 + (long) (buffer[4] & 0xff) * 4294967296L; FileInputStream isBundle = newFileInputStream(bundleFileName); isBundle.skip(offset); byte[] lengthBytes = new byte[4]; isBundle.read(lengthBytes); int length = (int) (lengthBytes[0] & 0xff) + (int) (lengthBytes[1] & 0xff) * 256 + (int) (lengthBytes[2] & 0xff) * 65536 + (int) (lengthBytes[3] & 0xff) * 16777216; result = new byte[length]; isBundle.read(result); } catch(Exception ex) { ex.printStackTrace(); } returnresult; } }
AgsOfflineTiles.java
packagecom.esri.arcgis.sample; importcom.esri.android.map.MapView; importandroid.app.Activity; importandroid.os.Bundle; public class AgsOfflineTiles extendsActivity { MapView map = null; AgsOfflineTiledLayer layer = null; /**Called when the activity is first created. */@Override public voidonCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); map =(MapView) findViewById(R.id.map); layer =(AgsOfflineTiledLayer) findViewById(R.id.layer); } }
在SD卡的瓦片数据的路径
源码和测试数据在附件中
BaseMap.rar (1.5 MB)
AgsOfflineTiles.rar (2.4 MB)