Getting started with ArcGIS Runtime SDK for Android (24): temporal data query

Posted by Darklink on Mon, 30 Dec 2019 19:11:24 +0100

The temporal Query function is to retrieve the time information stored in the element table through the time range set by the user, so as to obtain the operation of elements in a specific temporal range. In this case, taking typhoon data as an example, the temporal Query conditions are constructed through the set time range, the temporal Query results of the elements are obtained by executing the Query query, and the resulting elements are transformed into graphic objects for display.

Implementation steps:

1. Create Android project

2. Add Runtime SDK dependency

The first two steps are omitted. For beginners, please refer to Getting started with ArcGIS Runtime SDK for Android (1): first map application (2D)

3. Add permissions and OpenGL ES support

Add in Android manifest.xml:

    <!--Networking permission -->
    <uses-permission android:name="android.permission.INTERNET" />
    <!--OpenGL ES Support -->
    <uses-feature
        android:glEsVersion="0x00020000"
        android:required="true" />

4. Set interface layout

Layout XML code:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:orientation="horizontal">
        <Button
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:id="@+id/btnSetStartDate"
            android:text="Set start date"/>
        <Button
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:id="@+id/btnSetEndDate"
            android:text="Set end date"/>

    </LinearLayout>

    <com.esri.arcgisruntime.mapping.view.MapView
        android:id="@+id/mapView"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="10"/>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:orientation="horizontal">

        <Button
            android:id="@+id/btnQuery"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:text="QUERY" />

        <Button
            android:id="@+id/btnClearGraphics"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:text="Clear query results"/>
    </LinearLayout>

</LinearLayout>

5. Write code

Train of thought:

(1) Load online feature service data.

(2) Set two buttons to open the date selection box, and set the start and end dates.

(3) Perform temporal query according to the set start and end dates.

Steps:

(1) Variable preparation:

    private ArcGISMap mMap;                                     //Map objects
    private MapView mMapView;                                   //MapView component object
    private ServiceFeatureTable mServiceFeatureTable;           //Element table service object
    private FeatureLayer mFeaturelayer;                         //Feature layer objects
    private DatePickerDialog mStartDateDialog;                  //Set date selection box for start date
    private DatePickerDialog mEndDateDialog;                    //Set date selection box for end date
    private GregorianCalendar mStartDateCalendar;               //From date object
    private GregorianCalendar mEndDateCalendar;                 //End date object

(2) onCreate method:

    //Trigger event to execute this function during Activity initialization
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //Get MapView component object in Layout
        mMapView = (MapView)findViewById(R.id.mapView);
        //Create map objects with ocean map as base map
        mMap = new ArcGISMap(Basemap.createOceans());
        //Creating element table of typhoon element service through URL
        mServiceFeatureTable = new ServiceFeatureTable("https://sampleserver6.arcgisonline.com/arcgis/rest/services/Hurricanes/MapServer/0");
        //Creating a Featurelayer object using a ServiceFeatureTable object
        mFeaturelayer = new FeatureLayer(mServiceFeatureTable);
        //Add layers to your map
        mMap.getOperationalLayers().add(mFeaturelayer);
        //Set map display in MapView
        mMapView.setMap(mMap);
        //Initialization date selection box
        initDatePickerDialog();
        //Set click listening events for each button
        findViewById(R.id.btnSetStartDate).setOnClickListener(this);
        findViewById(R.id.btnSetEndDate).setOnClickListener(this);
        findViewById(R.id.btnQuery).setOnClickListener(this);
        findViewById(R.id.btnClearGraphics).setOnClickListener(this);
    }

