Android ArcGis runtime 100 基础操作

1.为什么升级100.0

我之前在公司做地图一直用的是arcgis10.2,经过多年的开发,这个版本的工具类封装的非常方便,自己也没有时间去换100.0的版本。但是突然有一天工程反馈说他的9.0的安卓手机打开地图直接崩溃,在网上找了半天没有解决arcgis10在9.0手机上的兼容问题,所以只好去换最先的100.0了。但是100.0与10.0的api完全不同,在开发中踩了许多坑,所以了这篇文章希望能帮到之后遇到同样问题的同学。

下面代码如果有错误请大神指出,我会及时改正

2.集成ArcGIS Runtime SDK

集成方式在官方文档中有介绍

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.最后一步添加权限

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

3.代码

首先直接上全部代码

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<String,List<LayerFieldBean.FieldModels>> 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<LayerFieldBean> list = (ArrayList<LayerFieldBean>) GsonUtils.fromJsonForList(string, LayerFieldBean.class);
                    for (LayerFieldBean item : list) {
                        List<LayerFieldBean.FieldModels> li= map.get(item.getTableName());
                        if(li==null){
                            li=new ArrayList<>();
                            map.put(item.getTableName(),li);
                        }
                        List<LayerFieldBean.FieldModels> 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<Point> 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<Point> 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<Point> 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<List<IdentifyLayerResult>> listListenableFuture = mapView.identifyLayersAsync(
                screenPoint, 12, false, 10);
        listListenableFuture.addDoneListener(new Runnable() {
            @Override
            public void run() {
                iView.dismissLoading();
                try {
                    //IdentifyLayerResult:每个图层的返回结果
                    List<IdentifyLayerResult> identifyLayerResults = listListenableFuture.get();
                    if (identifyLayerResults != null && identifyLayerResults.size() > 0) {
                        int count = 0;
                        List<Map<String, Object>> attributes = new ArrayList<>();
                        List<String>names=new ArrayList<>();
                        List<Geometry> geometrys = new ArrayList<>();
                        for (IdentifyLayerResult identifyLayerResult : identifyLayerResults) {
                            String name = identifyLayerResult.getLayerContent().getName();
                            Log.e("xyh", "run: " + name);
                            List<GeoElement> elements = identifyLayerResult.getElements();
                            if (elements.size() > 0) {
                                count++;
                                GeoElement element = elements.get(0);
                                Map<String, Object> attribute = element.getAttributes();
                                attributes.add(attribute);
                                names.add(name);
                                Geometry geometry = element.getGeometry();
                                geometrys.add(geometry);
                                if (count >= 3) {
                                    break;
                                }
                            }
                        }
                        if (geometrys.size() > 0 && attributes.size() > 0) {
                            FeaturesToMap(attributes, geometrys,names);
                        }
                    }
                } catch (Exception e) {
                    iView.showError(R.string.not_element_error);
                }
            }
        });
    }

    /**
     * 要素识别
     *
     * @param screenPoint
     */
    private void IdentifyFeatures(android.graphics.Point screenPoint) {
        iView.showLoading();
        LayerList list = arcGISMap.getOperationalLayers();
        FeatureLayer mFeatureLayer = null;
        for (int i = list.size() - 1; i > 0; i--) {
            Layer layer = arcGISMap.getOperationalLayers().get(i);
            if (layer instanceof FeatureLayer) {
                mFeatureLayer = (FeatureLayer) layer;
                break;
            }
        }
        if (mFeatureLayer != null) {
            //查询mFeatureLayer图层中点击范围内的所有地理要素
            final ListenableFuture<IdentifyLayerResult> identifyLayerResultListenableFuture = mapView.identifyLayerAsync(
                    mFeatureLayer, screenPoint, 12, false, 10);
            identifyLayerResultListenableFuture.addDoneListener(new Runnable() {
                @Override
                public void run() {
                    iView.dismissLoading();
                    try {
                        IdentifyLayerResult identifyLayerResult = identifyLayerResultListenableFuture.get();
                        String name = identifyLayerResult.getLayerContent().getName();
                        Log.e("xyh", "run: " + name);
                        List<GeoElement> elements = identifyLayerResult.getElements();
                        if (elements.size() > 0) {
                            GeoElement element = elements.get(0);
                            Map<String, Object> attributes = element.getAttributes();
                            Geometry geometry = element.getGeometry();
                            //查询结果显示
//                            FeaturesToMap(attributes,geometry);
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            });
        } else {
            iView.dismissLoading();
        }
    }

    //I查询结果显示到地图上
    private void FeaturesToMap(List<Map<String, Object>> attributes, List<Geometry> geometrys) {
       
    }

    @Override
    public void SearchToMap(QueryResultBean2.HitsItem qrb, boolean isaddtososoids) {
        QueryResultBean2._source source = qrb.get_source();
        double y = source.getNorth();
        double x = source.getEast();
        Point p = new Point(x, y);
        BitmapDrawable image = (BitmapDrawable) iView.getContext().getResources().getDrawable(R.mipmap.d);
        PictureMarkerSymbol symbol = new PictureMarkerSymbol(image);
        Graphic graphic = new Graphic(p, symbol);
        ListenableList listenableList = graphicsOverlay.getGraphics();
        listenableList.clear();
        listenableList.add(graphic);
        zoomToScale(p, mapView.getMapScale());

        callout = mapView.getCallout();
        View view = LayoutInflater.from(iView.getContext()).inflate(R.layout.callout_layout, null);
        TextView tv1 = (TextView) view.findViewById(R.id.callout_tv1);
        TextView tv2 = (TextView) view.findViewById(R.id.callout_tv2);
        ImageButton callout_clous = (ImageButton) view.findViewById(R.id.callout_clous);
        tv1.setText(source.getName());
        tv2.setText("地址:" + source.getAddname());
        callout.setContent(view);
        callout.setLocation(p);
//        callout.setOffset(0, DisplayUtils.dp2px(MainActivity.this, 25));
        Callout.Style calloutStyle = callout.getStyle();
        //设置尖尖角的位置,尖尖显示在气泡的下放,
        calloutStyle.setLeaderPosition(Callout.Style.LeaderPosition.LEFT_MIDDLE);
        calloutStyle.setBorderColor(R.color.colorDominantTone);
        calloutStyle.setCornerRadius(0);

//        calloutStyle.setCornerCurveDp(0, mContext);
        callout.setStyle(calloutStyle);
        callout_clous.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                callout.dismiss();
//                graphicsOverlay.getGraphics().
            }
        });
        callout.show();
    }

    /**
     * 以一点为中心放大或缩小
     *
     * @param point
     * @param scale 比例尺
     */
    private void zoomToScale(Point point, double scale) {
        mapView.setViewpointCenterAsync(point, scale);
    }

    public Symbol getSymbol(String typeName) {
        int color = Color.RED;
        if (typeName.equalsIgnoreCase("point")) {
            SimpleMarkerSymbol sms = new SimpleMarkerSymbol(SimpleMarkerSymbol.Style.CIRCLE, color, 10);
            return sms;
        } else if (typeName.equalsIgnoreCase("polyline")) {
            SimpleLineSymbol fillSymbol = new SimpleLineSymbol(SimpleLineSymbol.Style.SOLID, color, 5);
            return fillSymbol;
        } else {
            SimpleFillSymbol sfs = new SimpleFillSymbol(SimpleFillSymbol.Style.SOLID, Color.RED, null);
            return sfs;
        }
    }
}

4.几个注意点

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);
}

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值