外業數據採集平臺(GPS+Android Studio+Arcgis for android 100.2.1)

来源:https://www.cnblogs.com/InProsperity/archive/2018/07/05/Android_GIS.html
-Advertisement-
Play Games

平臺目的:該平臺主要用於室外,通過平板或者手機接收GPS坐標,實時繪製點、線、面數據,以便後續進行海域監測、土地確權、地圖測量提供有效數據和依據。 技術路線:Android studio3.0.1+Arcgis for android 100.2.1+GPS ...


歡迎加入QQ溝通交流群:186178114(群名:外業數據採集(GIS+GPS))

 

外業數據採集平臺

1. 綜述

在室外,通過平板或者手機接收GPS坐標,實時繪製點、線、面數據,以便為後續進行海域監測、土地確權、地圖繪圖提供有效數據和依據。

2. 技術路線

   Android studio3.0.1+Arcgis for android 100.2.1+GPS

2.1 Android studio工具:

2.2 Android studio工具下載地址:

http://www.android-studio.org/index.php/download/hisversion

 

2.2.1 Android studio安裝與配置

參考博客地址:https://www.cnblogs.com/xiadewang/p/7820377.html

2.3 Arcgis for android

Arcgis for androidESRI公司專門為Android手機開發GIS地圖軟體的一套API,整合廣泛的地圖和GIS能力線上或離線,包括編輯,分析,地理編碼,路由,網路地圖管理,數據可視化,移動地圖包和矢量平鋪層。

2.3.1 Arcgis for android SDK

https://developers.arcgis.com/android/latest/

 

2.3.2 Arcgis for android配置

http://www.cnblogs.com/gis-luq/p/4760370.html

 

2.4 技術架構

外業數據採集平臺採用的是Android最原生也是最基礎的架構,可以理解為MVCController即是ActivityFragment,但是這兩者掌握了Android系統中絕大多數的資源,並且在內部直接控制View,因此傳統的Android App一般是以ActivityFragment為核心,將網路模塊,資料庫管理模塊,文件管理模塊,常用工具類等分離成若幹工具類包,供ActivityFragment使用。由於項目不是很大,最後決定採用Android預設的架構,而沒有採用MVP或者MVVM架構。

 

3. 平臺展示與實例代碼

3.1 登錄與主界面

3.1.1 登錄

 

3.1.2 主界面

 

包含最基本的:放大、縮小、旋轉、指北針、比例尺等基本功能。

3.2 基礎功能

3.2.1 導入矢量

支持導入內置SD卡和外置SD卡中.shp格式的數據。

 

 1 private ShapefileFeatureTable featureLayerShapefile(String filePath, String fileType, boolean
 2         isFullExtent, String dapFilePath, boolean isVisible, float opacity, boolean isCheckLayerName) {
 3     if (!check(filePath, "SHP", isCheckLayerName)) {
 4         return null;
 5     }
 6     ShapefileFeatureTable shapefileFeatureTable = new ShapefileFeatureTable(filePath);
 7     shapefileFeatureTable.loadAsync();
 8     ShapefileFeatureTable finalShapefileFeatureTable = shapefileFeatureTable;
 9     shapefileFeatureTable.addDoneLoadingListener(() -> {
10         if (finalShapefileFeatureTable.getLoadStatus() == LoadStatus.LOADED) {
11             // create a feature layer to display the shapefile
12             FeatureLayer featureLayer = new FeatureLayer(finalShapefileFeatureTable);
13             if ("".equals(dapFilePath)) {
14                 featureLayer.setDescription(filePath);
15             } else {
16                 featureLayer.setDescription(dapFilePath);
17             }
18             featureLayer.setVisible(isVisible);
19             mMapView.getMap().getOperationalLayers().add(featureLayer);
20             if (isFullExtent) {
21                 Envelope envelope = LayerUtil.GetLayerFullExtend(featureLayer);
22                 if (envelope != null && !envelope.isEmpty()) {
23                     mMapView.setViewpointGeometryAsync(envelope
24                             , LayerUtil.FullExtendPadding);
25                 }
26             }
27         } else {
28             String error = "Shapefile feature table failed to load: " +
29                     finalShapefileFeatureTable
30                             .getLoadError().toString();
31             Log.e(TAG, error);
32         }
33     });
34 
35     return shapefileFeatureTable;
36 } 

