如何在Android Studio中用GeoTools读取ZIP格式Shapefile并导出到Google Maps
实现思路与示例代码
前置配置(GeoTools适配Android)
首先需要在项目中配置GeoTools的依赖源和排除不兼容的依赖项:
- 在项目的
settings.gradle中添加GeoTools的官方仓库:
dependencyResolutionManagement { repositories { maven { url "https://repo.osgeo.org/repository/release/" } google() mavenCentral() } }
- 在模块级
build.gradle中添加依赖:
dependencies { // GeoTools 核心与Shapefile解析依赖 implementation('org.geotools:gt-shapefile:28.2') { exclude group: 'javax.media', module: 'jai_core' exclude group: 'javax.media', module: 'jai_imageio' exclude group: 'javax.xml.stream', module: 'stax-api' } // Google Maps SDK implementation 'com.google.android.gms:play-services-maps:18.2.0' }
核心实现代码
1. 读取ZIP格式Shapefile并转换为Google Maps多边形对象
import android.graphics.Color; import com.google.android.gms.maps.model.LatLng; import com.google.android.gms.maps.model.PolygonOptions; import org.geotools.data.shapefile.ShapefileDataStore; import org.geotools.data.simple.SimpleFeatureIterator; import org.locationtech.jts.geom.Coordinate; import org.locationtech.jts.geom.Polygon; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public List<PolygonOptions> parseShapefileZip(String zipFilePath) throws IOException { List<PolygonOptions> result = new ArrayList<>(); File shapeZip = new File(zipFilePath); Map<String, Object> params = new HashMap<>(); params.put("url", shapeZip.toURI().toURL()); // 根据你的Shapefile实际编码调整,国内常用编码为GBK、UTF-8 params.put("charset", "GBK"); ShapefileDataStore dataStore = new ShapefileDataStore(params); String typeName = dataStore.getTypeNames()[0]; try (SimpleFeatureIterator featureIterator = dataStore.getFeatureSource(typeName).getFeatures().features()) { while (featureIterator.hasNext()) { var feature = featureIterator.next(); Polygon jtsPolygon = (Polygon) feature.getDefaultGeometry(); List<LatLng> polygonPoints = new ArrayList<>(); // 转换JTS坐标为Google Maps LatLng格式 for (Coordinate coord : jtsPolygon.getCoordinates()) { polygonPoints.add(new LatLng(coord.y, coord.x)); } // 构造地图多边形样式,可自定义调整 PolygonOptions options = new PolygonOptions() .addAll(polygonPoints) .strokeWidth(4f) .strokeColor(Color.RED) .fillColor(0x7F3DDC84); result.add(options); } } finally { dataStore.dispose(); } return result; }
2. 将多边形加载到Google Maps
在onMapReady回调中调用解析方法,注意大文件解析需要放在子线程执行,避免阻塞主线程导致ANR:
@Override public void onMapReady(GoogleMap googleMap) { mMap = googleMap; // 子线程执行解析逻辑 new Thread(() -> { try { List<PolygonOptions> polygons = parseShapefileZip("本地Shapefile压缩包的绝对路径"); // 切回主线程操作地图 runOnUiThread(() -> { for (PolygonOptions option : polygons) { mMap.addPolygon(option); } }); } catch (IOException e) { e.printStackTrace(); } }).start(); }
替代方案(轻量无GeoTools依赖)
如果对APK包体积有要求,或者遇到GeoTools的兼容问题,可以直接手动解析Shapefile的.shp二进制结构:
- 从ZIP包中提取后缀为
.shp、.dbf的文件 - 按照Shapefile官方格式规范读取坐标点和属性数据,直接转换为Google Maps的LatLng对象即可,整体代码量在300行以内,不需要引入第三方重型依赖
注意事项
- 若Shapefile使用的坐标参考系不是WGS84,需要先做坐标转换,否则加载到地图上会出现偏移
- 读取本地文件前需要先申请对应Android版本的存储权限
- 如果需要将解析后的地块数据存储到Firebase,可以直接把每个多边形的坐标列表、属性字段转换为JSON格式存储即可
内容的提问来源于stack exchange,提问作者Teo Pal
相关产品推荐
相关产品推荐

