├── .gitignore~ ├── .gitignore ├── lint.xml ├── libs ├── jts-1.12.jar ├── armeabi │ └── libjsqlite.so └── spatialite-android-library.jar ├── res ├── drawable-hdpi │ └── icon.png ├── drawable-ldpi │ └── icon.png ├── drawable-mdpi │ ├── file.png │ ├── folder.png │ └── icon.png ├── values │ └── strings.xml └── layout │ ├── canvas.xml │ ├── listview_item.xml │ └── main.xml ├── gen └── com │ └── spatialite │ ├── BuildConfig.java │ └── R.java ├── META-INF └── MANIFEST.MF ├── src └── com │ └── spatialite │ ├── MessageType.java │ ├── QueryDataThread.java │ ├── TestActivity.java │ └── MapCanvas.java ├── local.properties ├── .classpath ├── project.properties ├── .settings └── org.eclipse.jdt.core.prefs ├── README.md ├── proguard-project.txt ├── AndroidManifest.xml ├── proguard.cfg └── .project /.gitignore~: -------------------------------------------------------------------------------- 1 | bin/ 2 | 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | bin/ 2 | tags 3 | 4 | -------------------------------------------------------------------------------- /lint.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /libs/jts-1.12.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shiyj/AndroidGIS/HEAD/libs/jts-1.12.jar -------------------------------------------------------------------------------- /libs/armeabi/libjsqlite.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shiyj/AndroidGIS/HEAD/libs/armeabi/libjsqlite.so -------------------------------------------------------------------------------- /res/drawable-hdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shiyj/AndroidGIS/HEAD/res/drawable-hdpi/icon.png -------------------------------------------------------------------------------- /res/drawable-ldpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shiyj/AndroidGIS/HEAD/res/drawable-ldpi/icon.png -------------------------------------------------------------------------------- /res/drawable-mdpi/file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shiyj/AndroidGIS/HEAD/res/drawable-mdpi/file.png -------------------------------------------------------------------------------- /res/drawable-mdpi/folder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shiyj/AndroidGIS/HEAD/res/drawable-mdpi/folder.png -------------------------------------------------------------------------------- /res/drawable-mdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shiyj/AndroidGIS/HEAD/res/drawable-mdpi/icon.png -------------------------------------------------------------------------------- /libs/spatialite-android-library.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shiyj/AndroidGIS/HEAD/libs/spatialite-android-library.jar -------------------------------------------------------------------------------- /gen/com/spatialite/BuildConfig.java: -------------------------------------------------------------------------------- 1 | /** Automatically generated file. DO NOT MODIFY */ 2 | package com.spatialite; 3 | 4 | public final class BuildConfig { 5 | public final static boolean DEBUG = true; 6 | } -------------------------------------------------------------------------------- /META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Bundle-ManifestVersion: 2 3 | Bundle-Name: TestActivity 4 | Bundle-SymbolicName: TestActivity 5 | Bundle-Version: 1.0.0.qualifier 6 | Export-Package: com.spatialite 7 | -------------------------------------------------------------------------------- /res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Hello Giser, This is a demo from GeoInker! 4 | GeoInker 5 | Load the last datasource 6 | 7 | -------------------------------------------------------------------------------- /src/com/spatialite/MessageType.java: -------------------------------------------------------------------------------- 1 | package com.spatialite; 2 | 3 | public class MessageType { 4 | public static final int SEND_LENGTH = 0; 5 | public static final int SEND_ENVELOPE = 1; 6 | public static final int SEND_PROGRESS = 2; 7 | public static final int SEND_GEOMETRIES = 3; 8 | public static final int SEND_ERR = 9; 9 | } 10 | -------------------------------------------------------------------------------- /local.properties: -------------------------------------------------------------------------------- 1 | # This file is automatically generated by Android Tools. 2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED! 3 | # 4 | # This file must *NOT* be checked into Version Control Systems, 5 | # as it contains information specific to your local configuration. 6 | 7 | # location of the SDK. This is only used by Ant 8 | # For customization when using a Version Control System, please read the 9 | # header note. 10 | sdk.dir=/home/engin/appstore/android-sdk-linux 11 | -------------------------------------------------------------------------------- /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /project.properties: -------------------------------------------------------------------------------- 1 | # This file is automatically generated by Android Tools. 2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED! 3 | # 4 | # This file must be checked in Version Control Systems. 5 | # 6 | # To customize properties used by the Ant build system edit 7 | # "ant.properties", and override values to adapt the script to your 8 | # project structure. 9 | # 10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): 11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt 12 | 13 | # Project target. 14 | target=android-8 15 | -------------------------------------------------------------------------------- /.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled 3 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 4 | org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve 5 | org.eclipse.jdt.core.compiler.compliance=1.6 6 | org.eclipse.jdt.core.compiler.debug.lineNumber=generate 7 | org.eclipse.jdt.core.compiler.debug.localVariable=generate 8 | org.eclipse.jdt.core.compiler.debug.sourceFile=generate 9 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error 10 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error 11 | org.eclipse.jdt.core.compiler.source=1.6 12 | -------------------------------------------------------------------------------- /res/layout/canvas.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /res/layout/listview_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 13 | 21 | -------------------------------------------------------------------------------- /res/layout/main.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 12 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Android GIS 2 | 3 | ## App introduction: 4 | 5 | 6 | This is a native GIS plantform made for Android. 7 | 8 | This application is based on [spatialite-android](http://code.google.com/p/spatialite-android/). 9 | But as you known,spatialite-android just is a geodatabase library, how can we show the data in view? The purpose of this app is to solve it. 10 | 11 | ## Installation 12 | 13 | Just import it into eclipse and then run. 14 | 15 | **Note:** *I have compiled the source code of spatialite-android and got two file "/libs/armeabi/libjsqlite.so" and "/libs/spatialite-android-library.jar" ,and then I copy them into this project.* 16 | 17 | 18 | ## useage 19 | Perhaps you nead a sample database, download it [here](http://geoinker.com/file/test.sqlite).Then use this application to open it. 20 | 21 | -------------------------------------------------------------------------------- /proguard-project.txt: -------------------------------------------------------------------------------- 1 | # To enable ProGuard in your project, edit project.properties 2 | # to define the proguard.config property as described in that file. 3 | # 4 | # Add project specific ProGuard rules here. 5 | # By default, the flags in this file are appended to flags specified 6 | # in ${sdk.dir}/tools/proguard/proguard-android.txt 7 | # You can edit the include path and order by changing the ProGuard 8 | # include property in project.properties. 9 | # 10 | # For more details, see 11 | # http://developer.android.com/guide/developing/tools/proguard.html 12 | 13 | # Add any project specific keep options here: 14 | 15 | # If your project uses WebView with JS, uncomment the following 16 | # and specify the fully qualified class name to the JavaScript interface 17 | # class: 18 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 19 | # public *; 20 | #} 21 | -------------------------------------------------------------------------------- /AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 13 | 14 | 15 | 16 | 17 | 18 | 20 | 21 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /proguard.cfg: -------------------------------------------------------------------------------- 1 | -optimizationpasses 5 2 | -dontusemixedcaseclassnames 3 | -dontskipnonpubliclibraryclasses 4 | -dontpreverify 5 | -verbose 6 | -optimizations !code/simplification/arithmetic,!field/*,!class/merging/* 7 | 8 | -keep public class * extends android.app.Activity 9 | -keep public class * extends android.app.Application 10 | -keep public class * extends android.app.Service 11 | -keep public class * extends android.content.BroadcastReceiver 12 | -keep public class * extends android.content.ContentProvider 13 | -keep public class * extends android.app.backup.BackupAgentHelper 14 | -keep public class * extends android.preference.Preference 15 | -keep public class com.android.vending.licensing.ILicensingService 16 | 17 | -keepclasseswithmembernames class * { 18 | native ; 19 | } 20 | 21 | -keepclasseswithmembernames class * { 22 | public (android.content.Context, android.util.AttributeSet); 23 | } 24 | 25 | -keepclasseswithmembernames class * { 26 | public (android.content.Context, android.util.AttributeSet, int); 27 | } 28 | 29 | -keepclassmembers enum * { 30 | public static **[] values(); 31 | public static ** valueOf(java.lang.String); 32 | } 33 | 34 | -keep class * implements android.os.Parcelable { 35 | public static final android.os.Parcelable$Creator *; 36 | } 37 | -------------------------------------------------------------------------------- /gen/com/spatialite/R.java: -------------------------------------------------------------------------------- 1 | /* AUTO-GENERATED FILE. DO NOT MODIFY. 2 | * 3 | * This class was automatically generated by the 4 | * aapt tool from the resource data it found. It 5 | * should not be modified by hand. 6 | */ 7 | 8 | package com.spatialite; 9 | 10 | public final class R { 11 | public static final class attr { 12 | } 13 | public static final class drawable { 14 | public static final int file=0x7f020000; 15 | public static final int folder=0x7f020001; 16 | public static final int icon=0x7f020002; 17 | } 18 | public static final class id { 19 | public static final int ItemName=0x7f050004; 20 | public static final int fileTypeIcon=0x7f050003; 21 | public static final int imageView1=0x7f050002; 22 | public static final int listView1=0x7f050006; 23 | public static final int loadLast=0x7f050005; 24 | public static final int zoom_in=0x7f050000; 25 | public static final int zoom_out=0x7f050001; 26 | } 27 | public static final class layout { 28 | public static final int canvas=0x7f030000; 29 | public static final int listview_item=0x7f030001; 30 | public static final int main=0x7f030002; 31 | } 32 | public static final class string { 33 | public static final int app_name=0x7f040001; 34 | public static final int hello=0x7f040000; 35 | public static final int load_last=0x7f040002; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | spatialite 4 | 5 | 6 | 7 | 8 | 9 | com.android.ide.eclipse.adt.ResourceManagerBuilder 10 | 11 | 12 | 13 | 14 | com.android.ide.eclipse.adt.PreCompilerBuilder 15 | 16 | 17 | 18 | 19 | org.eclipse.jdt.core.javabuilder 20 | 21 | 22 | 23 | 24 | com.android.ide.eclipse.adt.ApkBuilder 25 | 26 | 27 | 28 | 29 | org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder 30 | full,incremental, 31 | 32 | 33 | 34 | 35 | org.eclipse.pde.ManifestBuilder 36 | 37 | 38 | 39 | 40 | org.eclipse.pde.SchemaBuilder 41 | 42 | 43 | 44 | 45 | 46 | com.android.ide.eclipse.adt.AndroidNature 47 | org.eclipse.jdt.core.javanature 48 | org.eclipse.cdt.core.cnature 49 | org.eclipse.cdt.core.ccnature 50 | org.eclipse.cdt.managedbuilder.core.managedBuildNature 51 | org.eclipse.cdt.managedbuilder.core.ScannerConfigNature 52 | org.eclipse.pde.PluginNature 53 | 54 | 55 | -------------------------------------------------------------------------------- /src/com/spatialite/QueryDataThread.java: -------------------------------------------------------------------------------- 1 | package com.spatialite; 2 | 3 | import java.util.ArrayList; 4 | 5 | import jsqlite.Exception; 6 | import jsqlite.Stmt; 7 | import com.spatialite.MessageType; 8 | 9 | import android.app.ProgressDialog; 10 | import android.os.Handler; 11 | import android.os.Message; 12 | import android.util.Log; 13 | 14 | import com.vividsolutions.jts.geom.Envelope; 15 | import com.vividsolutions.jts.geom.Geometry; 16 | import com.vividsolutions.jts.index.strtree.STRtree; 17 | import com.vividsolutions.jts.io.ParseException; 18 | import com.vividsolutions.jts.io.WKBReader; 19 | 20 | public class QueryDataThread extends Thread { 21 | 22 | private final jsqlite.Database mDatabase; 23 | private Handler mHandler; 24 | private String mTableName; 25 | 26 | public QueryDataThread(jsqlite.Database database, Handler handler) { 27 | mDatabase = database; 28 | mHandler = handler; 29 | } 30 | 31 | public void setTableName(String tableName) { 32 | this.mTableName = tableName; 33 | } 34 | 35 | @Override 36 | public void run() { 37 | Message mMsg = mHandler.obtainMessage(); 38 | if (null == mTableName) { 39 | mMsg.obj = "You must set the table name before you run the query thread!"; 40 | mMsg.what = MessageType.SEND_ERR; 41 | mMsg.sendToTarget(); 42 | return; 43 | } 44 | try { 45 | // checking the Vector Layers 46 | String getExtendSQL = "SELECT row_count, "; 47 | getExtendSQL += "extent_min_x, extent_min_y, "; 48 | getExtendSQL += "extent_max_x, extent_max_y "; 49 | getExtendSQL += "FROM layer_statistics "; 50 | getExtendSQL += "WHERE table_name = '"; 51 | getExtendSQL += mTableName + "'"; 52 | 53 | Stmt extStmt = mDatabase.prepare(getExtendSQL); 54 | getExtendSQL = null; 55 | if (extStmt.step()) { 56 | int layer_length = extStmt.column_int(0); 57 | mMsg.obj = layer_length; 58 | mMsg.what = MessageType.SEND_LENGTH; 59 | mMsg.sendToTarget(); 60 | double[] env = new double[4]; 61 | env[0] = extStmt.column_double(1); 62 | env[1] = extStmt.column_double(2); 63 | env[2] = extStmt.column_double(3); 64 | env[3] = extStmt.column_double(4); 65 | mMsg = mHandler.obtainMessage(); 66 | mMsg.obj = env; 67 | env = null; 68 | mMsg.what = MessageType.SEND_ENVELOPE; 69 | mMsg.sendToTarget(); 70 | } 71 | 72 | // Create query 73 | String query = "SELECT AsBinary(geometry) from "; 74 | query += mTableName; 75 | // String query = 76 | // "SELECT name, AsBinary(geometry) from HighWays limit 100"; 77 | // String query = "SELECT name, AsBinary(geometry) from Regions"; 78 | Stmt stmt = mDatabase.prepare(query); 79 | query = null; 80 | // ArrayList geoms = new ArrayList(); 81 | // get the fist geometry type as the who geometry type; 82 | Log.w("查询", "开始查询时间……"); 83 | int i = 0; 84 | WKBReader wkbReader = new WKBReader(); 85 | STRtree indexRtree = new STRtree(); 86 | while (stmt.step()) { 87 | // Create JTS geometry from binary representation 88 | // returned from database 89 | try { 90 | // geoms.add(wkbReader.read(stmt.column_bytes(1))); 91 | Geometry geometry = wkbReader.read(stmt.column_bytes(0)); 92 | indexRtree.insert(geometry.getEnvelopeInternal(), geometry); 93 | geometry = null; 94 | mMsg = mHandler.obtainMessage(); 95 | mMsg.obj = i++; 96 | mMsg.what = MessageType.SEND_PROGRESS; 97 | mMsg.sendToTarget(); 98 | } catch (ParseException e) { 99 | Log.e("ERR!!!", e.getMessage()); 100 | } 101 | } 102 | wkbReader = null; 103 | Log.w("查询", "结束查询,开始转换……"); 104 | stmt.close(); 105 | stmt = null; 106 | mMsg = mHandler.obtainMessage(); 107 | mMsg.obj = indexRtree; 108 | mMsg.what = MessageType.SEND_GEOMETRIES; 109 | indexRtree = null; 110 | mMsg.sendToTarget(); 111 | } catch (Exception e) { 112 | // Log.e("ERR!!!", e.getMessage()); 113 | mMsg = mHandler.obtainMessage(); 114 | mMsg.obj = e.getMessage(); 115 | mMsg.what = MessageType.SEND_ERR; 116 | mMsg.sendToTarget(); 117 | } 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /src/com/spatialite/TestActivity.java: -------------------------------------------------------------------------------- 1 | package com.spatialite; 2 | 3 | import java.io.ByteArrayOutputStream; 4 | import java.io.File; 5 | import java.io.FileInputStream; 6 | import java.io.FileNotFoundException; 7 | import java.io.FileOutputStream; 8 | import java.io.IOException; 9 | import java.util.ArrayList; 10 | import java.util.HashMap; 11 | import java.util.List; 12 | import java.util.Map; 13 | 14 | import android.app.Activity; 15 | import android.app.AlertDialog; 16 | import android.app.AlertDialog.Builder; 17 | import android.content.Context; 18 | import android.content.Intent; 19 | import android.os.Bundle; 20 | import android.view.View; 21 | import android.widget.AdapterView; 22 | import android.widget.Button; 23 | import android.widget.ListView; 24 | import android.widget.SimpleAdapter; 25 | import android.widget.Toast; 26 | import android.widget.AdapterView.OnItemClickListener; 27 | 28 | public class TestActivity extends Activity { 29 | private String cacheFileName = "geoinker_db_dir.gik"; 30 | private String currentDirString = ""; 31 | private File currentFileParent; 32 | private File[] currentFiles; 33 | private ListView list; 34 | Context context; 35 | 36 | private void geoinkerInit() { 37 | currentFileParent = new File("/mnt/sdcard/"); 38 | if (!currentFileParent.exists()) { 39 | AlertDialog.Builder exitApp = new Builder(this); 40 | exitApp.setTitle("No SDCard!"); 41 | exitApp.setMessage("No SDCard are detected!"); 42 | return; 43 | } 44 | File dir1 = new File("/mnt/sdcard/GeoInker"); 45 | mkdatadir(dir1); 46 | File dir2 = new File("/mnt/sdcard/GeoInker/database"); 47 | mkdatadir(dir2); 48 | File dir3 = new File("/mnt/sdcard/GeoInker/shp"); 49 | mkdatadir(dir3); 50 | currentFileParent = dir1; 51 | currentFiles = currentFileParent.listFiles(); 52 | inflateListView(currentFiles); 53 | currentDirString = readLastDir(); 54 | if (null == currentDirString) { 55 | Button bt = (Button) findViewById(R.id.loadLast); 56 | bt.setEnabled(false); 57 | } 58 | 59 | } 60 | 61 | private void mkdatadir(File dir) { 62 | if (!dir.exists()) { 63 | dir.mkdir(); 64 | } 65 | } 66 | 67 | @Override 68 | protected void onCreate(Bundle savedInstanceState) { 69 | super.onCreate(savedInstanceState); 70 | context = this; 71 | setContentView(R.layout.main); 72 | 73 | list = (ListView) findViewById(R.id.listView1); 74 | // binding the click listener of each file item in the listview 75 | list.setOnItemClickListener(new OnItemClickListener() { 76 | @Override 77 | public void onItemClick(AdapterView adapterView, View view, 78 | int position, long id) { 79 | //the first one is a button switch to parent file 80 | if (0 == position) { 81 | currentFileParent = currentFileParent.getParentFile(); 82 | if (null == currentFileParent) { 83 | Toast.makeText(TestActivity.this, 84 | "This is the root directory!", Toast.LENGTH_LONG) 85 | .show(); 86 | return; 87 | } 88 | currentFiles = currentFileParent.listFiles(); 89 | inflateListView(currentFiles); 90 | return; 91 | } 92 | position = position - 1; 93 | if (currentFiles[position].isFile()) { 94 | openDataSource(currentFiles[position].getPath()); 95 | return; 96 | } 97 | 98 | File[] tem = currentFiles[position].listFiles(); 99 | if (tem == null || tem.length == 0) { 100 | 101 | Toast.makeText(TestActivity.this, 102 | "No File in this directory", Toast.LENGTH_LONG) 103 | .show(); 104 | } else { 105 | currentFileParent = currentFiles[position]; 106 | currentFiles = tem; 107 | inflateListView(currentFiles); 108 | } 109 | 110 | } 111 | }); 112 | 113 | geoinkerInit(); 114 | } 115 | 116 | @Override 117 | protected void onActivityResult(int requestCode, int resultCode, Intent data) 118 | { 119 | switch (resultCode) 120 | { 121 | //return if the canvas can't get data from database 122 | case RESULT_OK: 123 | //get the error message from bundle 124 | Bundle bl= data.getExtras(); 125 | String errString=bl.getString("err"); 126 | AlertDialog.Builder errOpenDB = new Builder(context); 127 | errOpenDB.setTitle("Can't open the data!"); 128 | errOpenDB.setMessage(errString); 129 | errOpenDB.setPositiveButton("OK", null); 130 | errOpenDB.create().show(); 131 | break; 132 | default: 133 | break; 134 | } 135 | } 136 | 137 | private void openDataSource(String path){ 138 | Intent intent = new Intent(TestActivity.this, MapCanvas.class); 139 | Bundle dataSource = new Bundle(); 140 | dataSource.putString("datasource", path); 141 | intent.putExtras(dataSource); 142 | startActivityForResult(intent, 0); 143 | } 144 | public void onClick(View v) { 145 | if (v.getId() == R.id.loadLast) { 146 | 147 | } 148 | } 149 | 150 | /** 151 | * @param files 152 | * the currend directory files. flate the list view with the 153 | * currend directory file 154 | */ 155 | private void inflateListView(File[] files) { 156 | List> listItems = new ArrayList>(); 157 | Map listItemUp = new HashMap(); 158 | listItemUp.put("icon", R.drawable.folder); 159 | listItemUp.put("filename", " .."); 160 | listItems.add(listItemUp); 161 | for (int i = 0; i < files.length; i++) { 162 | Map listItem = new HashMap(); 163 | // choose the icon of file. 164 | if (files[i].isDirectory()) { 165 | listItem.put("icon", R.drawable.folder); 166 | } else { 167 | listItem.put("icon", R.drawable.file); 168 | } 169 | // set the file name into text list 170 | listItem.put("filename", files[i].getName()); 171 | listItems.add(listItem); 172 | } 173 | SimpleAdapter mSchedule = new SimpleAdapter(context, listItems, 174 | R.layout.listview_item, new String[] { "icon", "filename" }, 175 | new int[] { R.id.fileTypeIcon, R.id.ItemName }); 176 | list.setAdapter(mSchedule); 177 | } 178 | 179 | 180 | 181 | private String readLastDir() { 182 | try { 183 | FileInputStream inputStream = this.openFileInput(cacheFileName); 184 | byte[] bytes = new byte[1024]; 185 | ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream(); 186 | while (inputStream.read(bytes) != -1) { 187 | arrayOutputStream.write(bytes, 0, bytes.length); 188 | } 189 | inputStream.close(); 190 | arrayOutputStream.close(); 191 | return new String(arrayOutputStream.toByteArray()); 192 | 193 | } catch (FileNotFoundException e) { 194 | e.printStackTrace(); 195 | return null; 196 | } catch (IOException e) { 197 | e.printStackTrace(); 198 | return null; 199 | } 200 | } 201 | 202 | } -------------------------------------------------------------------------------- /src/com/spatialite/MapCanvas.java: -------------------------------------------------------------------------------- 1 | package com.spatialite; 2 | 3 | import java.io.FileNotFoundException; 4 | import java.io.FileOutputStream; 5 | import java.io.IOException; 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | import jsqlite.Exception; 10 | import jsqlite.Stmt; 11 | //引入JTS 12 | import com.vividsolutions.jts.geom.*; 13 | import com.vividsolutions.jts.index.strtree.STRtree; 14 | 15 | import android.R.bool; 16 | import android.R.integer; 17 | import android.app.Activity; 18 | import android.app.AlertDialog; 19 | import android.app.AlertDialog.Builder; 20 | import android.app.ProgressDialog; 21 | import android.content.Context; 22 | import android.content.DialogInterface; 23 | import android.content.DialogInterface.OnClickListener; 24 | import android.content.DialogInterface.OnMultiChoiceClickListener; 25 | import android.content.Intent; 26 | import android.graphics.Bitmap; 27 | import android.graphics.Canvas; 28 | import android.graphics.Color; 29 | import android.graphics.Paint; 30 | import android.graphics.Path; 31 | import android.graphics.Paint.Style; 32 | import android.graphics.drawable.AnimationDrawable; 33 | import android.os.Bundle; 34 | import android.os.Handler; 35 | import android.os.Message; 36 | import android.util.Log; 37 | import android.view.KeyEvent; 38 | import android.view.MotionEvent; 39 | import android.view.View; 40 | import android.view.Window; 41 | import android.view.WindowManager; 42 | import android.view.animation.Animation; 43 | 44 | public class MapCanvas extends Activity { 45 | private String cacheFileName = "geoinker_db_dir.gik"; 46 | private final jsqlite.Database mDatabase; 47 | private Envelope mGeomEnvelope; 48 | private MyView mView; 49 | private ProgressDialog mProgressDialog; 50 | private Intent mIntent; 51 | 52 | private boolean mIsDynamicDrawing = false; 53 | 54 | public MapCanvas() { 55 | mGeomEnvelope = new Envelope(); 56 | mDatabase = new jsqlite.Database(); 57 | } 58 | 59 | @Override 60 | protected void onCreate(Bundle savedInstanceState) { 61 | super.onCreate(savedInstanceState); 62 | mIntent = this.getIntent(); 63 | Bundle dataBundle = mIntent.getExtras(); 64 | String dataSource = dataBundle.getString("datasource"); 65 | // open the datasource 66 | try { 67 | mDatabase.open(dataSource, jsqlite.Constants.SQLITE_OPEN_READONLY); 68 | // if open successed,save the directory for next launch 69 | saveCurrentDir(dataSource); 70 | 71 | } catch (Exception e) { 72 | throwErrToMain(e.getMessage()); 73 | } 74 | // Hide the title bar 75 | requestWindowFeature(Window.FEATURE_NO_TITLE); 76 | // set the full to screen 77 | getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, 78 | WindowManager.LayoutParams.FLAG_FULLSCREEN); 79 | 80 | mProgressDialog = new ProgressDialog(this); 81 | mProgressDialog.setTitle("Getting data"); 82 | mProgressDialog.setMessage("***I'm Loading***"); 83 | mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); 84 | mView = new MyView(this); 85 | showTabelSelect(getGeomtryTable()); 86 | setContentView(mView); 87 | } 88 | 89 | @Override 90 | public boolean onKeyDown(int keyCode, KeyEvent event) { 91 | if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) { 92 | mView.zoomIn(); 93 | return true; 94 | } else if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) { 95 | mView.zoomOut(); 96 | return true; 97 | } 98 | return super.onKeyDown(keyCode, event); 99 | } 100 | 101 | private void saveCurrentDir(String content) { 102 | try { 103 | FileOutputStream outputStream = openFileOutput(cacheFileName, 104 | Activity.MODE_PRIVATE); 105 | outputStream.write(content.getBytes()); 106 | outputStream.flush(); 107 | outputStream.close(); 108 | } catch (FileNotFoundException e) { 109 | e.printStackTrace(); 110 | } catch (IOException e) { 111 | e.printStackTrace(); 112 | } 113 | } 114 | 115 | private void showTabelSelect(ArrayList tableName) { 116 | // not a spatialite database 117 | if (null == tableName || 0 == tableName.size()) { 118 | throwErrToMain("not a spatialite database"); 119 | return; 120 | } 121 | final String[] tableNameStrings = (String[]) tableName 122 | .toArray(new String[tableName.size()]); 123 | final boolean[] tableSelect = new boolean[tableName.size()]; 124 | tableName = null; 125 | AlertDialog.Builder selectTableBuilder = new Builder(this); 126 | selectTableBuilder.setTitle("Select the layer(s)"); 127 | OnMultiChoiceClickListener multiLIstener = new OnMultiChoiceClickListener() { 128 | @Override 129 | public void onClick(DialogInterface dialog, int which, 130 | boolean isChecked) { 131 | tableSelect[which] = isChecked; 132 | } 133 | }; 134 | selectTableBuilder.setMultiChoiceItems(tableNameStrings, null, 135 | multiLIstener); 136 | OnClickListener loadListener = new OnClickListener() { 137 | @Override 138 | public void onClick(DialogInterface dialog, int which) { 139 | ArrayList selectedTable = new ArrayList(); 140 | for (int i = 0; i < tableSelect.length; i++) { 141 | if (tableSelect[i]) { 142 | selectedTable.add(tableNameStrings[i]); 143 | } 144 | } 145 | if (0 == selectedTable.size()) { 146 | throwErrToMain("You have not select a single layer!"); 147 | return; 148 | } 149 | mView.getData(selectedTable); 150 | dialog.dismiss(); 151 | } 152 | }; 153 | selectTableBuilder.setPositiveButton("OK", loadListener); 154 | OnClickListener cancleListener = new OnClickListener() { 155 | @Override 156 | public void onClick(DialogInterface dialog, int which) { 157 | MapCanvas.this.finish(); 158 | } 159 | }; 160 | selectTableBuilder.setNegativeButton("Cancle", cancleListener); 161 | selectTableBuilder.create().show(); 162 | } 163 | 164 | private ArrayList getGeomtryTable() { 165 | try { 166 | ArrayList tableName = new ArrayList(); 167 | String query = "SELECT DISTINCT f_table_name from geometry_columns"; 168 | Stmt stmt = mDatabase.prepare(query); 169 | query = null; 170 | while (stmt.step()) { 171 | tableName.add(stmt.column_string(0)); 172 | } 173 | stmt.close(); 174 | return tableName; 175 | } catch (Exception e) { 176 | throwErrToMain(e.getMessage()); 177 | return null; 178 | } 179 | } 180 | 181 | /** 182 | * send the errors messages back to main activity and close this. 183 | * 184 | * @param errmsg 185 | */ 186 | public void throwErrToMain(String errmsg) { 187 | Bundle errBundle = new Bundle(); 188 | errBundle.putString("err", errmsg); 189 | mIntent.putExtras(errBundle); 190 | this.setResult(RESULT_OK, mIntent); 191 | this.finish(); 192 | } 193 | 194 | public void setIsDynamicDrawing(boolean isDynamic) { 195 | mIsDynamicDrawing = isDynamic; 196 | } 197 | 198 | public class MyView extends View { 199 | /** 200 | * 分别表示:SELECT选择属性 DRAG 拖动 ZOOM 放大缩小 201 | */ 202 | private static final int NONE = 0; 203 | private static final int ZOOM = 1; 204 | private static final int DRAG = 2; 205 | private static final int SELECT = 3; 206 | 207 | // store all the geometries to be shown and the spatial index of each 208 | // geometry. 209 | private STRtree m_geomsIndex; 210 | private Paint paint = new Paint(); 211 | // indentify the mode while operating the map view. 212 | private int m_nMode = DRAG; 213 | // touch point to indentify move(drag) 214 | private double m_startX = 0; 215 | private double m_startY = 0; 216 | private double m_endX = 0; 217 | private double m_endY = 0; 218 | private double m_fOldDist = 1f; 219 | 220 | // the scale of fullscreen 全屏时比例 221 | private double rate; 222 | 223 | /** 224 | * the scale of current screen. leavel = 1,full screen; leavel > 225 | * 1,enlarged map leavel < 1,lessened map 226 | */ 227 | private double leavel = 1; 228 | // 229 | /** 230 | * the distance of the origin map data(in database) while zooming and 231 | * panning on the screen 相对于原数据坐标的平移位置dx,dy。 232 | */ 233 | private double dx = 0; 234 | private double dy = 0; 235 | 236 | // the width and height of the view 237 | int view_w; 238 | int view_h; 239 | 240 | // the picture of the canvas after redraw all the geometries on the 241 | // screen. 242 | private Bitmap m_CacheBitmap = null; 243 | boolean m_isDraging = false; 244 | 245 | MyView(Context context) { 246 | super(context); 247 | } 248 | 249 | Path path = new Path(); 250 | 251 | @Override 252 | protected void onDraw(Canvas canvas) { 253 | view_w = getWidth(); 254 | view_h = getHeight(); 255 | if (!mIsDynamicDrawing && m_isDraging) { 256 | Log.w("Bitmap", "drag START"); 257 | if (null == m_CacheBitmap) { 258 | Log.w("Bitmap", "drag bitmap is null"); 259 | return; 260 | } 261 | if (m_CacheBitmap.isRecycled()) { 262 | Log.w("Bitmap", "drag bitmap had been recycled"); 263 | return; 264 | } 265 | int offsetX = (int) (m_endX - m_startX); 266 | int offsetY = (int) (m_endY - m_startY); 267 | canvas.drawBitmap(m_CacheBitmap, offsetX, offsetY, null); 268 | Log.w("Bitmap", "drag END"); 269 | return; 270 | } 271 | 272 | paint.setColor(Color.BLUE); 273 | paint.setStyle(Style.FILL); 274 | canvas.drawText("GeoInker", 10, 50, paint); 275 | if (null == m_CacheBitmap) { 276 | Log.w("Bitmap", "redraw bitmap is null"); 277 | return; 278 | } 279 | Log.w("Bitmap", "redraw START"); 280 | canvas.drawBitmap(m_CacheBitmap, 0, 0, null); 281 | Log.w("Bitmap", "redraw END"); 282 | } 283 | 284 | @Override 285 | public boolean onTouchEvent(MotionEvent event) { 286 | switch (event.getAction() & MotionEvent.ACTION_MASK) { 287 | 288 | case MotionEvent.ACTION_DOWN: 289 | // 触摸获取位置查询 290 | m_endX = m_startX = event.getX(); 291 | m_endY = m_startY = event.getY(); 292 | query(m_startX, m_startY); 293 | break; 294 | case MotionEvent.ACTION_UP: 295 | if (m_isDraging) { 296 | m_isDraging = false; 297 | drag2(); 298 | DrawGeometryToBitmap();// redraw the geometry in this view 299 | } 300 | m_endX = m_startX = 0; 301 | m_endY = m_startY = 0; 302 | break; 303 | case MotionEvent.ACTION_POINTER_1_DOWN: 304 | /** 305 | * change to zoom mode only when the moved distance of two 306 | * fingers is big 10f 计算两点的距离,大于10f才认为是两根手指。 307 | */ 308 | m_fOldDist = spacing(event); 309 | if (m_fOldDist > 10f) { 310 | m_nMode = ZOOM; 311 | } 312 | break; 313 | case MotionEvent.ACTION_POINTER_1_UP: 314 | /** 315 | * change to drag mode when a finger leave the screen and reset 316 | * the touch point 中途其中一根手指离开屏幕,退出缩放模式.同时将开始标记点记为当前. 317 | */ 318 | m_nMode = DRAG; 319 | m_endX = m_startX = event.getX(); 320 | m_endY = m_startY = event.getY(); 321 | break; 322 | case MotionEvent.ACTION_MOVE: 323 | m_endX = event.getX(); 324 | m_endY = event.getY(); 325 | if (m_nMode == ZOOM) { 326 | double a_fNewDist = spacing(event); 327 | if (a_fNewDist - m_fOldDist > 14 328 | || a_fNewDist - m_fOldDist < -14) { 329 | zoom(a_fNewDist - m_fOldDist); 330 | m_fOldDist = a_fNewDist; 331 | } 332 | } else if (m_nMode == DRAG) { 333 | if (mIsDynamicDrawing) { 334 | if (m_endX - m_startX > 10 || m_endX - m_startX < -10 335 | || m_endY - m_startY > 10 336 | || m_endY - m_startY < -10) { 337 | drag(); 338 | m_endX = m_startX = event.getX(); 339 | m_endY = m_startY = event.getY(); 340 | } 341 | } else { 342 | if (!m_isDraging) { 343 | m_isDraging = true; 344 | } 345 | } 346 | postInvalidate(); 347 | } 348 | break; 349 | } 350 | return true; 351 | } 352 | 353 | /* 354 | * validate whether the distance of panning is out of the boundary of the mapview 355 | */ 356 | private void ValidateDragDistance() { 357 | // 不能超出地图范围。 358 | double width = mGeomEnvelope.getWidth(); 359 | double height = mGeomEnvelope.getHeight(); 360 | if (dx > width) { 361 | dx = width; 362 | } else if (dx < -width) { 363 | dx = -width; 364 | } 365 | if (dy > height) { 366 | dy = height; 367 | } else if (dy < -height) { 368 | dy = -height; 369 | } 370 | } 371 | 372 | /** 373 | * if the leavel is the minimal value ,don't zoom it anymore. 374 | * @return Whether the leavel should change 375 | */ 376 | private boolean ValidateLeavel() { 377 | double min_leavel = rate / 2; 378 | if (leavel < min_leavel) { 379 | leavel = min_leavel; 380 | return false; 381 | } 382 | return true; 383 | } 384 | 385 | private void ExecuedZoom(double zoomRate) { 386 | double originx, originy, destx, desty; 387 | originx = antTransData(view_w / 2, 0); 388 | originy = antTransData(view_h / 2, 1); 389 | leavel += zoomRate * leavel; 390 | if (!ValidateLeavel()) 391 | return; 392 | destx = antTransData(view_w / 2, 0); 393 | desty = antTransData(view_h / 2, 1); 394 | dx += destx - originx; 395 | dy += desty - originy; 396 | ValidateDragDistance(); 397 | DrawGeometryToBitmap(); 398 | } 399 | 400 | private void zoom(double dis) { 401 | double zoomRate = dis 402 | / Math.sqrt(view_w * view_w + view_h * view_h); 403 | ExecuedZoom(zoomRate); 404 | } 405 | 406 | public void zoomIn() { 407 | ExecuedZoom(0.2); 408 | } 409 | 410 | public void zoomOut() { 411 | ExecuedZoom(-0.2); 412 | } 413 | 414 | /** 415 | * drag with dynamic drawing; 416 | */ 417 | private void drag() { 418 | double tmp_dx = 0;// 直接赋值给dx会影响dy的判断 419 | if (m_endX - m_startX > 10 || m_endX - m_startX < -10) { 420 | tmp_dx = antTransData(m_endX, 0) - antTransData(m_startX, 0); 421 | } 422 | if (m_endY - m_startY > 10 || m_endY - m_startY < -10) { 423 | dy += (antTransData(m_endY, 1) - antTransData(m_startY, 1)); 424 | } 425 | dx += tmp_dx; 426 | ValidateDragDistance(); 427 | } 428 | 429 | /** 430 | * drag with picture move 431 | */ 432 | private void drag2() { 433 | double tmp_dx = 0;// 直接赋值给dx会影响dy的判断 434 | tmp_dx = antTransData(m_endX, 0) - antTransData(m_startX, 0); 435 | dy += (antTransData(m_endY, 1) - antTransData(m_startY, 1)); 436 | dx += tmp_dx; 437 | ValidateDragDistance(); 438 | } 439 | 440 | private void query(double x, double y) { 441 | 442 | } 443 | 444 | /** 445 | * change the coordinate from datasource to screen. 446 | * 将数据坐标转换成屏幕坐标。 447 | * 448 | * @param f 449 | * the value(x or y,decided by the param i) of the coordinate 坐标值 450 | * @param i 451 | * 0,trans x;1,trans y . 0表示x,1表示y; 452 | * @return 453 | */ 454 | private double transData(double f, double i) { 455 | double result = 0; 456 | if (i == 0) { 457 | double minx; 458 | minx = mGeomEnvelope.getMinX(); 459 | result = (f + dx - minx) * leavel; 460 | } else { 461 | double miny; 462 | miny = mGeomEnvelope.getMinY(); 463 | result = (view_h - (f + dy - miny) * leavel); 464 | } 465 | return result; 466 | } 467 | 468 | /** 469 | * change the coordinate from screen to datasource. 470 | * 将屏幕坐标转换成数据坐标。 471 | * 472 | * @param f 473 | * the value(x or y,decided by the param i) of the coordinate 坐标值 474 | * @param i 475 | * 0,trans x;1,trans y . 0表示x,1表示y; 476 | * @return 477 | */ 478 | private double antTransData(double f, double i) { 479 | double result = 0; 480 | if (i == 0) { 481 | double minx; 482 | minx = mGeomEnvelope.getMinX(); 483 | result = (f / leavel + minx - dx); 484 | } else { 485 | double miny; 486 | miny = mGeomEnvelope.getMinY(); 487 | result = ((view_h - f) / leavel + miny - dy); 488 | } 489 | return result; 490 | } 491 | 492 | private double spacing(MotionEvent event) { 493 | double x = event.getX(0) - event.getX(1); 494 | double y = event.getY(0) - event.getY(1); 495 | return Math.sqrt(x * x + y * y); 496 | } 497 | 498 | /** 499 | * query the geometries by an envelope while redraw them into screen 500 | */ 501 | private Envelope searchEnv = new Envelope(); 502 | private void setCurrentEnvelop(double x1, double x2, double y1, 503 | double y2) { 504 | double xx1, xx2, yy1, yy2; 505 | xx1 = antTransData(x1, 0); 506 | xx2 = antTransData(x2, 0); 507 | yy1 = antTransData(y1, 1); 508 | yy2 = antTransData(y2, 1); 509 | searchEnv.init(xx1, xx2, yy1, yy2); 510 | } 511 | private void setCurrentEnvelop() { 512 | double xx1, xx2, yy1, yy2; 513 | xx1 = antTransData(0, 0); 514 | xx2 = antTransData(view_w, 0); 515 | yy1 = antTransData(view_h, 1); 516 | yy2 = antTransData(0, 1); 517 | searchEnv.init(xx1, xx2, yy1, yy2); 518 | } 519 | 520 | /** 521 | * Draw the Geometrise to a bitmap call this function only when the 522 | * change of the canvas is done 523 | */ 524 | private void DrawGeometryToBitmap() { 525 | m_CacheBitmap = Bitmap.createBitmap(view_w, view_h, 526 | Bitmap.Config.ARGB_8888); 527 | Canvas cn = new Canvas(m_CacheBitmap); 528 | if (null == m_geomsIndex) { 529 | return; 530 | } 531 | DrawGeomtry(cn); 532 | draw(cn); 533 | cn.save(Canvas.ALL_SAVE_FLAG); 534 | cn.restore(); 535 | postInvalidate(); 536 | } 537 | 538 | private void DrawGeomtry(Canvas canvas) { 539 | setCurrentEnvelop(); 540 | List geoms = m_geomsIndex.query(searchEnv); 541 | int geoms_len = geoms.size(); 542 | for (int i = 0; i < geoms_len; i++) { 543 | Geometry geometry = geoms.get(i); 544 | String type = geometry.getGeometryType(); 545 | 546 | if (type.equals("MultiPoint")) { 547 | DrawPoints(canvas, geometry); 548 | } else if (type.equals("Point")) { 549 | DrawPoints(canvas, geometry); 550 | } else if (type.equals("MultiLineString")) { 551 | DrawLineStrings(canvas, geometry); 552 | } else if (type.equals("LineString")) { 553 | DrawLineStrings(canvas, geometry); 554 | } else if (type.equals("MultiPolygon")) { 555 | DrawPolygons(canvas, geometry); 556 | } else if (type.equals("Polygon")) { 557 | DrawPolygons(canvas, geometry); 558 | } 559 | } 560 | } 561 | 562 | private void DrawPoints(Canvas canvas, Geometry geometry) { 563 | String type = geometry.getGeometryType(); 564 | 565 | if (type.equals("MultiPoint")) { 566 | int len = geometry.getNumGeometries(); 567 | for (int i = 0; i < len; i++) { 568 | Geometry subGeometry = geometry.getGeometryN(i); 569 | DrawPoints(canvas, subGeometry); 570 | } 571 | } else if (type.equals("Point")) { 572 | paint.setColor(Color.RED); 573 | paint.setStyle(Style.FILL); 574 | Point pt = (Point) geometry; 575 | canvas.drawCircle((float) transData(pt.getX(), 0), 576 | (float) transData(pt.getY(), 1), 2, paint); 577 | } 578 | 579 | } 580 | 581 | /** 582 | * @param canvas 583 | * @param mulLines 584 | * 585 | */ 586 | private void DrawLineStrings(Canvas canvas, Geometry geometry) { 587 | String type = geometry.getGeometryType(); 588 | if (type.equals("MultiLineString")) { 589 | int len = geometry.getNumGeometries(); 590 | for (int i = 0; i < len; i++) { 591 | Geometry subGeometry = geometry.getGeometryN(i); 592 | DrawLineStrings(canvas, subGeometry); 593 | } 594 | } else if (type.equals("LineString")) { 595 | paint.setColor(Color.GREEN); 596 | LineString lineString = (LineString) geometry; 597 | int pointLen = lineString.getNumPoints(); 598 | for (int j = 0; j < pointLen - 1; j++) { 599 | Point ptStart = lineString.getPointN(j); 600 | Point ptStop = lineString.getPointN(j + 1); 601 | canvas.drawLine((float) transData(ptStart.getX(), 0), 602 | (float) transData(ptStart.getY(), 1), 603 | (float) transData(ptStop.getX(), 0), 604 | (float) transData(ptStop.getY(), 1), paint); 605 | ptStart = null; 606 | ptStop = null; 607 | } 608 | } 609 | geometry = null; 610 | } 611 | 612 | /** 613 | * @param canvas 614 | * @param mulPolygon 615 | * 616 | */ 617 | private void DrawPolygons(Canvas canvas, Geometry geometry) { 618 | String type = geometry.getGeometryType(); 619 | 620 | if (type.equals("Polygon")) { 621 | Polygon pg = (Polygon) geometry; 622 | int innerRines = pg.getNumInteriorRing(); 623 | for (int j = 0; j < innerRines; j++) { 624 | DrawPolygon(canvas, pg.getInteriorRingN(j), true); 625 | } 626 | LineString outterRine = pg.getExteriorRing(); 627 | DrawPolygon(canvas, outterRine, false); 628 | } else if (type.equals("MultiPolygon")) { 629 | int pglen = geometry.getNumGeometries(); 630 | for (int i = 0; i < pglen; i++) { 631 | Geometry subGeometry = geometry.getGeometryN(i); 632 | DrawPolygons(canvas, subGeometry); 633 | } 634 | } 635 | } 636 | 637 | private void DrawPolygon(Canvas canvas, LineString polygon, 638 | Boolean isInerRing) { 639 | paint.setColor(Color.DKGRAY); 640 | paint.setStyle(Style.FILL); 641 | path.reset(); 642 | int len = polygon.getNumPoints(); 643 | // no data 644 | if (len < 1) { 645 | return; 646 | } 647 | Point pt0 = polygon.getPointN(0); 648 | path.moveTo((float) transData(pt0.getX(), 0), 649 | (float) transData(pt0.getY(), 1)); 650 | for (int i = 1; i < len; i++) { 651 | Point ptStart = polygon.getPointN(i - 1); 652 | Point pt = polygon.getPointN(i); 653 | path.lineTo((float) transData(pt.getX(), 0), 654 | (float) transData(pt.getY(), 1)); 655 | canvas.drawLine((float) transData(ptStart.getX(), 0), 656 | (float) transData(ptStart.getY(), 1), 657 | (float) transData(pt.getX(), 0), 658 | (float) transData(pt.getY(), 1), paint); 659 | } 660 | path.close(); 661 | if (isInerRing) { 662 | paint.setColor(Color.BLACK); 663 | } else { 664 | paint.setColor(Color.BLUE); 665 | } 666 | canvas.drawPath(path, paint); 667 | } 668 | 669 | Handler handlerGetData = new Handler() { 670 | @Override 671 | public void handleMessage(Message msg) { 672 | switch (msg.what) { 673 | case MessageType.SEND_LENGTH: 674 | mProgressDialog.setMax(((Integer) (msg.obj)).intValue()); 675 | mProgressDialog.show(); 676 | break; 677 | case MessageType.SEND_ENVELOPE: 678 | double[] env = (double[]) msg.obj; 679 | double geom_width, 680 | geom_height; 681 | geom_width = env[2] - env[0]; 682 | geom_height = env[3] - env[1]; 683 | // if there only one point 只有一个点的图层,原比例无缩放。 684 | if (geom_height < 1e-8 && geom_width < 1e-8) { 685 | rate = 1; 686 | mGeomEnvelope.init(view_w, 0, view_h, 0); 687 | } else { 688 | double rate1 = view_h / view_w; 689 | //the screen is narrower then the envelope of all geometries 屏幕比外接矩形窄 690 | if (rate1 > geom_height / geom_width) { 691 | rate = view_w / geom_width; 692 | double d_height = (view_h / rate - geom_height) / 2; 693 | mGeomEnvelope.init(env[2], env[0], env[3] 694 | + d_height, env[1] - d_height); 695 | } else { 696 | rate = view_h / geom_height; 697 | double d_with = (view_w / rate - geom_width) / 2; 698 | mGeomEnvelope.init(env[2] + d_with, 699 | env[0] - d_with, env[3], env[1]); 700 | } 701 | } 702 | leavel = rate; 703 | break; 704 | case MessageType.SEND_PROGRESS: 705 | 706 | mProgressDialog.setProgress(((Integer) (msg.obj)) 707 | .intValue()); 708 | break; 709 | case MessageType.SEND_GEOMETRIES: 710 | m_geomsIndex = (STRtree) msg.obj; 711 | if (null == m_geomsIndex) { 712 | Log.w("database", "no date in the database……"); 713 | mProgressDialog.dismiss(); 714 | return; 715 | } 716 | mProgressDialog.dismiss(); 717 | DrawGeometryToBitmap(); 718 | break; 719 | case MessageType.SEND_ERR: 720 | MapCanvas.this.throwErrToMain(msg.obj.toString()); 721 | break; 722 | default: 723 | break; 724 | } 725 | } 726 | }; 727 | 728 | public void getData(ArrayList tableNames) { 729 | for (int i = 0; i < tableNames.size(); i++) { 730 | QueryDataThread qdThread = new QueryDataThread(mDatabase, 731 | handlerGetData); 732 | qdThread.setTableName(tableNames.get(i)); 733 | qdThread.start(); 734 | qdThread = null; 735 | } 736 | 737 | } 738 | } 739 | } 740 | --------------------------------------------------------------------------------