3.2.2 導入影像

支持導入內置SD卡和外置SD卡中.tif影像格式的數據。

 

 1 private Layer loadLocalTif(ArcGISMap arcGISMap, String filePath, String extendName, boolean
 2             isVisible, float opacity, boolean isCheckLayerName) {
 3         if (!check(filePath, extendName, isCheckLayerName)) {
 4             return null;
 5         }
 6         Raster raster = new Raster(filePath);
 7         if (raster == null)
 8             return null;
 9 
10         final RasterLayer rasterLayer = new RasterLayer(raster);
11         rasterLayer.setName("基礎底圖");
12         rasterLayer.setDescription(filePath);
13         rasterLayer.setVisible(isVisible);
14         rasterLayer.setOpacity(opacity);
15         Basemap basemap = new Basemap(rasterLayer);
16         mMapView.getMap().setBasemap(basemap);
17         rasterLayer.addDoneLoadingListener(new Runnable() {
18             @Override
19             public void run() {
20                 mMapView.setViewpointGeometryAsync(rasterLayer.getFullExtent(), LayerUtil
21                         .FullExtendPadding);
22                 mMapView.setViewpointScaleAsync(MyConfig.initialScale);
23             }
24         });
25         mMapView.setViewpointScaleAsync(MyConfig.initialScale);
26 
27         return rasterLayer;
28     } 

3.2.3 全圖

將所有圖層中所有要素範圍作為地圖的顯示範圍。

1  Envelope envelope = LayerUtil.GetFullExtend(mMapView);
2  if (envelope != null) {
3      mMapView.setViewpointGeometryAsync(envelope, LayerUtil.FullExtendPadding);
4  }

3.2.4 屬性識別

識別最上層的點、線、面要素。

 

 1 @Override
 2     public boolean onSingleTapConfirmed(MotionEvent e) {
 3         android.graphics.Point screenPoint = new android.graphics.Point((int) e.getX(), (int) e.getY());
 4         final ListenableFuture<List<IdentifyLayerResult>> identifyFuture = mMapView
 5                 .identifyLayersAsync(
 6                         screenPoint, 20, false, 25);
 7         identifyFuture.addDoneListener(new Runnable() {
 8             @Override
 9             public void run() {
10                 try {
11                     List<IdentifyLayerResult> identifyLayersResults = identifyFuture.get();
12                     for (IdentifyLayerResult identifyLayerResult : identifyLayersResults) {
13                         if (identifyLayerResult.getElements().size() > 0) {
14                             GeoElement topmostElement = identifyLayerResult.getElements().get(0);
15                             if (topmostElement instanceof Feature) {
16                                 Feature identifiedFeature = (Feature) topmostElement;
17                                 LayerContent layerContent = identifyLayerResult.getLayerContent();
18                                 String layerName = "";
19                                 if (layerContent != null)
20                                     layerName = layerContent.getName();
21                                 Map<String, Object> attrs = identifiedFeature.getAttributes();
22                                 String[] itemArr = new String[items.size()];
23                                 itemArr = items.toArray(itemArr);
24                                 showIdentifyInfo(itemArr, layerName);
25                                 break;
26                             }
27                         }
28                     }
29                 } catch (InterruptedException | ExecutionException ex) {
30                 }
31             }
32         });
33 
34         return true;
35     }

3.2.5 圖層管理

