View in Java Kotlin View on GitHub
Sample viewer app
Find features in a feature table which match an SQL query.
Use case
Query expressions can be used in ArcGIS to select a subset of features from a feature table. This is most useful in large or complicated data sets. A possible use case might be on a feature table marking the location of street furniture through a city. A user may wish to query by a TYPE column to return "benches". In this sample, we query a U.S. state by STATE_NAME from a feature table containing all U.S. states.
How to use the sample
Input the name of a U.S. state into the text field. When you tap "GO", a query is performed and the matching features are highlighted or an error is returned.
How it works
Create a ServiceFeatureTable
using the URL of a feature service.
Create a QueryParameters
with a where clause specified using setWhereClause()
.
Perform the query using queryFeaturesAsync(query)
on the service feature table.
When complete, the query will return a FeatureQueryResult
which can be iterated over to get the matching features.
About the data
This sample uses U.S. State polygon features from the USA 2016 Daytime Population feature service.
Relevant API
FeatureLayer
FeatureQueryResult
QueryParameters
ServiceFeatureTable
Search and Query
Sample CodeMainActivity.java
Use dark colors for code blocks Copy
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
/* Copyright 2016 ESRI
*
* All rights reserved under the copyright laws of the United States
* and applicable international laws, treaties, and conventions.
*
* You may freely redistribute and use this sample code, with or
* without modification, provided you include the original copyright
* notice and use restrictions.
*
* See the Sample code usage restrictions document for further information.
*
*/
package com.esri.arcgisruntime.sample.featurelayerquery;
import java.util.Iterator;
import android.app.SearchManager;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.SearchView;
import com.esri.arcgisruntime.ArcGISRuntimeEnvironment;
import com.esri.arcgisruntime.concurrent.ListenableFuture;
import com.esri.arcgisruntime.data.Feature;
import com.esri.arcgisruntime.data.FeatureQueryResult;
import com.esri.arcgisruntime.data.QueryParameters;
import com.esri.arcgisruntime.data.ServiceFeatureTable;
import com.esri.arcgisruntime.geometry.Envelope;
import com.esri.arcgisruntime.geometry.Point;
import com.esri.arcgisruntime.geometry.SpatialReferences;
import com.esri.arcgisruntime.layers.FeatureLayer;
import com.esri.arcgisruntime.mapping.ArcGISMap;
import com.esri.arcgisruntime.mapping.Basemap;
import com.esri.arcgisruntime.mapping.BasemapStyle;
import com.esri.arcgisruntime.mapping.view.MapView;
import com.esri.arcgisruntime.symbology.SimpleFillSymbol;
import com.esri.arcgisruntime.symbology.SimpleLineSymbol;
import com.esri.arcgisruntime.symbology.SimpleRenderer;
public class MainActivity extends AppCompatActivity {
private static final String TAG = MainActivity.class.getSimpleName();
private MapView mMapView;
private ServiceFeatureTable mServiceFeatureTable;
private FeatureLayer mFeatureLayer;
@Override
protected void onCreate (Bundle savedInstanceState) {
super .onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// authentication with an API key or named user is required to access basemaps and other
// location services
ArcGISRuntimeEnvironment.setApiKey(BuildConfig.API_KEY);
// get reference to map view
mMapView = findViewById(R.id.mapView);
// create a map with the topographic basemap
final ArcGISMap map = new ArcGISMap(BasemapStyle.ARCGIS_TOPOGRAPHIC);
// set the map to the map view
mMapView.setMap(map);
// create a service feature table and a feature layer from it
mServiceFeatureTable = new ServiceFeatureTable(getString(R.string.us_daytime_population_url));
// create the feature layer using the service feature table
mFeatureLayer = new FeatureLayer(mServiceFeatureTable);
mFeatureLayer.setOpacity( 0.8f );
mFeatureLayer.setMaxScale( 10000 );
//override the renderer
SimpleLineSymbol lineSymbol = new SimpleLineSymbol(SimpleLineSymbol.Style.SOLID, Color.BLACK, 1 );
SimpleFillSymbol fillSymbol = new SimpleFillSymbol(SimpleFillSymbol.Style.SOLID, Color.YELLOW, lineSymbol);
mFeatureLayer.setRenderer( new SimpleRenderer(fillSymbol));
// add the layer to the map
map.getOperationalLayers().add(mFeatureLayer);
// zoom to a view point of the USA
mMapView.setViewpointCenterAsync( new Point(- 11000000 , 5000000 , SpatialReferences.getWebMercator()), 100000000 );
}
/**
* Handle the search intent from the search widget
*/
@Override
protected void onNewIntent (Intent intent) {
setIntent(intent);
if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
String searchString = intent.getStringExtra(SearchManager.QUERY);
searchForState(searchString);
}
}
private void searchForState ( final String searchString) {
// clear any previous selections
mFeatureLayer.clearSelection();
// create objects required to do a selection with a query
QueryParameters query = new QueryParameters();
// make search case insensitive
query.setWhereClause( "upper(STATE_NAME) LIKE '%" + searchString.toUpperCase() + "%'" );
// call select features
final ListenableFuture<FeatureQueryResult> future = mServiceFeatureTable.queryFeaturesAsync(query);
// add done loading listener to fire when the selection returns
future.addDoneListener(() -> {
try {
// call get on the future to get the result
FeatureQueryResult result = future.get();
// check there are some results
Iterator<Feature> resultIterator = result.iterator();
if (resultIterator.hasNext()) {
// get the extent of the first feature in the result to zoom to
Feature feature = resultIterator.next();
Envelope envelope = feature.getGeometry().getExtent();
mMapView.setViewpointGeometryAsync(envelope, 10 );
// select the feature
mFeatureLayer.selectFeature(feature);
} else {
Toast.makeText( this , "No states found with name: " + searchString, Toast.LENGTH_LONG).show();
}
} catch (Exception e) {
String error = "Feature search failed for: " + searchString + ". Error: " + e.getMessage();
Toast.makeText( this , error, Toast.LENGTH_LONG).show();
Log.e(TAG, error);
}
});
}
@Override
public boolean onCreateOptionsMenu (Menu menu) {
// inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
// get the SearchView and set the searchable configuration
SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
SearchView searchView = (SearchView) menu.findItem(R.id.action_search).getActionView();
// assumes current activity is the searchable activity
searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
searchView.setIconifiedByDefault( false );
return true ;
}
@Override
protected void onPause () {
mMapView.pause();
super .onPause();
}
@Override
protected void onResume () {
super .onResume();
mMapView.resume();
}
@Override protected void onDestroy () {
mMapView.dispose();
super .onDestroy();
}
}