Access feature data in the cloud

Feature services expose REST endpoints to store and query geographic data such as points, lines, and polygons. The ArcGIS Runtime SDK for Android provides APIs to work with display and query features from these service. This tutorial shows you how to add a feature service that is hosted in to a map as a layer, and how to perform a query on the features in the service.

Create the QueryCloudFeatureService project in Android Studio

Start by creating a new Android application project. These steps are essentially the same as covered in the Add a map to your app tutorial. For more information about the project set up steps, refer to the Add a map to your app tutorial.

  1. In the Android Studio Welcome screen, under Quick Start, click Start a new Android Studio project.
  2. In Application name, enter QueryCloudFeatureService. Optionally change the Company Name and Project Location if you want to, then click Next.
    Create new project dialog window in Android Studio
  3. Leave the default Phone and Tablet option selected, in the Minimum SDK drop-down list, choose API 15: Android 4.0.3, then click Next.
  4. Click Blank Activity, then click Next. (In the latest Android Studio you may find this option is called Empty Activity.)
  5. Leave the default names for the activity, layout, title, and menu resource, and click Finish.

    A new default Android application project opens, showing a default layout.

You have now successfully created an Android project containing an application module. Next you will add the Runtime Android SDK Android dependency.

Add the ArcGIS Runtime for Android AAR dependency