包括圖層順序(置頂、置底、上移、下移)、圖層標註(能標註該圖層中多個欄位)、圖層樣式(能改變圖層中要素的顏色、寬度等信息)、圖層移除、圖層縮放到(縮放到選擇圖層的所有要素的範圍)等功能;

 

 1 private void loadLayers(boolean isToast,List<String> listChecked) {
 2         if (mapView == null) {
 3             return;
 4         }
 5         linearLayoutContent.removeAllViews();
 6         LayerList layers = mapView.getMap().getOperationalLayers();
 7         boolean layersLoaded = initialLayers(layers, 2,listChecked);
 8         if(layersLoaded)
 9         {
10             linearLayoutContent.addView(ViewUtil.AddDividerView(this));
11         }
12         Basemap basemap = mapView.getMap().getBasemap();
13         LayerList baseLayers = basemap.getBaseLayers();
14         boolean baseLayersLoaded = initialLayers(baseLayers, 1,listChecked);
15     }
16 
17     /**
18      * @param layers
19      * @param layerType //1:底圖  2:操作類
20      * @return
21      */
22     private boolean initialLayers(LayerList layers, int layerType,List<String> listChecked) {
23         if (layers == null || layers.size() == 0) {
24             return false;
25         }
26         for (int j = layers.size() - 1; j > -1; j--) {
27             Layer layer = layers.get(j);
28             boolean isChecked=false;
29             if(listChecked!=null) {
30                 isChecked= listChecked.contains(layer.getName());
31             }
32             addItem(layer, layerType,isChecked);
33         }
34         return true;
35     }

 

 1 private void initialLineSymbol(SimpleLineSymbol lineSymbol)
 2     {
 3         rowFillColor.setVisibility(View.INVISIBLE);
 4         rowIsFill.setVisibility(View.INVISIBLE);
 5         txtSymbolColor.setText("線顏色:");
 6         txtSymbolSize.setText("線寬度:");
 7         txtType.setText("線樣式:");
 8 
 9         btnSymbolColor.setBackgroundColor(lineSymbol.getColor());
10         seekBarSymbolSize.seekBar.setProgress((int)lineSymbol.getWidth());
11         initialColorPick(lineSymbol.getColor(),btnSymbolColor);
12     }
13 
14 private SimpleLineSymbol setLineSymbol(SimpleLineSymbol lineSymbol)
15     {
16         lineSymbol.setColor(ViewUtil.GetButtonBackgoundColor(btnSymbolColor));
17         lineSymbol.setWidth(seekBarSymbolSize.seekBar.getProgress());
18         return lineSymbol;
19     }

 

 1 private void initialListView()
 2     {
 3             FeatureLayer featureLayer=(FeatureLayer)layer;
 4             List<Field> fieldList=  featureLayer.getFeatureTable().getFields();
 5             List<LabelDefinition> labelDefinitionList=  featureLayer.getLabelDefinitions();
 6             boolean isLabel=featureLayer.isLabelsEnabled();
 7            for (Field field :fieldList)
 8            {
 9                CheckBox checkBox=new CheckBox(this);
10                String fileName=field.getAlias();
11                if(TextUtils.isEmpty(fileName))
12                {
13                    fileName=field.getName();
14                }
15                checkBox.setText(fileName);
16                checkBox.setTag(field);
17                if(isLabel)
18                {
19                    for (LabelDefinition labelDefinition:labelDefinitionList)
20                    {
21                      String jsonString =labelDefinition.toJson();
22                        try {
23                            JSONObject jObject = new JSONObject(jsonString);
24                            if(jObject!=null)
25                            {
26                            JSONObject jObjectItem=    jObject.getJSONObject("labelExpressionInfo");
27                                if(jObjectItem!=null)
28                                {
29                                    String expression=jObjectItem.getString("expression");
30                                    String[] expressionContent=expression.split("\\.");
31                                    if(expressionContent.length>1)
32                                    {
33                                     String[] expressionField=   expressionContent[1].split(";");
34                                     if(expressionField.length>0)
35                                     {
36                                        if( expressionField[0].equals(field.getName()))
37                                        {
38                                            checkBox.setChecked(true);
39                                        }
40                                     }
41                                    }
42                                }
43                            }
44                        } catch (JSONException e) {
45 
46                        }
47                    }
48                }
49 
50                listViewLabel.addView(checkBox);
51            }
52     }
53 
54     public void btnLabelOk_Click(View view)
55     {
56             FeatureLayer featureLayer = (FeatureLayer) layer;
57             List<Field> checkedFieldList = getCheckedFields();
58             featureLayer.getLabelDefinitions().clear();
59             if(checkedFieldList!=null&&checkedFieldList.size()>0) {
60                 for (Field field : checkedFieldList) {
61                     LabelDefinition labelDefinition = LayerUtil.CreateFillLabelDefinition(field.getName());
62                     featureLayer.getLabelDefinitions().add(labelDefinition);
63                 }
64                 featureLayer.setLabelsEnabled(true);
65             }
66             else
67             {
68                 featureLayer.setLabelsEnabled(false);
69             }
70             finish();
71     }

