Last active
August 13, 2019 12:33
-
-
Save kiichi/6119073 to your computer and use it in GitHub Desktop.
ShapeFile in Android Demo using OpenMap Library.
Reading .shp and .dbf files after extracting the zip file into the external storage area. Learn Android Programming in our Online Course
http://liu.edu/gis/
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package edu.liu.shapefileexample; | |
// Note: | |
// This is my modified version for educational purpose by Kiichi Takeuchi. I removed swing dependency and changed class name. | |
// | |
// ********************************************************************** | |
// | |
// <copyright> | |
// | |
// BBN Technologies, a Verizon Company | |
// 10 Moulton Street | |
// Cambridge, MA 02138 | |
// (617) 873-8000 | |
// | |
// Copyright (C) BBNT Solutions LLC. All rights reserved. | |
// | |
// </copyright> | |
// ********************************************************************** | |
// | |
// $Source: /cvs/distapps/openmap/com/bbn/openmap/dataAccess/shape/input/DbfInputStream.java,v $ | |
// $RCSfile: DbfInputStream.java,v $ | |
// $Revision: 1.1.2.1 $ | |
// $Date: 2002/10/25 17:43:42 $ | |
// $Author: dietrick $ | |
// | |
// ********************************************************************** | |
import com.bbn.openmap.dataAccess.shape.input.LittleEndianInputStream; | |
//package com.bbn.openmap.dataAccess.shape.input; | |
import com.bbn.openmap.dataAccess.shape.*; | |
import java.io.*; | |
import java.util.ArrayList; | |
/** | |
* Reads the contents of a DBF file and provides access to what it has read | |
* through several get methods | |
* @author Doug Van Auken | |
*/ | |
public class DbfInputStream2 { | |
/** An input stream to process primitives in Little Endian or Big Endian */ | |
private LittleEndianInputStream _leis = null; | |
/** An array of column names, as read from the field descripter array */ | |
private String[] _columnNames = null; | |
/** An array of column lengths, as read from the field descripter array */ | |
private byte[] _lengths = null; | |
/** An array of decimal counts, as read from the field descripter array */ | |
private byte[] _decimalCounts = null; | |
/** An array of column types, as read from the field descripter array */ | |
private byte[] _types = null; | |
/** The number of columns */ | |
private int _columnCount = -1; | |
/** The number of rows */ | |
private int _rowCount = -1; | |
/** The header length */ | |
private short _headerLength = -1; | |
/** The record length */ | |
private short _recordLength = -1; | |
/** An ArrayList with each element representing a record, which itself is an ArrayList */ | |
private ArrayList _records = null; | |
/** | |
* Creates a LittleEndianInputStream then uses it to read the contents | |
* of the DBF file | |
* @param is An inputstream used to create a LittleEndianInputStream | |
*/ | |
public DbfInputStream2(InputStream is) throws Exception { | |
BufferedInputStream bis = new BufferedInputStream(is); | |
_leis = new LittleEndianInputStream(bis); | |
readHeader(); | |
readFieldDescripters(); | |
readData(); | |
} | |
/** | |
* Returns an array of column names | |
* @return An array of column names | |
*/ | |
public String[] getColumnNames(){ | |
return _columnNames; | |
} | |
/** | |
* Returns an array of character lengths | |
* @return An array of character lengths | |
*/ | |
public byte[] getLengths(){ | |
return _lengths; | |
} | |
/** | |
* Returns an array of decimal counts | |
* @return An array of decimal counts | |
*/ | |
public byte[] getDecimalCounts(){ | |
return _decimalCounts; | |
} | |
/** | |
* Returns an array of field types | |
* @return An array of field types | |
*/ | |
public byte[] getTypes() { | |
return _types; | |
} | |
/** | |
* Returns an ArrayList of records | |
* @return An ArrayList of recrods | |
*/ | |
public ArrayList getRecords(){ | |
return _records; | |
} | |
/** | |
* Returns the number of columns | |
* @return The nunber of columns | |
*/ | |
public int getColumnCount(){ | |
return _columnCount; | |
} | |
/** | |
* Returns the number of rows | |
* @return The number of rows | |
*/ | |
public int getRowCount(){ | |
return _rowCount; | |
} | |
/** | |
* Reads the header | |
*/ | |
private void readHeader() throws IOException { | |
byte description = _leis.readByte(); | |
byte year = _leis.readByte(); | |
byte month = _leis.readByte(); | |
byte day = _leis.readByte(); | |
_rowCount = _leis.readLEInt(); | |
_headerLength = _leis.readLEShort(); | |
_recordLength = _leis.readLEShort(); | |
_columnCount = (_headerLength - 32 - 1) / 32; | |
_leis.skipBytes(20); | |
} | |
/** | |
* Initializes arrays that hold column names, column types, character | |
* lengths, and decimal counts, then populates them | |
*/ | |
private void readFieldDescripters() throws IOException { | |
_columnNames = new String[_columnCount]; | |
_types = new byte[_columnCount]; | |
_lengths = new byte[_columnCount]; | |
_decimalCounts = new byte[_columnCount]; | |
for (int n=0; n<=_columnCount-1; n++) { | |
_columnNames[n] = _leis.readString(11); | |
_types[n] = (byte)_leis.readByte(); | |
_leis.skipBytes(4); | |
_lengths[n] = _leis.readByte(); | |
_decimalCounts[n] = _leis.readByte(); | |
_leis.skipBytes(14); | |
} | |
} | |
/** | |
* Reads the data and places data in a class scope ArrayList of records | |
*/ | |
public void readData() throws IOException { | |
_leis.skipBytes(2); | |
_records = new ArrayList(); | |
for (int r=0; r <= _rowCount - 1; r++) { | |
ArrayList record = new ArrayList(); | |
for (int c = 0; c <= _columnCount - 1; c++) { | |
int length = _lengths[c]; | |
int type = _types[c]; | |
String cell = _leis.readString(length); | |
if (type == DbfTableModel.TYPE_NUMERIC && !cell.equals("")) { | |
record.add(c, new Double(cell)); | |
} else { | |
record.add(c, cell); | |
} | |
} | |
_records.add(record); | |
_leis.skipBytes(1); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package edu.liu.shapefileexample; | |
import android.content.Context; | |
import android.content.res.AssetManager; | |
import android.util.Log; | |
import java.io.BufferedOutputStream; | |
import java.io.File; | |
import java.io.FileOutputStream; | |
import java.io.IOException; | |
import java.util.zip.ZipEntry; | |
import java.util.zip.ZipInputStream; | |
/** | |
* Created by kiichi on 7/21/13. | |
*/ | |
//<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> | |
public class Installer { | |
// context = activity | |
// assetName = "shapefile.zip" | |
// | |
public static String unzip(Context context, String assetName, String destPath, boolean overwrite){ | |
// Create a directory in the SDCard to store the files | |
File file = new File(destPath); | |
if (!file.exists()){ | |
file.mkdirs(); | |
} | |
else{ | |
file.delete(); | |
} | |
try{ | |
// Open the ZipInputStream | |
ZipInputStream inputStream = new ZipInputStream(context.getAssets().open(assetName)); | |
// from the first entry (copressed first file), until you get null, keep getting next file | |
for (ZipEntry entry = inputStream.getNextEntry(); entry != null; entry = inputStream.getNextEntry()){ | |
String innerFileName = destPath + File.separator + entry.getName(); | |
File innerFile = new File(innerFileName); | |
//if overwrite option is on and file already exists, delete | |
if (innerFile.exists()) { | |
if (overwrite == false ){ | |
Log.v("myapp","Skipping... "+ innerFileName); | |
continue; | |
} | |
else { | |
innerFile.delete(); | |
} | |
} | |
Log.v("myapp","Extracting: " + entry.getName() + "..."); | |
// Check if it is a folder | |
if (entry.isDirectory()){ | |
// Its a folder, create that folder | |
innerFile.mkdirs(); | |
} | |
else{ | |
// Create a file output stream | |
FileOutputStream outputStream = new FileOutputStream(innerFileName); | |
final int BUFFER = 2048; | |
// Buffer the ouput to the file | |
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outputStream,BUFFER); | |
// Write the contents | |
int count = 0; | |
byte[] data = new byte[BUFFER]; | |
while ((count = inputStream.read(data, 0, BUFFER)) != -1){ | |
bufferedOutputStream.write(data, 0, count); | |
} | |
// Flush and close the buffers | |
bufferedOutputStream.flush(); | |
bufferedOutputStream.close(); | |
} | |
Log.v("myapp","DONE"); | |
// Close the current entry | |
inputStream.closeEntry(); | |
} | |
inputStream.close(); | |
} | |
catch (IOException e){ | |
Log.v("myapp","error = " + e); | |
e.printStackTrace(); | |
} | |
return destPath + File.separator + assetName.replace(".zip",""); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package edu.liu.shapefileexample; | |
import android.app.Activity; | |
import android.content.res.AssetFileDescriptor; | |
import android.content.res.AssetManager; | |
import android.graphics.Color; | |
import android.net.Uri; | |
import android.os.Bundle; | |
import android.os.Environment; | |
import android.util.Log; | |
import com.bbn.openmap.dataAccess.shape.DbfFile; | |
import com.bbn.openmap.dataAccess.shape.DbfTableModel; | |
import com.bbn.openmap.dataAccess.shape.ShapeUtils; | |
import com.bbn.openmap.dataAccess.shape.input.DbfInputStream; | |
import com.bbn.openmap.layer.shape.ESRIPoly; | |
import com.bbn.openmap.layer.shape.ESRIPolygonRecord; | |
import com.bbn.openmap.layer.shape.ESRIRecord; | |
import com.bbn.openmap.layer.shape.ShapeFile; | |
import com.bbn.openmap.layer.shape.ShapeLayer; | |
import com.google.android.gms.maps.CameraUpdate; | |
import com.google.android.gms.maps.CameraUpdateFactory; | |
import com.google.android.gms.maps.GoogleMap; | |
import com.google.android.gms.maps.MapFragment; | |
import com.google.android.gms.maps.model.LatLng; | |
import com.google.android.gms.maps.model.MarkerOptions; | |
import com.google.android.gms.maps.model.PolygonOptions; | |
import java.io.File; | |
import java.io.FileInputStream; | |
import java.io.FileReader; | |
import java.io.IOException; | |
import java.util.ArrayList; | |
public class MyActivity extends Activity { | |
@Override | |
public void onCreate(Bundle savedInstanceState) { | |
super.onCreate(savedInstanceState); | |
setContentView(R.layout.main); | |
MapFragment mapFragment = (MapFragment)getFragmentManager().findFragmentById(R.id.map); | |
final GoogleMap map = mapFragment.getMap(); | |
map.setMapType(GoogleMap.MAP_TYPE_NORMAL); | |
LatLng centerLatLng = new LatLng(40.776902,-73.969284); | |
CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(centerLatLng, 3); | |
map.moveCamera(cameraUpdate); | |
try { | |
String path = Environment.getExternalStorageDirectory().toString(); | |
//String fileName = "tl_2012_us_state.zip"; | |
String fileName = "TM_WORLD_BORDERS_SIMPL.zip"; | |
// extracted file name would be "(zip file name)/(extracted file name).ext" | |
String destPath = Installer.unzip(getApplicationContext(),fileName,path,false); | |
String targetFilePath = destPath + File.separator + "TM_WORLD_BORDERS_SIMPL.shp"; | |
Log.v("myapp","path = " + targetFilePath); | |
ShapeFile shapeFile = new ShapeFile(targetFilePath); | |
// DbfInputStream2 modification is for educational purpose only. | |
// I took the source code of DbfInputStream and remove swing import. | |
// note, you have to put the modification as public domain. read bbn license here | |
// http://openmap.bbn.com/license.html | |
FileInputStream fileInputStream = new FileInputStream(new File(destPath + File.separator + "TM_WORLD_BORDERS_SIMPL.dbf")); | |
DbfInputStream2 dbfInputStream = new DbfInputStream2(fileInputStream); | |
Log.v("myapp","row 200, column 4 = "+ ((ArrayList)dbfInputStream.getRecords().get(200)).get(4)); | |
for (ESRIRecord esriRecord = shapeFile.getNextRecord(); esriRecord!=null;esriRecord = shapeFile.getNextRecord()){ | |
String shapeTypeStr = ShapeUtils.getStringForType(esriRecord.getShapeType()); | |
Log.v("myapp","shape type = " + esriRecord.getRecordNumber() + "-" + shapeTypeStr); | |
// In QGIS, US is 208 but index starts from 0 so add 1 | |
if (esriRecord.getRecordNumber() != 209){ | |
continue; | |
} | |
if (shapeTypeStr.equals("POLYGON")) { | |
// cast type after checking the type | |
ESRIPolygonRecord polyRec = (ESRIPolygonRecord)esriRecord; | |
Log.v("myapp","number of polygon objects = " + polyRec.polygons.length); | |
for (int i=0; i<polyRec.polygons.length; i++){ | |
// read for a few layers | |
ESRIPoly.ESRIFloatPoly poly = (ESRIPoly.ESRIFloatPoly)polyRec.polygons[i]; | |
PolygonOptions polygonOptions = new PolygonOptions(); | |
polygonOptions.strokeColor(Color.argb(150,200,0,0)); | |
polygonOptions.fillColor(Color.argb(150,0,0,150)); | |
polygonOptions.strokeWidth(2.0f); | |
Log.v("myapp","Points in the polygon = " + poly.nPoints); | |
for (int j=0; j<poly.nPoints; j++){ | |
//Log.v("myapp",poly.getY(j) + "," + poly.getX(j)); | |
polygonOptions.add(new LatLng(poly.getY(j), poly.getX(j))); | |
} | |
map.addPolygon(polygonOptions); | |
Log.v("myapp","polygon added"); | |
} | |
} | |
else { | |
Log.v("myapp","error polygon not found (type = " + esriRecord.getShapeType() + ")"); | |
} | |
} | |
} catch (Exception e) { | |
e.printStackTrace(); | |
Log.v("myapp","error=" + e); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Sir pls send me complete source to import shapefile onto map offline. in your code i cant find .zip file