Skip to content
View on GitHubSample viewer app

Add feature layers from various data sources.

Add feature layers

Use case

Feature layers, like all layers, are visual representations of data and are used on a map or scene. In the case of feature layers, the underlying data is held in a feature table or feature service.

Feature services are useful for sharing vector GIS data with clients so that individual features can be queried, displayed, and edited. There are various online and offline methods to load feature services.

How to use the sample

Tap the button on the bottom menu to add feature layers, from different sources, to the map. Pan and zoom the map to view the feature layers.

How it works

  1. Set the basemap with a BasemapStyle.
  2. Load a feature layer with a URL.
    i. Create a ServiceFeatureTable from a URL.
    ii. Create a FeatureLayer with the feature table.
  3. Load a feature layer with a portal item.
    i. Create a PortalItem with the portal and item ID.
    ii. Create a FeatureLayer with the portal item and with or without the layer ID.
  4. Load a feature layer with a geodatabase.
    i. Instantiate and load a Geodatabase using the file name.
    ii. Get the feature table from the geodatabase with the feature table's name.
    iii. Create a FeatureLayer from the feature table.
  5. Load a feature layer with a geopackage.
    i. Instantiate and load a geopackage using its file name.
    ii. Get the first GeoPackageFeatureTable from the GeoPackage.geoPackageFeatureTables array.
    iii. Create a FeatureLayer from the feature table.
  6. Load a feature layer with a shapefile.
    i. Create a ShapefileFeatureTable using the shapefile path.
    ii. Create a FeatureLayer from the feature table and load it.
  7. Add the feature layer to the map's OperationalLayers.

Relevant API

  • FeatureLayer
  • Geodatabase
  • GeoPackageFeatureTable
  • PortalItem
  • ServiceFeatureTable
  • ShapefileFeatureTable

About the data

This sample uses the Naperville damage assessment service, Trees of Portland portal item, Los Angeles Trailheads geodatabase, Aurora, Colorado GeoPackage, and Scottish Wildlife Trust Reserves Shapefile.

The Scottish Wildlife Trust shapefile data is provided from Scottish Wildlife Trust under CC-BY licence. Data Copyright Scottish Wildlife Trust (2022).

Tags

feature, geodatabase, geopackage, layers, service, shapefile, table

Sample Code