3.2.6 距離測量

通過手在屏幕中點擊開始,雙擊停止,支持動態顯示每段線的距離(以米為單位)。

 

 1 public boolean onDoubleTap(MotionEvent point) {
 2 
 3 if (geoType == GeometryType.POLYLINE)//繪製線
 4         {
 5             if (!lineGeometry.isSketchValid()) {
 6                 removeGraphic(pCurrGraphic);
 7             } else {
 8                 updateGraphic(lineGeometry.toGeometry());
 9             }
10             PartCollection partCollection = lineGeometry.getParts();
11             if (partCollection.size() == 0) {
12                 return false;
13             }
14             Part part = partCollection.get(partCollection.size() - 1);
15             int count = part.getPointCount();
16             if (count <= 2) {
17                 return false;
18             }
19             double length = GeometryEngine.lengthGeodetic(lineGeometry.toGeometry(), new
20                     LinearUnit(LinearUnitId.METERS), GeodeticCurveType.GEODESIC);
21             Graphic lengthGriphic = new Graphic(ptCurrent, getTextSymbol(getFormatString(length,
22                     2, "米"), TextSymbol.HorizontalAlignment.RIGHT, TextSymbol.VerticalAlignment
23                     .TOP));
24             drawLayer.getGraphics().add(lengthGriphic);
25 
26    }
27 
28  } 

3.2.7 面積測量

通過手在屏幕中點擊開始,雙擊停止,會形成一個面要素,並顯示長度和麵積(以米為單位)。

 

 1 public boolean onDoubleTap(MotionEvent point) {
 2 
 3 if (!polygonGeometry.isSketchValid()) {
 4     removeGraphic(pCurrGraphic);
 5     return true;
 6 } else {
 7     updateGraphic(polygonGeometry.toGeometry());
 8 }
 9 
10 double area = GeometryEngine.areaGeodetic(polygonGeometry.toGeometry(), new AreaUnit
11         (AreaUnitId.SQUARE_METERS), GeodeticCurveType.GEODESIC);
12 Graphic areaGriphic = new Graphic(ptCurrent, getTextSymbol(getFormatString(area, 2,
13         "平方米"), TextSymbol.HorizontalAlignment.LEFT, TextSymbol.VerticalAlignment
14         .BOTTOM));
15 drawLayer.getGraphics().add(areaGriphic);
16 
17 double length = GeometryEngine.lengthGeodetic(polygonGeometry.toPolyline(), new
18         LinearUnit(LinearUnitId.METERS), GeodeticCurveType.GEODESIC);
19 Point ptShift = mapView.screenToLocation(new android.graphics.Point(Math.round(point
20         .getX()), Math.round(point.getY()) + 30));
21 Graphic lengthGriphic = new Graphic(ptShift, getTextSymbol(getFormatString(length,
22         2, "米"), TextSymbol.HorizontalAlignment.RIGHT, TextSymbol.VerticalAlignment
23         .TOP));
24 drawLayer.getGraphics().add(lengthGriphic);
25 
26  }

3.2.8 清除覆蓋物

清除上面距離測量或者面積測量的圖形要素。

