Skip navigation
All Places > AppStudio for ArcGIS > Blog > 2017 > July
2017

Trying to build an app that has an easy to use address finder functionality? Look no further, we are excited to release a brand new beautiful, intuitive and ready-to-use geocoding sample app built with latest ArcGIS Runtime 100.1 and following Google's Material Design guidelines. The source code of this sample is available both in the AppStudio Desktop as well as online at arcgis-appstudio-samples GitHub repo.  

 

  • You can directly download and run the sample app on your AppStudio Desktop, AppStudio Player, or even build an app on any supported platform.  
  • Check out the code of the sample app and use it to your own amazing AppStudio app
  • It's also a great resource to learn more about QML, building beautiful interfaces using Material Design, AppFramework, and ArcGIS Runtime concepts.  

 

Few features and highlights of the sample:

 

When you type an address or a point of interest, a list of suggestions based on the input address will show up, which provides you with a better geocoding experience.  As you can see, when typing 380, the search returns all of the possible results containing 380.  This auto-complete function not only avoids user provide invalid address but also saves time typing out an entire address.                        

        

 

 

This geocoding sample app does more than just search for places. We improved the geo-searching experience by sorting search results based on the direction and how far they are from the user’s current location. A campus icon and the distance will be displayed at the beginning of the returned address. As I search for Starbucks, the results that I got are sorted by distance, which is extremely helpful for me to choose the closest Starbucks on the way back home.

            

     

AppStudio for ArcGIS 2.0 now supports ArcGIS Runtime Version 100.1, which means many features such as 3D scenes, raster data, mobile map packages, and vector tiles can be used in your mapping applications. This geocoding sample app takes advantage of new runtime capabilities and uses the World Street Map, which is a vector tile layer as the basemap. The vector tile layer delivers a high-resolution display across devices. It also performs faster than raster tiles due to the fact that it has a smaller file size. The vector tile layer provides unique capabilities for customization, such as changing its label fonts, symbology, content, and more.

 

           

 

Can't wait? Let's get started:

 

  1. Download AppStudio Desktop Edition from here (if you have not already)
  2. Click on the New App button
  3. Search for the Geocoding sample app
  4. Choose the Geocoding sample app and click Create
  5. Now you can run the app and also upload it to your org and use the Player to play it in your own device of choice.
  6. If you want to learn more about the code, click the 'Edit' icon on the side panel to view and edit source code

 

               

 

 

When you open the app project from Qt Creator.  The first folder, “controls” contains four files, which are used to complete the user interface. Each file is a customized control component, which can be reused by calling the filename. For example, the MapRoundButton.qml file includes the snippets of QML code that defines a round button interface; it is used three times for three round buttons on the right of the map. To load a component:

  1. Import a component. In this case, we use import "../controls" statement
  2. Load a component by calling the QML filename.                                                                                                     Note that in the MapArea.qml file, the MapRoundButton component matches the QML filename.

            

 

The second folder, “images,” contains all of the system icon images for the Geocoding app. You will find the most important source code from the third folder; “views.” The GeocodeView.qml includes QML code that implements the geocoding function.  Take a look at imports; you might notice the import Esri.ArcGISRuntime 100.1 statement. ArcGISRuntime SDK integrates mapping and GIS capabilities and empowers this geocoding sample app. Geocoding is implemented with the LocatorTask class. You can pass an online locator URL or create an offline locator and pass the file path to the LocatorTask. ArcGIS Online World Geocoding service is used in this sample. You will be able to find the LocatorTask class from the GeocodeView.qml file (line 285).

LocatorTask {
    id: locatorTask
    url: "http://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer"
}

 

The MapArea.qml file includes the QML code that imports the base map, complete action button interface, and the button's 'click' functionality, as well as drawing a pinpoint of the reach results on the map.

 

And that was a quick look at the structure and code of the geocoding sample app.  I hope you find it helpful to implement geocoding functionality to your own amazing native apps.  More exciting sample apps will roll out soon!   

 

Tile Package Kreator

Tile Package Kreator -  the desktop utility used for the easy creation of Tile Packages (i.e. local basemaps that you can take offline in Survey123 for ArcGIS, Collector for ArcGIS and ArcGIS Runtime apps) has just been updated! Version 1.2 comes complete with a number of enhancements that will make the app easier and more intuitive to use. To find out how to use it - please see the following blog: Taking your maps offline with Tile Package Creator.

 

Esri Labs projects are developed by Esri employees and are inspired by our interactions with ArcGIS users like you. Esri Labs projects are free to use but are not official Esri products. These projects do not go through the rigorous software development cycle so they are not holistically tested, documented or supported by Esri technical support.

 

