Skip To Content

Edit an ArcGISFeatureLayer

In this topic

Using the ArcGIS API for Android, you can edit feature services using methods on the ArcGISFeatureLayer class. This topic includes a summary of the editing workflow to add new features, edit existing geometries, or edit attributes of existing features, along with more detailed information and code snippets to assist you in the creation of editing tools.

At version 10.2.3 of the SDK, an alternative editing model for online and offline data was introduced; for more information on this editing model, see the topic Edit features. For an overview of your editing options, see the Editing topic. The remainder of this topic focuses on editing an ArcGISFeatureLayer.

Create new features

Creating features involves adding new geometries with attributes to a feature layer, using three general steps:

  1. Choose the layer to which a new feature will be added.
  2. Provide tools for the user to create the geometry of the new feature. You may additionally wish to allow the user to set attributes of the new feature.
  3. Apply the edits to the server.

The tool you provide a tool with which the user can create features must use the correct geometry type for the chosen layer. If this tool is interactive, it needs to be connected to touch events on the MapView object. The following code example shows how to set the OnSingleTapListener of a MapView, use parameters of this method to create a Point geometry, and then create a new Graphic from this Point and a set of attribute values in the form of a HashMap.

mMapView = (MapView)findViewById(R.id.map); // Get the MapView from the layout
mMapView.setOnSingleTapListener(new OnSingleTapListener() { // Set a single tap listener
 
  @Override
  public void onSingleTap(float x, float y) {
    // Obtain the clicked point from a single tap on the map
    Point mapPt = map.toMapPoint(x, x);

    // Create a map of attributes (keys must match fields in the feature layer)
    Map<String,Object> attributes = new HashMap<String,Object>();
    attributes.put("Type", "Park");
    attributes.put("Description", "Editing...");

    // Create a Graphic from the point and attributes, and set a symbol.
    Graphic newFeatureGraphic = new Graphic(mapPt, new SimpleMarkerSymbol(Color.RED, 10, STYLE.CIRCLE), attributes, 0);

    // Add the graphic to an array ready to pass to applyEdits.
    Graphic[] adds = {newFeatureGraphic};

Alternatively you may want to use the device GPS location for creating or tracing geometries, in which case, integrate the LocationDisplayManager class into your code.

You may wish to allow the user to set attributes of the new feature immediately, or alternatively allow the attribute edits as a second stage.

See the following sections for information on using feature templates and providing map tools. See the section Applying edits on the server for more information.

Use feature templates

If your feature layer has subtypes, templates, or domains defined, it may be useful to display these choices to the user in an Android spinner, dialog box, or view. The default renderer and attributes from a subtype or template can be used for the feature being added, saving the user from having to add this information. The ArcGISFeatureLayer class has some utility methods to help achieve this; see the createFeatureWithType and createFeatureWithTemplate methods.

For example, the following code shows how you can get templates from an ArcGISFeatureLayer, and pass a template to the createFeatureWithTemplate method to create a new feature.

// Get FeatureTemplates from the ArcGISFeatureLayer to be edited.
if ( (featureLayer.getTemplates() != null) && (featureLayer.getTemplates().length > 0))
{
  // Get the template required from the layer - using first template here as example.
  FeatureTemplate template = featureLayer.getTemplates()[0];
  // Create a new Graphic using the FeatureTemplate
  Graphic newFeatureGraphic = featureLayer.createFeatureWithTemplate(template, mapPt);
  // Continue by setting attribute values and then adding to array ready to pass to applyEdits.

The Geometry Editor sample demonstrates creating template-based features using an ArcGISFeatureLayer, and applying those edits to the service.

Adding map touch events

To capture the location for new features and/or their vertices as the user touches the map, add a listener on the MapView object. For points, this can be a simple OnSingleTapListener as shown previously. For polygons or lines, this can be MapOnTouchListener (for freehand style drawing) or a more complex OnSingleTapListener that has logic to record when a feature edit has started and finished (perhaps via a long click or double tap). The new feature can be drawn into a GraphicsLayer first, so the user can see the feature as it's being edited.

The Geometry Editor sample also demonstrates creating new polygon and polyline elements, and using a graphics layer to draw the features during creation.

Edit attributes

Editing attributes of existing features can also involve three general steps:

  1. Select the feature to be edited and display the current attribute values to the user.
  2. Provide a way for the user to change the editable attribute values of the feature.
  3. Apply the edits to the server.

When writing an application to edit a feature's attributes, you need to know some information about the feature layer being edited. This includes information on the available editable fields, the type of data that each field contains, and whether a field represents a subtype or domain, and what the possible subtypes or domain values can be. The ArcGISFeatureLayer class provides all this for you and ensures data integrity. See the following section Applying edits on the server for more information.

Inspect layer fields

The layers field information is the key to editing attributes and is available from the feature layer getFields method, which returns an array of field objects. A field object tells you whether the field is editable as well as the field type (so you know what data the user can enter). The following code examples show how to inspect the layer fields:

This code snippet determines editable fields that a user can add data to with a keyboard (strings, numbers, and dates) by eliminating all the other field types:

public boolean isFieldValidForEditing(Field field) {
  
  int fieldType = field.getFieldType();

  if (field.isEditable() && fieldType != Field.esriFieldTypeOID && fieldType != Field.esriFieldTypeGeometry
        && fieldType != Field.esriFieldTypeBlob && fieldType != Field.esriFieldTypeRaster
        && fieldType != Field.esriFieldTypeGUID && fieldType != Field.esriFieldTypeXML) {

    return true;
			
  } else {

    return false;
  }
}

The following method determines the type of field (text, date, number, or decimal) and allows you to add logic to handle each field type:

public void determineFieldType(Field field) {

      if (field.getFieldType()== Field.esriFieldTypeString) {
        return FieldType.STRING;
      } else if (field.getFieldType() == Field.esriFieldTypeSmallInteger
          || field.getFieldType() == Field.esriFieldTypeInteger) {
        return FieldType.NUMBER;
      } else if (field.getFieldType() == Field.esriFieldTypeSingle
          || field.getFieldType()== Field.esriFieldTypeDouble) {
        return FieldType.DECIMAL;
      } else if (field.getFieldType() == Field.esriFieldTypeDate) {
        return FieldType.DATE;
      }
      return null;
}

Present editable fields to user

Once you know what type of data can be edited, you can present it to the user in the appropriate format. The ArcGIS API for Android includes various view elements for you to do this. The EditTextobject is probably the most used view element to allow user input and is very flexible. Its size and field length can be set, along with the type of data input, so that the appropriate soft keyboard is shown.

The following EditText Android layout XML shows how to set up a field for entering decimal numbers only (see the android:inputType attribute):

<EditText
    android:id="@+id/field_value_txt"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:minWidth="100dp"
    android:maxWidth="150dp"
    android:padding="10dp"
    android:textSize="16sp"
    android:layout_alignParentLeft="true"
    android:layout_marginLeft="150dp"
    android:inputType="numberSigned|numberDecimal">
  </EditText>

For domains and subtypes, the Spinner object can be used. This represents a drop-down list and can be populated using an adapter. See the Attribute Editor sample sample uses this method to create a pop-up dialog box.

Ensure data integrity

Before you commit the data, it is good practice to convert the data into the correct format, as often in the ArcGIS API for Android, values that users have entered (from an EditText or Spinner view) are returned as a string. The previous code snippet for determining the field type can be used so that relevant parsing of string values into the required data type (integers, dates, doubles, and so on) can be performed.

Edit geometries

The three basic steps required to enable your app to edit existing features are as follows:

  1. Select the feature to be edited and display or highlight the current geometry to the user.
  2. Provide tools for the user to edit the geometry, for example, drag vertices or perform geometry operations such as split, merge, or cut.
  3. Apply the edits to the server.

More information about selecting features and editing geometries follows. See the following section Applying edits on the server for more information on apply edits to the server.

Select features

The feature layer includes a special selection mode to make feature selections easy. When you instantiate the feature layer, you can set this using the ArcGISFeatureLayer.MODE class and pass it to the constructor or the ArcGISFeatureLayer.OPTIONS class. In this mode, features are only retrieved from the server when they are selected. As a backdrop to this layer, you can provide an additional dynamic map service layer to show all available features; this is recommended for various performance reasons.

To select features either by attribute or by spatial location, create a Query object, then call the selectFeatures method on the feature layer and pass in the Query and a callback in order to process the query result. The Select Features sample demonstrates using both a spatial and an attribute query to select features.

Provide editing tools

To provide editing tools, you need to connect various touch listeners on the MapView object to respond to user events. This can include clicking a vertex on a polygon so it can be moved. The GeometryEngine class, which provides local geometric operations on the device (rather than a geometry service running on an instance of ArcGIS for Server), provides various methods to help you perform geometry edits. For selecting a vertex, GeometryEnginehas a getNearestVertex(method, which takes a point and a geometry (the selected feature in this case) and returns the vertex in the geometry closest to the point. You can then show this vertex on the screen and provide additional touch listeners so the user can move it.

GeometryEngine also provides a large array of geometric operations such as clips, buffers, and unions. These can be used in conjunction with new graphic features on the map to edit existing selected features, such as clipping an existing polygon using a newly drawn polygon.

See the Geometry Editor sample for an example of how editing tools can be provided to allow a user to create and change point, line, and polygon geometries.

Deleting features

A typical workflow for feature deletions is to first allow the user to identify the features to be deleted, and then to provide a confirmation step (such as a dialog), before the deletion is applied to the server.

To identify the feature(s) to be deleted, you may wish to let the user interact with the map, and identify the feature by tapping on it. Alternatively, you may wish to provide a way to choose a feature by it's attribute values. Use the techniques described in the previous sections about editing existing geometries.

Applying edits on the server

Once feature edits have been captured, they can be passed to the ArcGISFeatureLayer.applyEdits method. This asynchronous method categorizes edits into three types- adding, deleting, and updating. In all cases, features are added or updated as Graphic objects, which may include geometry, attributes, and a renderer or symbol.

  • New features to be created are passed in as graphics in the first argument. New features will be given a new ObjectID on the server, so this attribute is not required for to exist on the graphic objects passed in.
  • Existing features to be deleted are passed in as graphics in the second argument. The graphic objects passed in do not have to include all attributes, however, the ObjectID attribute must always exist on the graphic passed in for the deletion to succeed.
  • Existing features to be updated (either geometry or attribute updates) are passed in as graphics in the third argument. The graphic objects passed in must always include the ObjectID attribute for the edit to succeed. However, the graphic objects do not have to include all other attributes—it is possible to only pass in the ObjectID attribute plus those attributes that have changed.

A new CallbackListener needs to be created to handle the asynchronous response from the applyEdits method. The onCallback method receives a FeatureEditResult[ ][ ]multidimensional array object. This result object contains FeatureEditResult objects for every addition, deletion, and update:

  • the first sub-array, editResult[0], provides an array of addition results
  • the second sub-array, editResult[1], provides an array of deletion results, and
  • the third sub-array, editResult[2], provides an array of update results

In the following code example, a new graphic representing a feature addition is created by calling the createFeatureWithTemplate method, passing in a feature template, and the geometry of the new feature. This new feature is added to an array, and passed as the first parameter into the applyEdits method. A callback is set to receive the edit result, in which the first sub-array is checked for addition edit result success (this code is checking only the result of a single addition edit, referenced by editResult[0][0]).

// Create a graphic using a template, and add it to an array of graphics.
Graphic newFeatureGraphic = featureLayer.createFeatureWithTemplate(template, geometry);

// Pass array of additions to applyEdits as first parameter.
Graphic[] adds = {newFeatureGraphic};
featureLayer.applyEdits(adds, null, null, new CallbackListener<FeatureEditResult[][]>() {
    
  public void onError(Throwable error) {
    // Implement error handling code here
  }

  public void onCallback(FeatureEditResult[][] editResult) {
    // Check the response for success or failure
    if (editResult[0] != null && editResult[0][0] != null && editResult[0][0].isSuccess()) {
      // Implement any required success logic here
    }
  }
});

In the following code example, a new graphic representing an update to an existing feature is created by using the Graphic class constructor, passing in a set of attributes that include the ObjectID of the feature to be updated and the new value of the edited attribute. This new feature is added to an array, and passed as the third parameter into the applyEdits method. A callback is set to receive the edit result, in which the third sub-array is checked for update edit result success (this code is checking only the result of a single update edit, referenced by editResult[2][0]).

// Create attributes, including ObjectID and attribute being updated, and set into a Graphic.
Map<String, Object> attr = new HashMap<String, Object>();
attr.put(featureLayer.getObjectIdField(), objectIDOfUpdatedFeature);
attr.put(attributeFieldToEdit.getName(), newAttributeValue);
Graphic updatedFeatureGraphic = new Graphic(geometry, symbol, attr, null);
  
// Pass array of updates to applyEdits as third parameter.
Graphic[] updates = {updatedFeatureGraphic};
featureLayer.applyEdits(null, null, updates, new CallbackListener<FeatureEditResult[][]>() {

  public void onError(Throwable error) {
    // Implement error handling code here
  }

  public void onCallback(FeatureEditResult[][] editResult) {

    // Check the response for success or failure
    if (editResult[2] != null && editResult[2][0] != null && editResult[2][0].isSuccess()) {
      // Implement any required success logic here
    }
  }
});

The onCallback method is called even if there is an error with the edits, so you need to add code similar to the above to check for success or failure. The onError method will also fire after this method if there has been an error.

Edit capabilities and geometry updates

A feature service can have restrictions on what editing operations can be performed, and on which users can perform each operation. You can obtain the overall capabilities of the service via the ArcGISFeatureLayer.getEditCapabilities method. It's good practice to check the capabilities of a service before sending an editing request through to the server, as an incompatible request will be rejected by the server and may represent wasted effort.

At ArcGIS for Server 10.1 or later, a feature service may prevent geometries from being updated. You can check this service property by using the ArcGISFeatureLayer.isAllowGeometryUpdates method. If this method returns false, feature geometries cannot be updated, and geometries will not be sent to the server during the applyEdits method call described previously. When geometry updates are not allowed by the service, you can still create new geometries and features, and you can still edit other feature properties such as their editable attributes.