我之前在公司做地图一直用的是arcgis10.2,经过多年的开发,这个版本的工具类封装的非常方便,自己也没有时间去换100.0的版本。但是突然有一天工程反馈说他的9.0的安卓手机打开地图直接崩溃,在网上找了半天没有解决arcgis10在9.0手机上的兼容问题,所以只好去换最先的100.0了。但是100.0与10.0的api完全不同,在开发中踩了许多坑,所以了这篇文章希望能帮到之后遇到同样问题的同学。
下面代码如果有错误请大神指出,我会及时改正
集成方式在官方文档中有介绍
1.首先要在build.gradle文件中添加Esri的仓库
allprojects {
repositories {
google()
jcenter()
maven {
url 'https://esri.bintray.com/arcgis'
}
}
}
2.第二步添加依赖
dependencies {
implementation 'com.esri.arcgisruntime:arcgis-android:100.4.0'
}
3.根据官方文档要求在app模块build.gradle文件中添加如下代码设置java兼容版本
android {
[...]
module.
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
4.最后一步添加权限
首先直接上全部代码
public class MainPresenter extends BasePresenter implements MainContract.Presenter {
public static final String POLYLINE = "POLYLINE";//测量距离
public static final String POLYGON = "POLYGON";//测量面积
public static final String IDENTIFY = "IDENTIFY";//要素识别
public static final String NULL = "NULL";//什么都不做
private MapView mapView;
private ArcGISMap arcGISMap;
private GraphicsOverlay graphicsOverlay;
private String MapOperationType = NULL;
boolean isCanRotate = true;
private View contentview;
private TextView tv;
private ImageView iv;
private Callout callout;
private final MainContract.View iView;
private DecimalFormat df;
private SimpleDateFormat formatter;
Map> map=new HashMap<>();
public MainPresenter(BaseContract.View view) {
super(view);
iView = (MainContract.View) getmView();
}
//初始化地图
@SuppressLint("ClickableViewAccessibility")
@Override
public void initMap() {
mapView = iView.getMapView();
mapView.setAttributionTextVisible(false);
arcGISMap = new ArcGISMap();
//底图地址
String theURLString = common.Constance.BASE_MAP;
ArcGISTiledLayer mainArcGISVectorTiledLayer = new ArcGISTiledLayer(theURLString);
arcGISMap.setBasemap(new Basemap(mainArcGISVectorTiledLayer));
mapView.setMap(arcGISMap);
//新建并添加绘画图层
graphicsOverlay = new GraphicsOverlay();
mapView.getGraphicsOverlays().add(graphicsOverlay);
//添加地图的点击事件监听
mapView.setOnTouchListener(new DefaultMapViewOnTouchListener(iView.getContext(), mapView) {
@Override
public boolean onSingleTapConfirmed(MotionEvent e) {
switch (MapOperationType) {
case NULL:
return super.onSingleTapConfirmed(e);
case POLYLINE:
//距离测量
Point clickPoint = mapView.screenToLocation(new android.graphics.Point(Math.round(e.getX()), Math.round(e.getY())));
MeasuringDistance(clickPoint);
return true;
case POLYGON:
//测量面积
Point clickPoint2 = mapView.screenToLocation(new android.graphics.Point(Math.round(e.getX()), Math.round(e.getY())));
MeasuringArea(clickPoint2);
return true;
case IDENTIFY:
//要素识别
android.graphics.Point screenPoint = new android.graphics.Point(Math.round(e.getX()), Math.round(e.getY()));
if (arcGISMap.getOperationalLayers().size() > 0) {
// IdentifyFeatures(screenPoint);
IdentifyAllFeatures(screenPoint);
} else {
iView.showError(R.string.not_cxmap_error);
}
return true;
}
return super.onSingleTapConfirmed(e);
}
@Override
public boolean onRotate(MotionEvent event, double rotationAngle) {
//控制是否可以旋转地图
if (isCanRotate) {
return super.onRotate(event, rotationAngle);
} else {
return true;
}
}
});
//初始化范围
arcGISMap.setInitialViewpoint(new Viewpoint(new Point(542420.836330969, 2559890.377991153, SpatialReference.create(4547)), 60000));
//获取所有的图层的要显示字段
iView.showLoading();
String URL = common.Constance.LAYERFIELD;
HttpUtils.requstNet(URL, null, new IRequst() {
@Override
public void onSuccess(String string) {
iView.dismissLoading();
try {
ArrayList list = (ArrayList) GsonUtils.fromJsonForList(string, LayerFieldBean.class);
for (LayerFieldBean item : list) {
List li= map.get(item.getTableName());
if(li==null){
li=new ArrayList<>();
map.put(item.getTableName(),li);
}
List fieldModels = item.getFieldModels();
if(fieldModels!=null){
for(LayerFieldBean.FieldModels f:fieldModels)
li.add(f);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void onError(int code) {
iView.dismissLoading();
}
});
}
//地图操作——测量距离
@Override
public void MapOperation_MeasuringDistance() {
MapOperationType = POLYLINE;
}
//地图操作——测量面积
@Override
public void MapOperation_MeasuringArea() {
MapOperationType = POLYGON;
}
//地图操作——要素查询
@Override
public void MapOperation_IdentifyFeatures() {
MapOperationType = IDENTIFY;
}
//地图操作——清除所有操作
@Override
public void MapOperation_NULL() {
MapOperationType = NULL;
MDlist.clear();
MAlist.clear();
graphicsOverlay.getGraphics().clear();
Callout callout = mapView.getCallout();
callout.dismiss();
}
//地图操作——地图放大
@Override
public void MapOperation_Amplification() {
double scale = mapView.getMapScale();
mapView.setViewpointScaleAsync(scale * 0.5);
}
//地图操作——地图缩小
@Override
public void MapOperation_Shrink() {
double scale1 = mapView.getMapScale();
mapView.setViewpointScaleAsync(scale1 * 2);
}
//图层操作——切换底图
@Override
public void MapViewAddBaseLayer(String url) {
ArcGISTiledLayer mainArcGISVectorTiledLayer = new ArcGISTiledLayer(url);
arcGISMap.setBasemap(new Basemap(mainArcGISVectorTiledLayer));
}
//图层操作——添加专题图层
@Override
public void MapViewAddLayor(String url) {
LayerList mainLayerList = arcGISMap.getOperationalLayers();
ArcGISMapImageLayer imageLayer = new ArcGISMapImageLayer(url);
imageLayer.setId(url);
mainLayerList.add(imageLayer);
//添加FeatureLayer为了要素查询
FeatureTable featureTable = new ServiceFeatureTable(url);
FeatureLayer mFeatureLayer = new FeatureLayer(featureTable);
mFeatureLayer.setOpacity(0.1f);
mFeatureLayer.setId(url + "selected");
arcGISMap.getOperationalLayers().add(mFeatureLayer);
}
//图层操作——删除专题图层(根据地图url删除对应的图层)
@Override
public void MapViewRemoveLayor(String url) {
LayerList mainLayerList = arcGISMap.getOperationalLayers();
for (Layer layer : mainLayerList) {
if (TextUtils.equals(url, layer.getId())) {
mainLayerList.remove(layer);
break;
}
}
for (Layer layer : mainLayerList) {
if (TextUtils.equals(url + "selected", layer.getId())) {
mainLayerList.remove(layer);
break;
}
}
}
//地图操作——设置是否可以旋转
@Override
public void setCanRotate(boolean tag) {
isCanRotate = tag;
}
//地图操作——设置旋转角度
@Override
public void setAngle(double angle) {
mapView.setViewpointRotationAsync(angle);
}
@Override
public void start() {
}
@Override
public void destroy() {
}
/**
* 测量长度
*/
ArrayList MDlist = new ArrayList<>();
private void MeasuringDistance(Point clickPoint) {
SimpleMarkerSymbol simpleMarkerSymbol = new SimpleMarkerSymbol(SimpleMarkerSymbol.Style.CIRCLE, Color.RED, 10);
Graphic pointGraphic = new Graphic(clickPoint, simpleMarkerSymbol);
if (MDlist.size() == 0 || (MDlist.get(MDlist.size() - 1).getX() != clickPoint.getX() && MDlist.get(MDlist.size() - 1).getY() != clickPoint.getY()))
MDlist.add(clickPoint);
PointCollection borderCAtoNV = new PointCollection(mapView.getSpatialReference());
for (Point p : MDlist) {
borderCAtoNV.add(p);
}
Polyline polyline = new Polyline(borderCAtoNV);
SimpleLineSymbol fillSymbol = new SimpleLineSymbol(SimpleLineSymbol.Style.SOLID, Color.BLUE, 5);
Graphic lineGraphic = new Graphic(polyline, fillSymbol);
ListenableList listenableList = graphicsOverlay.getGraphics();
listenableList.clear();
listenableList.add(lineGraphic);
for (Point p : MDlist)
listenableList.add(new Graphic(p, simpleMarkerSymbol));
String longstr = calculateDistance(MDlist);
callout = mapView.getCallout();
if (contentview == null) {
contentview = LinearLayout.inflate(iView.getContext(), R.layout.mapview_content, null);
tv = contentview.findViewById(R.id.id_content_tv);
iv = contentview.findViewById(R.id.id_contentclose_iv);
}
tv.setText(longstr);
iv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
MDlist.remove(MDlist.size() - 1);
if (MDlist.size() >= 1) {
MeasuringDistance(MDlist.get(MDlist.size() - 1));
} else {
graphicsOverlay.getGraphics().clear();
callout.dismiss();
}
}
});
callout.show(contentview, MDlist.get(MDlist.size() - 1));
}
/**
* 计算长度
* @param list 点的集合
* @return
*/
private String calculateDistance(ArrayList list) {
if (df == null) {
df = new DecimalFormat("0.000");
}
double overallLength = 0;
if (list != null && list.size() > 1) {
for (int i = 1; i < list.size(); i++) {
Point p1 = list.get(i - 1);
Point p2 = list.get(i);
LinearUnit linearUnit = new LinearUnit(LinearUnitId.METERS);//距离单位
AngularUnit angularUnit = new AngularUnit(AngularUnitId.DEGREES);//角度单位
double distanceValue = GeometryEngine.distanceGeodetic(p1, p2, linearUnit, angularUnit, GeodeticCurveType.GEODESIC).getDistance();
overallLength += distanceValue;
}
}
if (overallLength >= 1000) {
overallLength /= 1000;
return df.format(overallLength) + "千米";
}
return df.format(overallLength) + "米";
}
/**
* 测量面积
*/
ArrayList MAlist = new ArrayList<>();
private void MeasuringArea(Point clickPoint) {
SimpleMarkerSymbol simpleMarkerSymbol = new SimpleMarkerSymbol(SimpleMarkerSymbol.Style.CIRCLE, Color.RED, 10);
Graphic pointGraphic = new Graphic(clickPoint, simpleMarkerSymbol);
if (MAlist.size() == 0 || (MAlist.get(MAlist.size() - 1).getX() != clickPoint.getX() && MAlist.get(MAlist.size() - 1).getY() != clickPoint.getY()))
MAlist.add(clickPoint);
PointCollection borderCAtoNV = new PointCollection(mapView.getSpatialReference());
for (Point p : MAlist) {
borderCAtoNV.add(p);
}
Polygon polygon = new Polygon(borderCAtoNV);
SimpleFillSymbol fillSymbol = new SimpleFillSymbol(SimpleFillSymbol.Style.DIAGONAL_CROSS, Color.BLUE, null);
Graphic fillGraphic = new Graphic(polygon, fillSymbol);
ListenableList listenableList = graphicsOverlay.getGraphics();
listenableList.clear();
listenableList.add(fillGraphic);
for (Point p : MAlist)
listenableList.add(new Graphic(p, simpleMarkerSymbol));
String longstr = calculateArea(polygon);
callout = mapView.getCallout();
if (contentview == null) {
contentview = LinearLayout.inflate(iView.getContext(), R.layout.mapview_content, null);
tv = contentview.findViewById(R.id.id_content_tv);
iv = contentview.findViewById(R.id.id_contentclose_iv);
}
tv.setText(longstr);
iv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
MAlist.remove(MAlist.size() - 1);
if (MAlist.size() >= 1) {
MeasuringArea(MAlist.get(MAlist.size() - 1));
} else {
graphicsOverlay.getGraphics().clear();
callout.dismiss();
}
}
});
callout.show(contentview, MAlist.get(MAlist.size() - 1));
}
/**
* 计算面积
*
* @param polygon 面要素
* @return
*/
private String calculateArea(Polygon polygon) {
if (df == null) {
df = new DecimalFormat("0.000");
}
double overallArea = 0;
overallArea = GeometryEngine.area(polygon);
//注意!测量面积时如果点的顺序如果是逆时针的,面积有可能是负数,需要处理一下
if (overallArea < 0) {
polygon = (Polygon) GeometryEngine.simplify(polygon);
overallArea = GeometryEngine.area(polygon);
}
if (overallArea >= 1000000) {
overallArea /= 1000000;
return df.format(overallArea) + "平方千米";
}
return df.format(overallArea) + "平方米";
}
/**
* I查询所有可见图层
*
* @param screenPoint
*/
DecimalFormat decimalFormat;
private void IdentifyAllFeatures(android.graphics.Point screenPoint) {
iView.showLoading();
final ListenableFuture> listListenableFuture = mapView.identifyLayersAsync(
screenPoint, 12, false, 10);
listListenableFuture.addDoneListener(new Runnable() {
@Override
public void run() {
iView.dismissLoading();
try {
//IdentifyLayerResult:每个图层的返回结果
List identifyLayerResults = listListenableFuture.get();
if (identifyLayerResults != null && identifyLayerResults.size() > 0) {
int count = 0;
List
1.100.0之后没有设置初始化范围的方法(setExtent())了,想要初始化范围需要利用中心点和比例尺来确定范围。
arcGISMap.setInitialViewpoint()
2.测量面积时,如果点的方向是逆时针的话,会出现负数。所以我们要加个判断,如果是负数需要
GeometryEngine.simplify()方法处理一下。
overallArea = GeometryEngine.area(polygon);
if (overallArea < 0) {
polygon = (Polygon) GeometryEngine.simplify(polygon);
overallArea = GeometryEngine.area(polygon);
}