But for now let’s run through what’s new:

 

New functionality

You can now navigate to your desired location using a place name or address, and once there, you can draw polygons (as well as squares and polylines) to define your export extent. If you want to revisit the extent at later date, you can now save these drawn extents as spatial bookmarks (which can be exported to geojson too). TPK 1.2 will also enable you to interactively define the range of zoom levels you want to export – so if you want to export for example levels 4-12, this is now possible.

 

Improvements

To make life easier, you can now switch tile services/basemaps without having to return to the gallery, and any public tiled service that you added to app will be persisted (so no need to keep re-entering them). There have also been a number of bug fixes related to the UI and file management.

 

If you want to get your hands on the latest version of the app – please visit here: ArcGIS Marketplace

The latest version of the guide can be downloaded here: Guide

Summary

 

SQL was introduced as a Beta feature in the AppFramework as part of AppStudio 2.0. What this means is we are looking forward to your feedback, use cases and what you want us to improve on. Future changes may affect your app and may require additional changes to support it.

 

In AppStudio 2.0 you can:

  • read/write SQLite, ODBC, PostgreSQL and MySQL databases
  • read DBF files (via SQLite virtual tables)
  • read CSV files (via SQLite virtual tables)

 

To get a taste of the SQL support, we will be covering the following.

 

  1. Minimal app - open a SQLite database
  2. Running queries
  3. Error handling
  4. Looping through results
  5. Prepared and parameterized queries
  6. Autoincrement field
  7. SqlQueryModel and SqlTableModel
  8. Including SQL Schema as an app resource 
  9. SQL Viewer app

 

1. Minimal app - open a SQLite database

 

This minimal working sample opens a SQLite database in your home directory called ArcGIS/Data/Sql/sample.sqlite. The code works on all platforms. On Android, Linux, Windows and Mac platform, the database created and can be accessed by other apps. On iOS the database will be sandboxed to your application, i.e. only your application may access it.

 

import QtQuick 2.8
import ArcGIS.AppFramework 1.0
import ArcGIS.AppFramework.Sql 1.0

Item {
  width: 640
  height: 480

  FileFolder {
    id: fileFolder
    path: "~/ArcGIS/Data/Sql"
  }

  SqlDatabase {
    id: db
    databaseName: fileFolder.filePath("sample.sqlite")
  }

  Component.onCompleted: {
    fileFolder.makeFolder();
    db.open();
  }
}


2.  Running queries

 

To run a SQL query, we use the SqlDatabase's query method. This function is overloaded, i.e. there are multiple, very useful ways of calling query. The most simplest is passing in a single string parameter and that query will be prepared and executed all in one go.

 

var query = db.query("SELECT COUNT(*) as Count FROM sqlite_master");
if (query.first()) {
  console.log(query.values.Count);
  query.finish();
}

 

3. Error handling

 

If the query failed, the error parameter would be not null. You can test for it, and, if it exists, it will be set to a JSON error object.

 

var query = db.query("****");
if (query.error) {
  console.log(JSON.stringify(query.error, undefined, 2));
} else {
  // success
}

 

Output:

 

{
  "isValid": true,
  "type": 2,
  "databaseText": "near \"****\": syntax error",
  "driverText": "Unable to execute statement",
  "text": "near \"****\": syntax error Unable to execute statement",
  "nativeErrorCode": "1"
}

 

4. Looping through results

 

If your query is a select statement, it will return data via the values JSON object property. The values property will contain values corresponding to one row of results. To get all the results we need to access them in a loop. Note that when we iterate through results, it's always important to call finish(). If you forget, the query could lock the database in an unfinished transaction which may prevent future operations such as DROP TABLE.

 

var query = db.query("SELECT * FROM Roads");
var ok = query.first();
while (ok) {
  console.log(JSON.stringify(query.values));
  ok = query.next();
}
query.finish();

 

Output:

 

qml: {"RoadID":1,"RoadName":"Coventry","RoadType":"St"}
qml: {"RoadID":2,"RoadName":"Sturt","RoadType":"St"}
qml: {"RoadID":3,"RoadName":"Kings","RoadType":"Way"}

 

5. Prepared and parameterized queries

 

A number of commands have been overloaded to support parameterized syntax. Using parametized queries diligently can stop accidental bugs or malicious attacks via SQL injection. You can bind to a parameter via name (e.g. ":name") or via position (e.g. "?"). In practice, I always recommend binding parameters by name, because it's stricter and safer. Parameterized queries go well with prepared queries. This is when you offer one SQL statement for repeated execution. The following shows how you can use this approach to populate a table.

 