MainActivity.ktMainActivity.ktDownloadActivity.kt
Use dark colors for code blocksCopy
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 /* Copyright 2022 Esri  *  * Licensed under the Apache License, Version 2.0 (the "License");  * you may not use this file except in compliance with the License.  * You may obtain a copy of the License at  *  * http://www.apache.org/licenses/LICENSE-2.0  *  * Unless required by applicable law or agreed to in writing, software  * distributed under the License is distributed on an "AS IS" BASIS,  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  * See the License for the specific language governing permissions and  * limitations under the License.  *  */  package com.esri.arcgismaps.sample.addfeaturelayers  import android.os.Bundle import android.util.Log import android.widget.ArrayAdapter import android.widget.Toast import com.esri.arcgismaps.sample.sampleslib.EdgeToEdgeCompatActivity import androidx.databinding.DataBindingUtil import androidx.lifecycle.lifecycleScope import com.arcgismaps.ApiKey import com.arcgismaps.ArcGISEnvironment import com.arcgismaps.data.GeoPackage import com.arcgismaps.data.Geodatabase import com.arcgismaps.data.ServiceFeatureTable import com.arcgismaps.data.ShapefileFeatureTable import com.arcgismaps.mapping.ArcGISMap import com.arcgismaps.mapping.BasemapStyle import com.arcgismaps.mapping.PortalItem import com.arcgismaps.mapping.Viewpoint import com.arcgismaps.mapping.layers.FeatureLayer import com.arcgismaps.portal.Portal import com.esri.arcgismaps.sample.addfeaturelayers.databinding.AddFeatureLayersActivityMainBinding import kotlinx.coroutines.launch import java.io.File  class MainActivity : EdgeToEdgeCompatActivity() {   // set up data binding for the activity  private val activityMainBinding: AddFeatureLayersActivityMainBinding by lazy {  DataBindingUtil.setContentView(this, R.layout.add_feature_layers_activity_main)  }   private val mapView by lazy {  activityMainBinding.mapView  }   private val provisionPath: String by lazy {  getExternalFilesDir(null)?.path.toString() + File.separator + getString(R.string.add_feature_layers_app_name)  }   // enum to keep track of the selected source to display the feature layer  enum class FeatureLayerSource(val menuPosition: Int) {  SERVICE_FEATURE_TABLE(0),  PORTAL_ITEM(1),  GEODATABASE(2),  GEOPACKAGE(3),  SHAPEFILE(4)  }   // keeps track of the previously selected feature layer source  private var previousSource: FeatureLayerSource? = null   override fun onCreate(savedInstanceState: Bundle?) {  super.onCreate(savedInstanceState)   // authentication with an API key or named user is  // required to access basemaps and other location services  ArcGISEnvironment.apiKey = ApiKey.create(BuildConfig.ACCESS_TOKEN)  lifecycle.addObserver(mapView)  // set the map to be displayed in as the BasemapStyle topographic  activityMainBinding.mapView.map = ArcGISMap(BasemapStyle.ArcGISTopographic)  setUpBottomUI()  }   /**  * Sets the map using the [layer] at the given [viewpoint]  */  private fun setFeatureLayer(layer: FeatureLayer, viewpoint: Viewpoint) {  activityMainBinding.mapView.apply {  // clears the existing layer on the map  map?.operationalLayers?.clear()  // adds the new layer to the map  map?.operationalLayers?.add(layer)  // updates the viewpoint to the given viewpoint  setViewpoint(viewpoint)  }  }   /**  * Load a feature layer with a URL  */  private fun loadFeatureServiceURL() {  // initialize the service feature table using a URL  val serviceFeatureTable =  ServiceFeatureTable(resources.getString(R.string.add_feature_layers_sample_service_url))  // create a feature layer with the feature table  val featureLayer = FeatureLayer.createWithFeatureTable(serviceFeatureTable)  val viewpoint = Viewpoint(41.70, -88.20, 120000.0)  // set the feature layer on the map  setFeatureLayer(featureLayer, viewpoint)  }    /**  * Load a feature layer with a portal item  */  private suspend fun loadPortalItem() {  // set the portal  val portal = Portal("https://www.arcgis.com")  // create the portal item with the item ID for the Portland tree service data  val portalItem = PortalItem(portal, "1759fd3e8a324358a0c58d9a687a8578")  portalItem.load().onSuccess {  // create the feature layer with the item  val featureLayer = FeatureLayer.createWithItem(portalItem)  // set the viewpoint to Portland, Oregon  val viewpoint = Viewpoint(45.5266, -122.6219, 2500.0)  // set the feature layer on the map  setFeatureLayer(featureLayer, viewpoint)  }.onFailure {  showError("Error loading portal item: ${it.message}")  }  }   /**  * Load a feature layer with a local geodatabase file  */  private suspend fun loadGeodatabase() {  // locate the .geodatabase file in the device  val geodatabaseFile = File(provisionPath, getString(R.string.geodatabase_la_trails))  // instantiate the geodatabase with the file path  val geodatabase = Geodatabase(geodatabaseFile.path)  // load the geodatabase  geodatabase.load().onSuccess {  // get the feature table with the name  val geodatabaseFeatureTable =  geodatabase.getFeatureTable("Trailheads")  if (geodatabaseFeatureTable == null) {  showError("Feature table name not found in geodatabase")  return  }  // create a feature layer with the feature table  val featureLayer = FeatureLayer.createWithFeatureTable(geodatabaseFeatureTable)  // set the viewpoint to Malibu, California  val viewpoint = Viewpoint(34.0772, -118.7989, 600000.0)  // set the feature layer on the map  setFeatureLayer(featureLayer, viewpoint)  }.onFailure {  showError("Error loading geodatabase: ${it.message}")  }  }   /**  * Load a feature layer with a local geopackage file  */  private suspend fun loadGeopackage() {  // locate the .gpkg file in the device  val geopackageFile = File(provisionPath, "/AuroraCO.gpkg")  // instantiate the geopackage with the file path  val geoPackage = GeoPackage(geopackageFile.path)  // load the geopackage  geoPackage.load().onSuccess {  // get the first feature table in the geopackage  val geoPackageFeatureTable = geoPackage.geoPackageFeatureTables.first()  // create a feature layer with the feature table  val featureLayer = FeatureLayer.createWithFeatureTable(geoPackageFeatureTable)  // set the viewpoint to Denver, CO  val viewpoint = Viewpoint(39.7294, -104.8319, 500000.0)  // set the feature layer on the map  setFeatureLayer(featureLayer, viewpoint)  }.onFailure {  showError("Error loading geopackage: ${it.message}")  }  }   /**  * Load a feature layer with a local shapefile file  */  private suspend fun loadShapefile() {  // locate the shape file in device  val file = File(  provisionPath,  "/ScottishWildlifeTrust_ReserveBoundaries_20201102.shp"  )  // create a shapefile feature table from a named bundle resource  val shapeFileTable = ShapefileFeatureTable(file.path)  shapeFileTable.load().onSuccess {  // create a feature layer for the shapefile feature table  val featureLayer = FeatureLayer.createWithFeatureTable(shapeFileTable)  // set the viewpoint to Scotland  val viewpoint = Viewpoint(56.641344, -3.889066, 6000000.0)  // set the feature layer on the map  setFeatureLayer(featureLayer, viewpoint)  }.onFailure {  showError("Error loading shapefile: ${it.message}")  }  }   private fun showError(message: String) {  Toast.makeText(this@MainActivity, message, Toast.LENGTH_SHORT).show()  Log.e(localClassName, message)  }   /**  * Sets up the bottom UI selector to switch between  * different ways to load a feature layers  */  private fun setUpBottomUI() {  // create an adapter with the types of feature layer  // sources to be displayed in menu  val adapter = ArrayAdapter(  this,  android.R.layout.simple_list_item_1,  resources.getStringArray(R.array.feature_layer_sources)  )  activityMainBinding.bottomListItems.apply {  // populate the bottom list with the feature layer sources  setAdapter(adapter)  // click listener when feature layer source is selected  setOnItemClickListener { _, _, i, _ ->  // get the selected feature layer source  val selectedSource = FeatureLayerSource.entries.find { it.menuPosition == i }  // check if the same feature is selected  if (previousSource != null && (previousSource == selectedSource)) {  // same feature layer selected, return  return@setOnItemClickListener  }  lifecycleScope.launch {  // set the feature layer source using the selected source  when (selectedSource) {  FeatureLayerSource.SERVICE_FEATURE_TABLE -> loadFeatureServiceURL()  FeatureLayerSource.PORTAL_ITEM -> loadPortalItem()  FeatureLayerSource.GEODATABASE -> loadGeodatabase()  FeatureLayerSource.GEOPACKAGE -> loadGeopackage()  FeatureLayerSource.SHAPEFILE -> loadShapefile()  else -> {}  }  }  // update the previous feature layer source  previousSource = selectedSource  }  }  } }

Your browser is no longer supported. Please upgrade your browser for the best experience. See our browser deprecation post for more details.