1 if (mearsureGraphicsOveray != null) {
2     mearsureGraphicsOveray.getGraphics().clear();
3 }

3.2.9 當前位置

點擊此按鈕,將GPS最近一次接受點的位置置於地圖中心位置,並增加圖標。

 1 public boolean startGPSCurrent(boolean isRequestUpdate) {
 2     if (GPSLocationManager.gpsLocationManager == null) {
 3         GPSLocationManager.gpsLocationManager = GPSLocationManager.getInstances
 4                 (MainActivity
 5                         .this);
 6     }
 7     if (currentLocationListener == null) {
 8         currentLocationListener = new MyGPSCurrentLocationListener();
 9     }
10     if (isRequestUpdate)
11         GPSLocationManager.gpsLocationManager.stop(2);
12     //開啟定位
13     GPSLocationManager.gpsLocationManager.start(currentLocationListener,
14             isRequestUpdate, 100, 2);
15 
16     return true;
17 }
18 
19  
20 
21 class MyGPSCurrentLocationListener implements GPSLocationListener {
22     @Override
23     public void UpdateLocation(Location location) {
24         if (location != null) {
25             LocationUtil.AddOrUpdateLocation(MainActivity.this, location,
26                     locationGraphicsOveray,
27                     spatialReference, mMapView);
28             if (GPSLocationManager.gpsLocationManager != null) {
29       

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Hadoop安裝方式 Hadoop的安裝方式有三種,分別是單機模式,偽分散式模式,偽分散式模式,分散式模式。 單機模式:Hadoop預設模式為非分散式模式(本地模式),無需進行其他配置即可運行。非分散式即單Java進程,方便進行調試。 偽分散式模式:Hadoop可以在單節點上以偽分散式的方式運行,H ...
  • Linux的選擇 在Linux系統各個發行版中,CentOS系統和Ubuntu系統在服務端和桌面端使用占比最高,網路上資料最是齊全,所以建議使用CentOS系統或Ubuntu。 一般來說,如果要做伺服器,選擇CentOS或者Ubuntu Server;如果做桌面系統,選擇Ubuntu Desktop ...
  • adb 命令可以幫我們快速的管理連接的手機設備,例如執行一些安裝apk,卸載apk命令,對於熟悉linux系統的人,可以方便的管理手機目錄操作手機文件,還可以通過adb命令查看手機的系統日誌等操作。 接下來講一講如何在windows系統下配置ADB環境變數: “電腦”右擊屬性進入系統設計界面,如下 ...
  • 典型情況下的生命周期 onCreate 表示創建Acticity,在這個方法中可以做一些初始化的操作,如載入界面佈局資源,初始化Activity所需的數據 onRestart 表示重新啟動Activity,正常情況下,當前Activity從不見到可見,就會調用此方法。 onStart 表示啟動Act ...
  • 當執行一個確定的工作的時候,一個任務是和用戶交互的activity的集合。這些activity被排列在棧中(返回棧),每一個activity是被打開的。例如,一個email app有一個activity去顯示消息列表,當點擊一個新的消息時打開一個新的activity,新的activity被加入到返回 ...
  • Error Domain=com.alamofire.error.serialization.response Code=-1016 "Request failed: unacceptable content-type: text/html" 解決方案: 在AFNetWorking的源文件AFURL ...
  • 版權聲明:未經博主允許不得轉載 補充 補充上一節,使用 是用來顯示列表項的,使用 需要兩個xml文件,一個是列表佈局,一個是單個列表項的佈局。如我們要在要顯示系統所有app列表項時,需要左邊app 視圖和右邊文本視圖。 一個是列表佈局 all_app_list.xml 單個列表項的佈局 list_i ...
  • 前言 大家好,給大家帶來 的概述,希望你們喜歡 學習目標 掌握兩個插件的安裝和使用,能夠實現代碼生成功能。 Android Code Generator是一款代碼生成的插件,幫助提高app的開發速度,只要打好佈局XML文件,就能幫你把Activity/Fragment/Adapter文件生成好。 而 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...