var insert = db.query();
insert.prepare("INSERT INTO Roads (RoadName, RoadType) VALUES (:name, :type)");
insert.executePrepared( { "name": "Bank", "type": "St" } );
insert.executePrepared( { "name": "Dorcas", "type": "St" } );

 

6. Autoincrement field

 

If your table has an autoincrement field you may want to query its value so that you can use it. This is useful if that field is used in a relationship. i.e. you want to populate a related table using the value of the autoincrement field. The value of the last autoincrement operation is in the insertId property.

 

var query = db.query("INSERT INTO Roads (RoadName, RoadType) VALUES ('Park', 'St')");
var roadID = query.insertId;
var query2 = db.query(
    "INSERT INTO Inspections (RoadID, Quality) VALUES (:id, :quality)",
    { "id": roadID, "quality": "good" } );

 

7. SqlQueryModel and SqlTableModel

 

SqlQueryModel and SqlTableModel are a read-only data model for SQL result sets. The following demonstrates how you can populate a TableView using a SqlQueryModel.

 

import QtQuick 2.8
import ArcGIS.AppFramework 1.0
import ArcGIS.AppFramework.Sql 1.0

Item {
  width: 640
  height: 480

  TableView {
    id: tableView
    anchors.fill: parent
    TableViewColumn {
      role: "RoadID"
      title: "Road ID"
    }
    TableViewColumn {
      role: "RoadName"
      title: "Road Name"
    }
    TableViewColumn {
      role: "RoadType"
      title: "Road Type"
    }
  }

  FileFolder {
    id: fileFolder
    path: "~/ArcGIS/Data/Sql"
  }

  SqlDatabase {
    id: db
    databaseName: fileFolder.filePath("sample.sqlite")
  }

  Component.onCompleted: {
    fileFolder.makeFolder();
    db.open();
    var queryModel = db.queryModel("SELECT * FROM Roads");
    tableView.model = queryModel;
  }
}

 

Output:

 

SQL Viewer Demo

 

8. Including SQL Schema as an app resource

 

To reduce the amount of JavaScript code, you may choose to initialize a SQLite database using a SQL Schema written in SQL. For example the following initdb.sql resets the SQLite database with a new Roads database every time the app is run:

 

DROP TABLE IF EXISTS Roads;
CREATE TABLE Roads
(
    RoadID   INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
    RoadName TEXT,
    RoadType TEXT,
    CHECK (RoadType IN ('St', 'Rd', 'Way'))
);
INSERT INTO Roads (RoadName, RoadType) VALUES ('Coventry', 'St');
INSERT INTO Roads (RoadName, RoadType) VALUES ('Sturt', 'St');
INSERT INTO Roads (RoadName, RoadType) VALUES ('Kings', 'Way');
CREATE INDEX IX_Roads_001 ON Roads (RoadName);
CREATE INDEX IX_Roads_002 ON Roads (RoadType);

Qt Creator will recognize SQL files if you add the *.sql filter to the qmlproject file as shown here:

 

    Files {
        directory: "."
        recursive: true
        filter: "*.json;*.html;*.txt;*.sql"
    }

 

Place the initdb.sql file into a scripts subdirectory and use the following code to load it:

 

    FileFolder {
        id: scriptsFolder
        url: "scripts"
    }

    Component.onCompleted: {
        dataFolder.makeFolder();
        db.open();
        var lines = scriptsFolder.readTextFile("initdb.sql").split(";");
        for (var i = 0; i < lines.length; i++) {
            var sql = lines[i];
            var query = db.query(sql);
            if (query.error) {
                console.log(JSON.stringify(query.error, undefined, 2));
                continue;
            }
        }
    }

 

Note that this example recognizes we can extract SQL commands by recognize each command is terminated by a semicolon. For more sophisticated SQL Schema involving triggers we will need to adapt the loading code appropriately.

 

9. SQL Viewer

 

The "SQL Viewer" app is available for you to try which demonstrates all of the above points. You can find a "SQL Viewer" app in AppStudio:

 

  1. Launch AppStudio
  2. Select New App
  3. Click Search Icon
  4. Type: SQL Viewer

 

The "SQL Viewer" source code is also available at arcgis-appstudio-samples/SQL Viewer at v2.0 · Esri/arcgis-appstudio-samples · GitHub 

 

10. Other AppStudio SQL Blogs

 

Introduction to SQL Beta in AppStudio 2.0
Using CSV files in your application