(3) Initialization method of date selection box:

    //Initialization date selection box
    private void initDatePickerDialog(){
        //Create time selection box object and set listening
        mStartDateDialog = new DatePickerDialog(MainActivity.this, new DatePickerDialog.OnDateSetListener() {
            @Override
            public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) { ;
                mStartDateCalendar=new GregorianCalendar(year, monthOfYear, dayOfMonth);
            }
        }, 2000, 7, 1);
        mEndDateDialog = new DatePickerDialog(MainActivity.this, new DatePickerDialog.OnDateSetListener() {
            @Override
            public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) { ;
                mEndDateCalendar=new GregorianCalendar(year, monthOfYear, dayOfMonth);
            }
        },2000,7,1);
        //Set the time range of the date selection box
        Calendar startCalendar = Calendar.getInstance();
        Calendar endCalendar = Calendar.getInstance();
        startCalendar.set(2000,7,1);
        endCalendar.set(2000,9,31);
        mStartDateDialog.getDatePicker().setMinDate(startCalendar.getTime().getTime());
        mStartDateDialog.getDatePicker().setMaxDate(endCalendar.getTime().getTime());
        mEndDateDialog.getDatePicker().setMinDate(startCalendar.getTime().getTime());
        mEndDateDialog.getDatePicker().setMaxDate(endCalendar.getTime().getTime());
    }

(4) The core method of executing temporal query:

    //Execute Query temporal Query operation and display Query results
    private void queryByTimeExtent(){
        //Create query parameter object
        QueryParameters queryParameters = new QueryParameters();
        //Set where clause to query all elements
        queryParameters.setWhereClause("1=1");
        // Create time range objects and set start and end times
        TimeExtent timeExtent = new TimeExtent(mStartDateCalendar,mEndDateCalendar);
        //Set the time range of query parameters
        queryParameters.setTimeExtent(timeExtent);
        //Query elements
        final ListenableFuture<FeatureQueryResult> future = mServiceFeatureTable.queryFeaturesAsync(queryParameters);
        //When the asynchronous query result returns, use addDoneListener to trigger to receive
        future.addDoneListener(new Runnable() {
            @Override
            public void run() {
                try {
                    //Call get method to get query results
                    FeatureQueryResult result = future.get();
                    //Create a graphiccoverlay object to display query results
                    GraphicsOverlay graphicsOverlay=new GraphicsOverlay();
                    //Creating feature iterator to traverse query results
                    Iterator<Feature> iterator=result.iterator();
                    //Check and traverse query results
                    while(iterator.hasNext()) {
                        //Traversing elements in iterators
                        Feature feature =iterator.next();
                        //Get the geometry object of the result feature
                        Geometry geometry=feature.getGeometry();
                        //Create Symbol to display query results
                        SimpleMarkerSymbol markerSymbol=new SimpleMarkerSymbol(SimpleMarkerSymbol.Style.CIRCLE, Color.RED, 8);
                        //Create a Graphic for displaying query results and add it to the Graphic overlay
                        Graphic graphic=new Graphic(geometry,markerSymbol);
                        graphicsOverlay.getGraphics().add(graphic);
                    }
                    //Show query results
                    mMapView.getGraphicsOverlays().clear();
                    mMapView.getGraphicsOverlays().add(graphicsOverlay);
                    Envelope envelope = graphicsOverlay.getExtent();
                    mMapView.setViewpointGeometryAsync(envelope, 100);
                } catch (Exception e) {
                    Toast.makeText(MainActivity.this, "Query failed"  + ". Error=" + e.getMessage(),Toast.LENGTH_SHORT).show();
                    Log.e(getResources().getString(R.string.app_name),"Feature search failed " + ". Error=" + e.getMessage());
                }
            }
        });
    }

(5) Click event monitoring:

    //Click event monitoring
    @Override
    public void onClick(View view) {
        switch (view.getId()){
            case R.id.btnSetStartDate:
                //When you click the "set start date" button, the start date selection box will pop up
                mStartDateDialog.show();
                break;
            case R.id.btnSetEndDate:
                //When clicking "set end date", the end date selection box will pop up
                mEndDateDialog.show();
                break;
            case R.id.btnQuery:
                //When "QUERY" is clicked, temporal QUERY is executed
                queryByTimeExtent();
                break;
            case R.id.btnClearGraphics:
                //When you click the "clear query result" button, delete the graph in MapView
                mMapView.getGraphicsOverlays().clear();
                break;
        }
    }

6. Run App: simple temporal query operation can be realized.

Topics: Android xml SDK encoding