Skip to content

Instantly share code, notes, and snippets.

@kiichi
Last active August 13, 2019 12:33
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save kiichi/6119073 to your computer and use it in GitHub Desktop.
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/
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);
}
}
}
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","");
}
}
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);
}
}
}
@shivapooja
Copy link

Sir pls send me complete source to import shapefile onto map offline. in your code i cant find .zip file

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment