1. 程式人生 > >ArcGIS Runtime SDK for Android 入門(9):通過PictureMarkerSymbol建立點符號

ArcGIS Runtime SDK for Android 入門(9):通過PictureMarkerSymbol建立點符號

    本文主要簡單講解如何通過本地或線上資源的方式使用SimpleMarkerSymbol建立簡單的圖片點符號。

實現步驟:

1.建立Android專案   

2.新增Runtime SDK依賴

3.新增許可權及OpenGL ES支援

在AndroidManifest.xml中新增:

    <!--聯網許可權-->
    <uses-permission android:name="android.permission.INTERNET" />
    <!--寫入外部儲存許可權-->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <!--OpenGL ES支援 -->
    <uses-feature
        android:glEsVersion="0x00020000"
        android:required="true" />

4.資源準備:

(1)在res-->values-->strings.xml中新增:

<resources>
    <!--新增的內容-->
    <string name="pin_blank_orange_folder_name">ArcGISTemp</string>
    <string name="pin_blank_orange_file_name">pin_blank_orange.png</string>
</resources>

(2)在res-->drawable中新增兩個符號圖片:

       

5.設定介面佈局

在layout中的佈局XML中新增:

    <!-- MapView控制元件 -->
    <com.esri.arcgisruntime.mapping.view.MapView
        android:id="@+id/mapView"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    </com.esri.arcgisruntime.mapping.view.MapView>

6.編寫程式碼

在Activity中:

(1)變數準備:

  //MapView控制元件變數
  MapView mMapView;
  //GraphicsOverlay變數
  GraphicsOverlay mGraphicsOverlay;
  //檔案地址
  String mArcGISTempFolderPath;
  String mPinBlankOrangeFilePath;
  //用於設定“讀取檔案”許可權的變數
  private final static int MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE = 101;
  //用來提示的標籤  
  private static final String TAG = "PictureMarkerSymbols";

(2)onCreate方法:

   //從layout中獲取MapView控制元件
    mMapView = (MapView) findViewById(R.id.mapView);
    // 以影像為地圖建立地圖變數
    ArcGISMap map = new ArcGISMap(Basemap.createTopographic());
    // 設定地圖在MapView控制元件中被顯示
    mMapView.setMap(map);

    //通過一個外接矩形(藉助左下和右上兩個點形成)建立一個初始化視點
    Envelope envelope = new Envelope(new Point(-228835, 6550763, SpatialReferences.getWebMercator()),
        new Point(-223560, 6552021, SpatialReferences.getWebMercator()));
    //在MapView中設定視點
    mMapView.setViewpointGeometryAsync(envelope, 100.0);

    // 建立一個新GraphicsOverlay並把它新增到MapView
    mGraphicsOverlay = new GraphicsOverlay();
    mMapView.getGraphicsOverlays().add(mGraphicsOverlay);

    //通過一個URL資料來源建立一個picture marker symbol
    //當使用URL時,你需要獲取遠端資源去裝載
    final PictureMarkerSymbol campsiteSymbol = new PictureMarkerSymbol(
        "http://sampleserver6.arcgisonline.com/arcgis/rest/services/Recreation/FeatureServer/0/images/e82f744ebb069bb35b234b3fea46deae");
    //可以設定圖片大小,如果沒有設定,圖片將自動設定為其自身預設的畫素大小
    //它的外觀會因不同解析度的裝置而異。
    campsiteSymbol.setHeight(18);
    campsiteSymbol.setWidth(18);
    campsiteSymbol.loadAsync();
    campsiteSymbol.addDoneLoadingListener(new Runnable() {
      @Override
      public void run() {
        //一旦符號被裝載,在GraphicOverlay中新增一個新的Graphic
        Point campsitePoint = new Point(-223560, 6552021, SpatialReferences.getWebMercator());
        Graphic campsiteGraphic = new Graphic(campsitePoint, campsiteSymbol);
        mGraphicsOverlay.getGraphics().add(campsiteGraphic);
      }
    });

    //通過APP資源建立picture marker symbol
    BitmapDrawable pinStarBlueDrawable = (BitmapDrawable) ContextCompat.getDrawable(this, R.drawable.pin_star_blue);
    final PictureMarkerSymbol pinStarBlueSymbol = new PictureMarkerSymbol(pinStarBlueDrawable);
    //可以設定圖片大小,如果沒有設定,圖片將自動設定為其自身預設的畫素大小
    //它的外觀會因不同解析度的裝置而異。
    pinStarBlueSymbol.setHeight(40);
    pinStarBlueSymbol.setWidth(40);
    //Optionally set the offset, to align the base of the symbol aligns with the point geometry
    //可以設定圖片的偏移,使圖片符號的基點與幾何點對齊
    pinStarBlueSymbol.setOffsetY(
        11); //符號使用的影象周圍有一個透明的緩衝區,因此偏移量不僅僅是高度的1/2
    pinStarBlueSymbol.loadAsync();
    pinStarBlueSymbol.addDoneLoadingListener(new Runnable() {
      @Override
      public void run() {
        //一旦符號被裝載,在GraphicOverlay中新增一個新的Graphic
        //通過與初始化視點相同的位置的建立一個新的Graphic
        Point pinStarBluePoint = new Point(-226773, 6550477, SpatialReferences.getWebMercator());
        Graphic pinStarBlueGraphic = new Graphic(pinStarBluePoint, pinStarBlueSymbol);
        mGraphicsOverlay.getGraphics().add(pinStarBlueGraphic);
      }
    });

    //請參閱createpicturelkersymbolfromfile()方法實現。
    //首次執行檢查讀取外儲存器許可權
    checkSaveResourceToExternalStorage();