Here you will add the Runtime Android SDK dependency to your application module as an Android Archive (AAR) package.

  1. In the Android project view window, under Gradle Scripts, double-click build.gradle (Project: QueryCloudFeatureService). This opens the gradle build script for the project where you can add the Esri ArcGIS Maven repository URL as shown below:
    allprojects {
        repositories {
            // add the esri arcgis maven repo
            maven {
                url ''
  2. In the Android project view window, under Gradle Scripts, double-click build.gradle (Module: app).
  3. In the dependencies section of the script, add a new value compile ''.
    dependencies {
      compile fileTree(dir: 'libs', include: ['*.jar'])
      compile '' 

    Depending on your Android Studio version, you may find a more recent version of the appcompat dependency; you can use either version.

  4. In the android section of the script, after defaultConfig, add the following values:
      exclude 'META-INF/LGPL2.1' 
      exclude 'META-INF/LICENSE' 
      exclude 'META-INF/NOTICE' 
  5. In the Android project view window, under manifests, double-click AndroidManifest.xml.
  6. In the AndroidManifest.xml file, add the following elements as children of the manifest element:
    <uses-feature android:glEsVersion="0x00020000"android:required="true" />
    <uses-permission android:name="android.permission.INTERNET" />
  7. In the Android Studio toolbar, click Sync Project with Gradle Files. Alternatively, when you see the Gradle files have changed since last project sync message at the top of the gradle script window, click Sync Now.

You have added a dependency to the Runtime Android SDK AAR to your app module. Next, you'll add code and a MapView.

Add a map and a feature service layer

In this step you will add a MapView to your layout. You will also add a hosted feature service layer to the map, and a graphics layer to display the results of queries on the feature service.

  1. In the Android project view window, under app, navigate to res > layout, then double-click activity_main.xml.

    Note that depending on the type of activity chosen and the version of Android Studio, your project may contain only one layout XML file, activity_main.xml, or multiple layout files, including content_main.xml; if so, open this file instead.

  2. At the bottom-left of the window, click Text to show the XML view of the layout.
  3. Select the entire TextView XML element and replace it with a MapView element as shown below:
      mapoptions.ZoomLevel="3""39.8282, -98.5795" />

    This map element has mapoptions attributes that tell the MapView to display initially using a default Topo map service layer, and to center the map at a specific set of coordinates, and zoom the map to a specific level.

  4. In the Android project view window, under app, navigate to res > values, then double-click strings.xml.
  5. Add the following string resources:
    <string name="featureServiceURL"></string>

    This string holds the URL of the hosted feature service you will add to the map as a layer.

  6. In the Android project view window, under app, navigate to java >, then double-click MainActivity to open the activity source code file.
  7. Add the following class variable declarations to the top of the MainActivity class:
    MapView mMapView;
    ArcGISFeatureLayer mFeatureLayer; 
    GraphicsLayer mGraphicsLayer;
    String mFeatureServiceURL;

    These variables will hold references to the MapView you added to the layout, and also to the feature service URL and layer, and results graphics layer.

  8. Android Studio will highlight in red the classes which must be imported to the class file. Place the cursor at the line with text highlighted in red and press ALT+Enter to resolve the symbol and import the,, and classes to your activity class.
    Resolve symbol error message in Android Studio

    You should resolve symbols for any similar errors you get throughout this tutorial.


    A complete list of imports is available at the end of this tutorial so you can check you have imported the classes correctly.

  9. In the OnCreate method, after the content view is set, set the reference to the MapView in the layout, and then create the feature service layer and graphics layer, and add both layers to the map:
    // Retrieve the map and initial extent from XML layout 
    mMapView = (MapView) findViewById(; 
    // Get the feature service URL from values->strings.xml 
    mFeatureServiceURL = this.getResources().getString(R.string.featureServiceURL); 
    // Add Feature layer to the MapView 
    mFeatureLayer = new ArcGISFeatureLayer(mFeatureServiceURL, ArcGISFeatureLayer.MODE.ONDEMAND); 
    // Add Graphics layer to the MapView 
    mGraphicsLayer = new GraphicsLayer(); 

You now have an app that contains a map with a feature service layer. You can run the app and test your code is working so far. Next, you will add code that runs when the user uses the options menu and performs a query on the feature service.

Add the query options menu

Now you will define the options menu of queries and add code to respond when a menu option is tapped.

  1. In the Android project view window, under app, right-click the res folder.
  2. Choose New > Android Resource File.

    This opens the New Resource File dialog box.

  3. Enter the following values into this dialog box, leaving the remaining options as their default values:
    • File name: menu_main
    • Resource type: Menu
  4. Click OK.

    This adds the new menu XML file to the project, and opens it.

  5. Add the following elements as children of the existing menu element:
    <group android:checkableBehavior="single">
            android:title="@string/query_us" />
            android:title="@string/query_ca" />
            android:title="@string/query_fr" />
            android:title="@string/query_au" />
            android:title="@string/query_br" />

    This defines the options in the options menu layout. Next you must define the strings that are used in these options.

  6. In the Android project view window, under app, navigate to res > values, then double-click strings.xml.
  7. Add the following string resources:
    <!-- query parameters -->
    <string name="query_us">COUNTRY = US</string>
    <string name="query_ca">COUNTRY = CANADA</string>
    <string name="query_fr">COUNTRY = FRANCE</string>
    <string name="query_au">COUNTRY = AUSTRALIA</string>
    <string name="query_br">COUNTRY = BRAZIL</string>

    These strings are used for the user interface of the options menu items you defined previously.

  8. In the Android project view window, under app, navigate to java >, then double-click MainActivity to open the activity source code file.
  9. Add the following class variable declarations to the top of the MainActivity class:
    MenuItem mQueryUsMenuItem = null;
        MenuItem mQueryCaMenuItem = null;
        MenuItem mQueryFrMenuItem = null;
        MenuItem mQueryAuMenuItem = null;
        MenuItem mQueryBrMenuItem = null;

    These variables will hold references to the MenuItems in the options menu.

  10. Override the onCreateOptionsMenu method of your activity and add code to inflate and set the new menu using getMenuInflater.inflate(, menu), and also set references to the new menu items.
    @Override public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(, menu);
        // Get the query params menu items.
        mQueryUsMenuItem = menu.getItem(0);
        mQueryCaMenuItem = menu.getItem(1);
        mQueryFrMenuItem = menu.getItem(2);
        mQueryAuMenuItem = menu.getItem(3);
        mQueryBrMenuItem = menu.getItem(4);
        return true;
    This sets the variables you added previously to reference the menu items in the options menu, when the menu layout is first shown; you will use these references in a following step.
  11. Override the onOptionsItemSelected method of your activity, replace the entire method body with the following code:
    @Override public boolean onOptionsItemSelected(MenuItem item) {
        // Handle menu item selection.
        switch (item.getItemId()) {
                QueryFeatureLayer().execute("United States");
                return true;
                new QueryFeatureLayer().execute("Canada");
                return true;
                new QueryFeatureLayer().execute("France");
                return true;
                new QueryFeatureLayer().execute("Australia");
                return true;
                new QueryFeatureLayer().execute("Brazil");
                return true;
               return super.onOptionsItemSelected(item);

    This code responds when a menu option is selected and then begins a query task, passing in information related to the specific item that was selected. You will define the QueryFeatureLayer next.

Define a task to run a query and display the results

Performing a query involves a network call to the feature service. In order for the app UI thread to remain responsive while the query is being executed, you will create an AsyncTask to perform the work on a background thread.

Learn more about Keeping your app responsive.

  1. In the MainActivity class, create a private subclass called QueryFeatureLayer that inherits from AsyncTask. run the query task off the UI thread:
    private class QueryFeatureLayer extends AsyncTask<String, Void, FeatureResult> {

    You should see a message asking you to implement the abstract method doInBackground.

  2. Add the following code to the QueryFeatureLayer class to define the doInBackground method.

            protected FeatureResult doInBackground(String... params) {
                String whereClause = "CNTRY_NAME='" + params[0] + "'";
                // Define a new query and set parameters
                QueryParameters mParams = new QueryParameters();
                // Define the new instance of QueryTask
                QueryTask queryTask = new QueryTask(mFeatureServiceURL);
                FeatureResult results;
                try {
                    // run the querytask
                    results = queryTask.execute(mParams);
                    return results;
                } catch (Exception e) {
                return null;

    Note that this method receives a String parameter; this value will be based on the selected menu item, defined in the onOptionsItemSelected method you added previously. This method will be called on a background thread. Its results will be passed to the onPostExecute method that you will add next.

    Refer to the imports list at the bottom of this tutorial to make sure you have imported the correct classes.

  3. Add the following code to the QueryFeatureLayer class to define the onPostExecute method.

            protected void onPostExecute(FeatureResult results) {
                // Remove the result from previously run query task
                // Define a new marker symbol for the result graphics
                SimpleMarkerSymbol sms = new SimpleMarkerSymbol(Color.BLUE, 10, SimpleMarkerSymbol.STYLE.CIRCLE);
                // Envelope to focus on the map extent on the results
                Envelope extent = new Envelope();
                // iterate through results
                for (Object element : results) {
                    // if object is feature cast to feature
                    if (element instanceof Feature) {
                        Feature feature = (Feature) element;
                        // convert feature to graphic
                        Graphic graphic = new Graphic(feature.getGeometry(), sms, feature.getAttributes());
                        // merge extent with point
                        // add it to the layer
                // Set the map extent to the envelope containing the result graphics
                mMapView.setExtent(extent, 100);

    Note that this method receives a FeatureResult parameter; this value was created in the doInBackground method you added previously. This method takes each feature in the FeatureResult and adds new graphics to the results graphics layer, drawing the results with a blue circle symbol. Finally, the map extent is updated to show the new graphics.

You can now test your query is working.

Run the application

To test your app, you should either have a connected device ready for debugging, or have a set up and started an emulator. To find our more, refer to the Android documentation on Using the emulator or Using hardware devices.

  1. In the Android Studio toolbar, click Run.
  2. In the Choose Device dialog, select the device or emulator you wish to use, then click OK
  3. When the app opens on your device, it shows a topological map.
  4. In the action bar of the app, tap the options overflow, and select one of the query options available.

    The map updates to show blue symbols for the features that satisfy that query.

    Query Cloud Feature Service app showing query options and results

That's it, you have built an app that displays feature data from an hosted service, and queries that service.

See an enhanced version of the QueryCloudFeatureService sample on the website—this demonstrates how you can add a progress dialog while your query is executing, and also how to show callouts when the user taps on a graphic in the results graphics layer. Fork the samples repo on GitHub to work with the sample.


The complete list of imports for your project should be:

import android.os.AsyncTask;
import android.os.Bundle;
import;  // May vary depending Android Studio version and options chosen
import android.view.Menu;
import android.view.MenuItem;

import com.esri.core.geometry.Envelope;
import com.esri.core.geometry.Point;
import com.esri.core.symbol.SimpleMarkerSymbol;
import com.esri.core.tasks.query.QueryParameters;
import com.esri.core.tasks.query.QueryTask;