diff --git a/CHANGELOG.md b/CHANGELOG.md
index 231dd43a..c0eb0bb1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,9 +4,27 @@ Adheres to [Semantic Versioning](http://semver.org/).
---
-## 1.17 (TBD)
-
-* TBD
+## [1.17](https://github.com/ngageoint/geopackage-mapcache-android/releases/tag/1.17) (11-21-2017)
+
+* geopackage-android-map version updated to 2.0.0
+* GeoPackage share fix for external GeoPackages
+* Geometry simplifications for displayed map features based upon zoom level
+* Only display and maintain features in the current map views
+* Maintain active feature indices when editing map features
+* Queryable map features (previously only available for feature tiles)
+* Automatically select active feature table when editing features
+* Update geometry envelopes when editing features
+* Increase default max map features & max points per tile to 5000, max features per tile to 2000
+* Updated preloaded GeoPackage url example files
+* Updated various now deprecated Android library calls
+* gradle plugin updated to 2.3.3
+* android maven gradle plugin updated to 2.0
+* maven google dependency
+* compile SDK version 26
+* build tools version updated to 26.0.1
+* target SDK version updated to 26
+* appcompat v7:26.0.2
+* multidex version 1.0.2
## [1.16](https://github.com/ngageoint/geopackage-mapcache-android/releases/tag/1.16) (07-13-2017)
diff --git a/build.gradle b/build.gradle
index 74bb64f7..9a32f7bd 100644
--- a/build.gradle
+++ b/build.gradle
@@ -2,17 +2,23 @@
buildscript {
repositories {
jcenter()
+ maven {
+ url "https://maven.google.com"
+ }
mavenLocal()
}
dependencies {
- classpath 'com.android.tools.build:gradle:2.3.2'
- classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5'
+ classpath 'com.android.tools.build:gradle:2.3.3'
+ classpath 'com.github.dcendents:android-maven-gradle-plugin:2.0'
}
}
allprojects {
repositories {
jcenter()
+ maven {
+ url "https://maven.google.com"
+ }
mavenLocal()
}
}
diff --git a/docs/index.html b/docs/index.html
index 6f78a317..3c06e174 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -15,7 +15,7 @@
GeoPackage MapCache Android
by the National Geospatial-Intelligence Agency
GitHub
- APK
+ APK
.zip
.tar.gz
diff --git a/mapcache/build.gradle b/mapcache/build.gradle
index 0b1defdf..b53f47af 100644
--- a/mapcache/build.gradle
+++ b/mapcache/build.gradle
@@ -5,8 +5,8 @@ def googleMapsApiReleaseKey = hasProperty('RELEASE_MAPS_MAPCACHE_API_KEY') ? REL
def googleMapsApiKeyDebug = hasProperty('DEBUG_MAPS_API_KEY') ? DEBUG_MAPS_API_KEY: ''
android {
- compileSdkVersion 25
- buildToolsVersion "25.0.3"
+ compileSdkVersion 26
+ buildToolsVersion "26.0.1"
dexOptions {
javaMaxHeapSize "4g"
@@ -15,7 +15,7 @@ android {
defaultConfig {
applicationId "mil.nga.mapcache"
minSdkVersion 14
- targetSdkVersion 25
+ targetSdkVersion 26
versionCode 18
versionName '1.17'
multiDexEnabled true
@@ -50,9 +50,11 @@ task androidAppVersion {
}
dependencies {
- compile "mil.nga.geopackage.map:geopackage-android-map:1.4.1" // comment out to build locally
- compile 'com.android.support:multidex:1.0.1'
+ compile 'com.android.support:appcompat-v7:26.0.2'
+ compile "mil.nga.geopackage.map:geopackage-android-map:2.0.0" // comment out to build locally
//compile project(':geopackage-map') // uncomment me to build locally
+ compile 'com.android.support:multidex:1.0.2'
+ androidTestCompile 'com.android.support:multidex:1.0.2'
}
configure extensions.android, {
diff --git a/mapcache/src/main/java/mil/nga/mapcache/GeoPackageManagerFragment.java b/mapcache/src/main/java/mil/nga/mapcache/GeoPackageManagerFragment.java
index 99702d7b..8fa5e788 100644
--- a/mapcache/src/main/java/mil/nga/mapcache/GeoPackageManagerFragment.java
+++ b/mapcache/src/main/java/mil/nga/mapcache/GeoPackageManagerFragment.java
@@ -867,7 +867,10 @@ private void shareDatabaseOption(final String database) {
// If external database, no permission is needed
if (manager.isExternal(database)) {
// Create the Uri and share
- Uri databaseUri = Uri.fromFile(databaseFile);
+ Uri databaseUri = FileProvider.getUriForFile(getActivity(),
+ "mil.nga.mapcache.fileprovider",
+ databaseFile);
+ shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
launchShareIntent(shareIntent, databaseUri);
}
// If internal database, file must be copied to cache for permission
@@ -1083,7 +1086,7 @@ public void onClick(DialogInterface dialog, int id) {
}
BoundingBox boundingBox = new BoundingBox(minLon,
- maxLon, minLat, maxLat);
+ minLat, maxLon, maxLat);
GeometryType geometryType = GeometryType
.fromName(geometryTypeSpinner
@@ -1238,7 +1241,7 @@ public void onClick(DialogInterface dialog, int id) {
.isChecked();
BoundingBox boundingBox = new BoundingBox(minLon,
- maxLon, minLat, maxLat);
+ minLat, maxLon, maxLat);
// If not importing tiles, just create the table
if (tileUrl == null || tileUrl.isEmpty()) {
@@ -2049,7 +2052,7 @@ public void onClick(DialogInterface dialog, int id) {
.isChecked();
BoundingBox boundingBox = new BoundingBox(minLon,
- maxLon, minLat, maxLat);
+ minLat, maxLon, maxLat);
// Load tiles
LoadTilesTask.loadTiles(getActivity(),
@@ -2328,8 +2331,8 @@ private void createFeatureTilesTableOption(final GeoPackageTable table) {
Projection projection = null;
if (boundingBox == null) {
boundingBox = new BoundingBox(-ProjectionConstants.WGS84_HALF_WORLD_LON_WIDTH,
- ProjectionConstants.WGS84_HALF_WORLD_LON_WIDTH,
ProjectionConstants.WEB_MERCATOR_MIN_LAT_RANGE,
+ ProjectionConstants.WGS84_HALF_WORLD_LON_WIDTH,
ProjectionConstants.WEB_MERCATOR_MAX_LAT_RANGE);
projection = ProjectionFactory.getProjection(ProjectionConstants.EPSG_WORLD_GEODETIC_SYSTEM);
} else {
@@ -2449,7 +2452,7 @@ public void onClick(DialogInterface dialog, int id) {
.isChecked();
BoundingBox boundingBox = new BoundingBox(minLon,
- maxLon, minLat, maxLat);
+ minLat, maxLon, maxLat);
GeoPackageManager manager = GeoPackageFactory.getManager(getActivity());
GeoPackage geoPackage = manager.open(table.getDatabase());
@@ -2626,8 +2629,8 @@ private void addFeatureOverlayTableOption(final GeoPackageTable table) {
worldGeodeticBoundingBox = worldGeodeticTransform.transform(webMercatorBoundingBox);
} else {
worldGeodeticBoundingBox = new BoundingBox(-ProjectionConstants.WGS84_HALF_WORLD_LON_WIDTH,
- ProjectionConstants.WGS84_HALF_WORLD_LON_WIDTH,
ProjectionConstants.WEB_MERCATOR_MIN_LAT_RANGE,
+ ProjectionConstants.WGS84_HALF_WORLD_LON_WIDTH,
ProjectionConstants.WEB_MERCATOR_MAX_LAT_RANGE);
}
@@ -4117,18 +4120,15 @@ public boolean onLongClick(View v) {
break;
}
}
- imageView.setImageDrawable(getResources().getDrawable(
- drawableId));
+ imageView.setImageDrawable(ContextCompat.getDrawable(getActivity(), drawableId));
break;
case TILE:
- imageView.setImageDrawable(getResources().getDrawable(
- R.drawable.ic_tiles));
+ imageView.setImageDrawable(ContextCompat.getDrawable(getActivity(), R.drawable.ic_tiles));
break;
case FEATURE_OVERLAY:
- imageView.setImageDrawable(getResources().getDrawable(
- R.drawable.ic_format_paint));
+ imageView.setImageDrawable(ContextCompat.getDrawable(getActivity(), R.drawable.ic_format_paint));
break;
default:
diff --git a/mapcache/src/main/java/mil/nga/mapcache/GeoPackageMapFragment.java b/mapcache/src/main/java/mil/nga/mapcache/GeoPackageMapFragment.java
index ab78a19d..0069bc9c 100755
--- a/mapcache/src/main/java/mil/nga/mapcache/GeoPackageMapFragment.java
+++ b/mapcache/src/main/java/mil/nga/mapcache/GeoPackageMapFragment.java
@@ -40,10 +40,10 @@
import android.widget.RadioButton;
import android.widget.Spinner;
import android.widget.TextView;
-import android.widget.Toast;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
+import com.google.android.gms.maps.GoogleMap.OnCameraIdleListener;
import com.google.android.gms.maps.GoogleMap.OnMapClickListener;
import com.google.android.gms.maps.GoogleMap.OnMapLongClickListener;
import com.google.android.gms.maps.GoogleMap.OnMarkerClickListener;
@@ -64,15 +64,20 @@
import com.google.android.gms.maps.model.TileProvider;
import org.osgeo.proj4j.units.DegreeUnit;
+import org.osgeo.proj4j.units.Unit;
+import org.osgeo.proj4j.units.Units;
import java.sql.SQLException;
import java.text.DecimalFormat;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
@@ -86,14 +91,22 @@
import mil.nga.geopackage.GeoPackageManager;
import mil.nga.geopackage.core.contents.Contents;
import mil.nga.geopackage.core.contents.ContentsDao;
+import mil.nga.geopackage.core.srs.SpatialReferenceSystem;
import mil.nga.geopackage.extension.link.FeatureTileTableLinker;
import mil.nga.geopackage.factory.GeoPackageFactory;
import mil.nga.geopackage.features.columns.GeometryColumns;
+import mil.nga.geopackage.features.index.FeatureIndexListResults;
import mil.nga.geopackage.features.index.FeatureIndexManager;
+import mil.nga.geopackage.features.index.FeatureIndexResults;
+import mil.nga.geopackage.features.index.FeatureIndexType;
+import mil.nga.geopackage.features.index.MultipleFeatureIndexResults;
import mil.nga.geopackage.features.user.FeatureCursor;
import mil.nga.geopackage.features.user.FeatureDao;
import mil.nga.geopackage.features.user.FeatureRow;
import mil.nga.geopackage.geom.GeoPackageGeometryData;
+import mil.nga.geopackage.map.MapUtils;
+import mil.nga.geopackage.map.features.FeatureInfoBuilder;
+import mil.nga.geopackage.map.geom.FeatureShapes;
import mil.nga.geopackage.map.geom.GoogleMapShape;
import mil.nga.geopackage.map.geom.GoogleMapShapeConverter;
import mil.nga.geopackage.map.geom.GoogleMapShapeMarkers;
@@ -107,6 +120,7 @@
import mil.nga.geopackage.map.geom.PolygonHoleMarkers;
import mil.nga.geopackage.map.geom.ShapeMarkers;
import mil.nga.geopackage.map.geom.ShapeWithChildrenMarkers;
+import mil.nga.geopackage.map.tiles.TileBoundingBoxMapUtils;
import mil.nga.geopackage.map.tiles.overlay.BoundedOverlay;
import mil.nga.geopackage.map.tiles.overlay.FeatureOverlay;
import mil.nga.geopackage.map.tiles.overlay.FeatureOverlayQuery;
@@ -121,19 +135,24 @@
import mil.nga.geopackage.tiles.features.FeatureTiles;
import mil.nga.geopackage.tiles.features.custom.NumberFeaturesTile;
import mil.nga.geopackage.tiles.matrixset.TileMatrixSet;
+import mil.nga.geopackage.tiles.matrixset.TileMatrixSetDao;
import mil.nga.geopackage.tiles.user.TileDao;
import mil.nga.mapcache.data.GeoPackageDatabase;
import mil.nga.mapcache.data.GeoPackageDatabases;
import mil.nga.mapcache.data.GeoPackageFeatureOverlayTable;
+import mil.nga.mapcache.data.GeoPackageFeatureTable;
import mil.nga.mapcache.data.GeoPackageTable;
+import mil.nga.mapcache.data.GeoPackageTableType;
import mil.nga.mapcache.data.GeoPackageTileTable;
import mil.nga.mapcache.filter.InputFilterMinMax;
import mil.nga.mapcache.indexer.IIndexerTask;
import mil.nga.mapcache.load.ILoadTilesTask;
import mil.nga.mapcache.load.LoadTilesTask;
import mil.nga.wkb.geom.Geometry;
+import mil.nga.wkb.geom.GeometryEnvelope;
import mil.nga.wkb.geom.GeometryType;
import mil.nga.wkb.geom.LineString;
+import mil.nga.wkb.util.GeometryEnvelopeBuilder;
import mil.nga.wkb.util.GeometryPrinter;
/**
@@ -143,7 +162,7 @@
*/
public class GeoPackageMapFragment extends Fragment implements
OnMapReadyCallback, OnMapLongClickListener, OnMapClickListener, OnMarkerClickListener,
- OnMarkerDragListener, ILoadTilesTask, IIndexerTask {
+ OnMarkerDragListener, ILoadTilesTask, IIndexerTask, OnCameraIdleListener {
/**
* Max features key for saving to preferences
@@ -165,6 +184,11 @@ public class GeoPackageMapFragment extends Fragment implements
*/
private GoogleMap map;
+ /**
+ * Map loaded flag
+ */
+ private boolean mapLoaded = false;
+
/**
* View
*/
@@ -200,10 +224,25 @@ public class GeoPackageMapFragment extends Fragment implements
*/
private MapUpdateTask updateTask;
+ /**
+ * Update features task
+ */
+ private MapFeaturesUpdateTask updateFeaturesTask;
+
+ /**
+ * Update lock for creating and cancelling update tasks
+ */
+ private Lock updateLock = new ReentrantLock();
+
/**
* Mapping of open GeoPackages by name
*/
- private Map geoPackages = new HashMap();
+ private Map geoPackages = new HashMap<>();
+
+ /**
+ * Mapping of open GeoPackage feature DAOs
+ */
+ private Map> featureDaos = new HashMap<>();
/**
* Vibrator
@@ -270,6 +309,21 @@ public class GeoPackageMapFragment extends Fragment implements
*/
private String editFeaturesTable;
+ /**
+ * Feature shapes
+ */
+ private FeatureShapes featureShapes = new FeatureShapes();
+
+ /**
+ * Current zoom level
+ */
+ private int currentZoom = -1;
+
+ /**
+ * Flag indicating if the initial zoom is still needed
+ */
+ private boolean needsInitialZoom = true;
+
/**
* Mapping between marker ids and the feature ids
*/
@@ -462,13 +516,18 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container,
return touch;
}
+ /**
+ * {@inheritDoc}
+ */
@Override
public void onMapReady(GoogleMap googleMap) {
map = googleMap;
initializeMap();
}
-
+ /**
+ * Initialize the map
+ */
private void initializeMap() {
if (map == null) return;
@@ -484,10 +543,52 @@ private void initializeMap() {
map.setOnMapClickListener(this);
map.setOnMarkerClickListener(this);
map.setOnMarkerDragListener(this);
+ map.setOnCameraIdleListener(this);
map.getUiSettings().setZoomControlsEnabled(true);
- if (visible) {
- updateInBackground(active.isModified());
+ map.setOnMapLoadedCallback(new GoogleMap.OnMapLoadedCallback() {
+ @Override
+ public void onMapLoaded() {
+ updateInBackground(true);
+ mapLoaded = true;
+ }
+ });
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onCameraIdle() {
+
+ // If visible & not editing a shape, update the feature shapes for the current map view region
+ if (visible && (!editFeaturesMode || editFeatureType == null || (editPoints.isEmpty() && editFeatureMarker == null))) {
+
+ int previousZoom = currentZoom;
+ int zoom = (int) MapUtils.getCurrentZoom(map);
+ currentZoom = zoom;
+ if (zoom != previousZoom) {
+ // Zoom level changed, remove all feature shapes
+ featureShapes.removeShapes();
+ } else {
+ // Remove shapes no longer visible on the map view
+ featureShapes.removeShapesNotWithinMap(map);
+ }
+
+ BoundingBox mapViewBoundingBox = MapUtils.getBoundingBox(map);
+ double toleranceDistance = MapUtils.getToleranceDistance(view, map);
+ int maxFeatures = getMaxFeatures();
+
+ updateLock.lock();
+ try {
+ if (updateFeaturesTask != null) {
+ updateFeaturesTask.cancel(false);
+ }
+ updateFeaturesTask = new MapFeaturesUpdateTask();
+ updateFeaturesTask.execute(false, maxFeatures, mapViewBoundingBox, toleranceDistance, true);
+ } finally {
+ updateLock.unlock();
+ }
}
}
@@ -905,6 +1006,8 @@ private void saveEditFeatures() {
try {
FeatureDao featureDao = geoPackage.getFeatureDao(editFeaturesTable);
long srsId = featureDao.getGeometryColumns().getSrsId();
+ FeatureIndexManager indexer = new FeatureIndexManager(getActivity(), geoPackage, featureDao);
+ List indexedTypes = indexer.getIndexedTypes();
GoogleMapShapeConverter converter = new GoogleMapShapeConverter(
featureDao.getProjection());
@@ -921,6 +1024,10 @@ private void saveEditFeatures() {
pointGeomData.setGeometry(point);
newPoint.setGeometry(pointGeomData);
featureDao.insert(newPoint);
+ updateLastChange(geoPackage, featureDao);
+ if (!indexedTypes.isEmpty()) {
+ indexer.index(newPoint, indexedTypes);
+ }
}
changesMade = true;
break;
@@ -934,6 +1041,10 @@ private void saveEditFeatures() {
lineStringGeomData.setGeometry(lineString);
newLineString.setGeometry(lineStringGeomData);
featureDao.insert(newLineString);
+ updateLastChange(geoPackage, featureDao);
+ if (!indexedTypes.isEmpty()) {
+ indexer.index(newLineString, indexedTypes);
+ }
changesMade = true;
break;
@@ -948,6 +1059,10 @@ private void saveEditFeatures() {
polygonGeomData.setGeometry(polygon);
newPolygon.setGeometry(polygonGeomData);
featureDao.insert(newPolygon);
+ updateLastChange(geoPackage, featureDao);
+ if (!indexedTypes.isEmpty()) {
+ indexer.index(newPolygon, indexedTypes);
+ }
changesMade = true;
break;
@@ -962,27 +1077,34 @@ private void saveEditFeatures() {
.queryForIdRow(featureId);
GeoPackageGeometryData geomData = featureRow.getGeometry();
geomData.setGeometry(geometry);
+ if(geomData.getEnvelope() != null){
+ geomData.setEnvelope(GeometryEnvelopeBuilder.buildEnvelope(geometry));
+ }
featureDao.update(featureRow);
+ updateLastChange(geoPackage, featureDao);
+ if (!indexedTypes.isEmpty()) {
+ indexer.index(featureRow, indexedTypes);
+ }
} else {
featureDao.deleteById(featureId);
editFeatureMarker = null;
+ updateLastChange(geoPackage, featureDao);
+ if (!indexedTypes.isEmpty()) {
+ indexer.deleteIndex(featureId, indexedTypes);
+ }
}
- updateLastChange(geoPackage, featureDao);
active.setModified(true);
break;
}
- if (changesMade) {
- updateLastChange(geoPackage, featureDao);
- }
} catch (Exception e) {
if (GeoPackageUtils.isFutureSQLiteException(e)) {
GeoPackageUtils
.showMessage(
getActivity(),
getString(R.string.edit_features_save_label)
- + " " + editFeatureType.name(),
+ + " " + editFeaturesTable,
"GeoPackage was created using a more recent SQLite version unsupported by Android");
} else {
GeoPackageUtils.showMessage(getActivity(),
@@ -999,7 +1121,7 @@ private void saveEditFeatures() {
if (changesMade) {
active.setModified(true);
- updateInBackground(false);
+ updateInBackground(false, true);
}
}
@@ -1053,7 +1175,29 @@ public void onClick(DialogInterface dialog, int which) {
active.setModified(false);
resetBoundingBox();
resetEditFeatures();
- updateInBackground(true);
+ if (mapLoaded) {
+ updateInBackground(true);
+ }
+ } else if (!visible) {
+ updateLock.lock();
+ try {
+ if (updateTask != null) {
+ if (updateTask.getStatus() != AsyncTask.Status.FINISHED) {
+ updateTask.cancel(false);
+ active.setModified(true);
+ }
+ updateTask = null;
+ }
+ if (updateFeaturesTask != null) {
+ if (updateFeaturesTask.getStatus() != AsyncTask.Status.FINISHED) {
+ updateFeaturesTask.cancel(false);
+ active.setModified(true);
+ }
+ updateFeaturesTask = null;
+ }
+ } finally {
+ updateLock.unlock();
+ }
}
}
@@ -1111,7 +1255,7 @@ public boolean handleMenuClick(MenuItem item) {
selectEditFeatures();
} else {
resetEditFeatures();
- updateInBackground(false);
+ updateInBackground(false, true);
}
break;
case R.id.map_bounding_box:
@@ -1120,7 +1264,7 @@ public boolean handleMenuClick(MenuItem item) {
if (editFeaturesMode) {
resetEditFeatures();
- updateInBackground(false);
+ updateInBackground(false, true);
}
boundingBoxMode = true;
@@ -1194,7 +1338,7 @@ public void onClick(DialogInterface dialog, int id) {
editFeaturesMenuItem
.setIcon(R.drawable.ic_features_active);
- updateInBackground(false);
+ updateInBackground(false, true);
} catch (Exception e) {
GeoPackageUtils
@@ -1361,7 +1505,7 @@ public void onClick(DialogInterface dialog,
Editor editor = settings.edit();
editor.putInt(MAX_FEATURES_KEY, maxFeature);
editor.commit();
- updateInBackground(false);
+ updateInBackground(false, true);
}
}
})
@@ -1408,13 +1552,35 @@ private void setMapType(int mapType) {
/**
* Update the map by kicking off a background task
*
- * @param zoom
+ * @param zoom zoom flag
*/
private void updateInBackground(boolean zoom) {
+ updateInBackground(zoom, false);
+ }
- if (updateTask != null) {
- updateTask.cancel(false);
+ /**
+ * Update the map by kicking off a background task
+ *
+ * @param zoom zoom flag
+ * @param filter filter features flag
+ */
+ private void updateInBackground(boolean zoom, boolean filter) {
+
+ MapUpdateTask localUpdateTask = null;
+ updateLock.lock();
+ try {
+ if (updateTask != null) {
+ updateTask.cancel(false);
+ }
+ if (updateFeaturesTask != null) {
+ updateFeaturesTask.cancel(false);
+ }
+ updateTask = new MapUpdateTask();
+ localUpdateTask = updateTask;
+ } finally {
+ updateLock.unlock();
}
+
map.clear();
for (GeoPackage geoPackage : geoPackages.values()) {
try {
@@ -1424,26 +1590,146 @@ private void updateInBackground(boolean zoom) {
}
}
geoPackages.clear();
+ featureDaos.clear();
+
+ if (zoom) {
+ zoomToActiveBounds();
+ }
+
featuresBoundingBox = null;
tilesBoundingBox = null;
featureOverlayTiles = false;
featureOverlayQueries.clear();
+ featureShapes.clear();
markerIds.clear();
- updateTask = new MapUpdateTask();
int maxFeatures = getMaxFeatures();
- updateTask.execute(zoom, maxFeatures);
+
+ BoundingBox mapViewBoundingBox = MapUtils.getBoundingBox(map);
+ double toleranceDistance = MapUtils.getToleranceDistance(view, map);
+
+ localUpdateTask.execute(zoom, maxFeatures, mapViewBoundingBox, toleranceDistance, filter);
}
/**
- * Update the map in the background
+ * Zoom to the active feature and tile table data bounds
*/
- private class MapUpdateTask extends AsyncTask