(3)方法支援:

private void createPictureMarkerSymbolFromFile() {
    //通過本地磁碟檔案建立一個PictureMarkerSymbol
    BitmapDrawable pinBlankOrangeDrawable = (BitmapDrawable) Drawable.createFromPath(mPinBlankOrangeFilePath);
    final PictureMarkerSymbol pinBlankOrangeSymbol = new PictureMarkerSymbol(pinBlankOrangeDrawable);
    //可以設定圖片大小,如果沒有設定,圖片將自動設定為其自身預設的畫素大小
    //它的外觀會因不同解析度的裝置而異。
    pinBlankOrangeSymbol.setHeight(20);
    pinBlankOrangeSymbol.setWidth(20);
    //可以設定圖片的偏移,使圖片符號的基點與幾何點對齊
    pinBlankOrangeSymbol.setOffsetY(10); //The image used has not buffer and therefore the Y offset is height/2
    pinBlankOrangeSymbol.loadAsync();
    //[DocRef: END]
    pinBlankOrangeSymbol.addDoneLoadingListener(new Runnable() {
      @Override
      public void run() {
        //通過與初始化視點相同的位置新增一個新的Graphic
        Point pinBlankOrangePoint = new Point(-228835, 6550763, SpatialReferences.getWebMercator());
        Graphic pinBlankOrangeGraphic = new Graphic(pinBlankOrangePoint, pinBlankOrangeSymbol);
        mGraphicsOverlay.getGraphics().add(pinBlankOrangeGraphic);
      }
    });

  }
  
  private void checkSaveResourceToExternalStorage() {
    //首先,檢查是否沒有SD卡
    if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
      // 沒有安裝的磁碟,程式不能繼續執行
      return;
    }

    //檢查儲存磁碟需要的許可權(安卓6.0需要在Manifest中設定而且應該被授予)
    if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
        != PackageManager.PERMISSION_GRANTED) {
      //no permission, need to task, onRequestPermissionsResult will handle the result
      //若沒有許可權,則需要動態獲取許可權,onRequestPermissionsResult方法可以解決這個問題
      ActivityCompat.requestPermissions(this, new String[] { Manifest.permission.WRITE_EXTERNAL_STORAGE },
          MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE);
    } else {
      //許可權已經被授予則繼續執行
      //將orange marker儲存到磁碟APP資原始檔
      if (saveFileToExternalStorage()) {
        createPictureMarkerSymbolFromFile();
      }
    }
  }

  @Override
  public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) {
    switch (requestCode) {
      case MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE: {
        //如果請求被拒絕,則結果陣列為空
        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
          //許可權授予
          if (saveFileToExternalStorage()) {
            createPictureMarkerSymbolFromFile();
          }
        }
      }
    }
  }

  private boolean saveFileToExternalStorage() {
    //建立路徑
    mArcGISTempFolderPath = Environment.getExternalStorageDirectory() + File.separator + this.getResources()
        .getString(R.string.pin_blank_orange_folder_name);
    mPinBlankOrangeFilePath =
        mArcGISTempFolderPath + File.separator + this.getResources().getString(R.string.pin_blank_orange_file_name);
    //獲取drawable資源
    Bitmap bm = BitmapFactory.decodeResource(getResources(), R.drawable.pin_blank_orange);
    //建立ArcGIS臨時資料夾
    File folder = new File(mArcGISTempFolderPath);
    if(folder.mkdirs()){
      Log.d(TAG, "Temp folder created");
    }else{
      Toast.makeText(MainActivity.this, "Could not create temp folder", Toast.LENGTH_LONG).show();
    }
    //建立磁碟上的檔案
    File file = new File(mPinBlankOrangeFilePath);
    try {
      OutputStream outStream = new FileOutputStream(file);
      bm.compress(Bitmap.CompressFormat.PNG, 100, outStream);
      outStream.flush();
      outStream.close();
      return true;
    } catch (Exception e) {
      Log.e("picture-marker-symbol", "Failed to write image to external directory: message = " + e.getMessage());
      return false;
    }
  }

  @Override
  public void onDestroy() {
    super.onDestroy();
    //清空我們儲存在磁碟上的檔案和資料夾
    try {
      File file = new File(mPinBlankOrangeFilePath);

      if(file.delete()){
        Log.d(TAG, "Temp folder created");
      }else{
        Toast.makeText(MainActivity.this, "Could not create temp folder", Toast.LENGTH_LONG).show();
      }

      File tempFolder = new File(mArcGISTempFolderPath);

      if(tempFolder.delete()){
        Log.d(TAG, "Temp folder created");
      }else{
        Toast.makeText(MainActivity.this, "Could not create temp folder", Toast.LENGTH_LONG).show();
      }

    } catch (Exception e) {
      Log.e("picture-marker-symbol",
          "Failed to delete temp files and directory written to external storage: message = " + e.getMessage());
    }
  }

6.執行APP:可以對建立的符號進行瀏覽

感謝luq老師的指導