Create, save and preview a KML multi-track, captured from a location data source.

Use case
When capturing location data for outdoor activities such as hiking or skiing, it can be useful to record and share your path. This sample demonstrates how you can collect individual KML tracks during a navigation session, then combine and export them as a KML multi-track.
How to use the sample
Start the KML multi track sample application to begin moving along a simulated trail. Tap Record Track(s) to start recording your current path. Tap Stop Recording to end recording and capture a KML track. Repeat these steps to capture multiple KML tracks in a single session. Tap the Save button to save your recorded tracks as a .kmz file to local storage. Then load the created .kmz file containing your KML multi-track to view all created tracks on the map. Tap the Recenter icon to position the location at the center of the map view.
How it works
- Create a
Mapwith a basemap and aGraphicsOverlayto display the path geometry for your navigation route. - Create a
SimulatedLocationDataSourceto drive theLocationDisplay. - As you receive
Locationupdates, add each point to a list ofKmlTrackElementobjects while recording. - Once recording stops, create a
KmlTrackusing one or moreKmlTrackElementobjects. - Combine one or more
KmlTrackobjects into aKmlMultiTrack. - Save the
KmlMultiTrackinside aKmlDocument, then export the document to a.kmzfile. - Load the saved
.kmzfile into aKmlDatasetand locate theKmlDocumentin the dataset’srootNodes. From the document’schildNodesget theKmlPlacemarkand retrieve theKmlMultiTrackgeometry. - Retrieve the geometry of each track in the
KmlMultiTrackby iterating through the list of tracks and obtaining the respectiveKmlTrack.geometry.
Relevant API
- KmlDataset
- KmlDocument
- KmlMultiTrack
- KmlPlacemark
- KmlTrack
- LocationDisplay
- SimulatedLocationDataSource
Tags
export, geoview-compose, hiking, kml, kmz, multi-track, record, track
Sample Code
// [WriteFile Name=CreateKmlMultiTrack, Category=EditData]]// [Legal]// Copyright 2025 Esri.//// Licensed under the Apache License, Version 2.0 (the "License");// you may not use this file except in compliance with the License.// You may obtain a copy of the License at// http://www.apache.org/licenses/LICENSE-2.0//// Unless required by applicable law or agreed to in writing, software// distributed under the License is distributed on an "AS IS" BASIS,// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.// See the License for the specific language governing permissions and// limitations under the License.// [Legal]
#ifdef PCH_BUILD#include "pch.hpp"#endif // PCH_BUILD
// sample headers#include "CreateKmlMultiTrack.h"
// ArcGIS Maps SDK headers#include "Basemap.h"#include "Error.h"#include "ErrorException.h"#include "Geometry.h"#include "GeometryEngine.h"#include "Graphic.h"#include "GraphicListModel.h"#include "GraphicsOverlay.h"#include "GraphicsOverlayListModel.h"#include "KmlDataset.h"#include "KmlDocument.h"#include "KmlMultiTrack.h"#include "KmlNodeListModel.h"#include "KmlPlacemark.h"#include "KmlTrack.h"#include "KmlTrackElement.h"#include "Location.h"#include "LocationDisplay.h"#include "Map.h"#include "MapQuickView.h"#include "MapTypes.h"#include "MapViewTypes.h"#include "Point.h"#include "Polyline.h"#include "PolylineBuilder.h"#include "SimpleLineSymbol.h"#include "SimpleMarkerSymbol.h"#include "SimulatedLocationDataSource.h"#include "SimulationParameters.h"#include "SpatialReference.h"#include "SymbolTypes.h"
// Qt headers#include <QFile>#include <QFileInfo>#include <QFuture>#include <QList>#include <QStandardPaths>#include <QUrl>
using namespace Esri::ArcGISRuntime;
// helper method to get cross platform data pathnamespace{ QString defaultDataPath() { QString dataPath;
#ifdef Q_OS_IOS dataPath = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);#else dataPath = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);#endif
return dataPath; }
QString coastalTrailJson() { QFile jsonFile(":/Samples/EditData/CreateKmlMultiTrack/coastalTrail.json"); if (!jsonFile.open(QIODevice::ReadOnly | QIODevice::Text)) { qDebug() << "Failed to open JSON file"; return {}; } return jsonFile.readAll(); }} // namespace
CreateKmlMultiTrack::CreateKmlMultiTrack(QObject* parent /* = nullptr */) : QObject(parent), m_map(new Map(BasemapStyle::ArcGISStreets, this)), m_graphicsOverlay(new GraphicsOverlay(this)), m_locationSymbol(new SimpleMarkerSymbol(SimpleMarkerSymbolStyle::Circle, Qt::red, 10, this)), m_lineSymbol(new SimpleLineSymbol(SimpleLineSymbolStyle::Solid, Qt::black, 3, this)){}
CreateKmlMultiTrack::~CreateKmlMultiTrack() = default;
void CreateKmlMultiTrack::init(){ qmlRegisterType<MapQuickView>("Esri.Samples", 1, 0, "MapView"); qmlRegisterType<CreateKmlMultiTrack>("Esri.Samples", 1, 0, "CreateKmlMultiTrackSample");}
MapQuickView* CreateKmlMultiTrack::mapView() const{ return m_mapView;}
// Set the view (created in QML)void CreateKmlMultiTrack::setMapView(MapQuickView* mapView){ if (m_mapView) { m_mapView->setMap(nullptr); // Remove map from old mapView. m_mapView->graphicsOverlays()->clear(); // Remove Graphics overlays from old mapView. }
m_mapView = mapView;
if (!m_mapView) { return; }
m_mapView->graphicsOverlays()->append(m_graphicsOverlay); m_mapView->setMap(m_map); emit mapViewChanged();
// Automatically enable recenter button when navigation pan is disabled connect(m_mapView->locationDisplay(), &LocationDisplay::autoPanModeChanged, this, [this](LocationDisplayAutoPanMode autoPanMode) { m_isRecenterButtonEnabled = (autoPanMode == LocationDisplayAutoPanMode::Off); emit isRecenterButtonEnabledChanged(); });
// Listen for changes in location connect(m_mapView->locationDisplay(), &LocationDisplay::locationChanged, this, [this](const Location& location) { if (m_isRecordingTrack) { addTrackElement(location.position()); m_polylineBuilder->addPoint(location.position()); } });
// turn on map view's navigation mode m_mapView->locationDisplay()->setAutoPanMode(LocationDisplayAutoPanMode::Navigation);}
void CreateKmlMultiTrack::startNavigation(){ // Get the hiking path geometry auto routeGeometry = geometry_cast<Polyline>(Geometry::fromJson(coastalTrailJson())); constexpr double velocity = 25.0; constexpr double horizontalAccuracy = 0.0; constexpr double verticalAccuracy = 0.0; constexpr double paddingInDips = 25.0;
// Create a simulated location data source from json data with simulation parameters to set a consistent velocity auto* simulationParameters = new SimulationParameters(QDateTime::currentDateTime(), velocity, horizontalAccuracy, verticalAccuracy, this); m_simulatedLocationDataSource = new SimulatedLocationDataSource(this); m_simulatedLocationDataSource->setLocationsWithPolyline(routeGeometry, simulationParameters);
// Set the map's initial viewpoint m_mapView->setViewpointGeometryAsync(routeGeometry, paddingInDips);
// Set the simulated location data source as the location data source for this app m_mapView->locationDisplay()->setDataSource(m_simulatedLocationDataSource);
// Start the location data source m_simulatedLocationDataSource->start();}
void CreateKmlMultiTrack::addTrackElement(const Point& locationPoint){ // Add a new element to the list of KML track elements auto* trackElement = new KmlTrackElement(QDateTime::currentDateTime(), locationPoint, nullptr, this); m_kmlTrackElements.append(trackElement); emit elementsCountChanged();
// Add a graphic at the location's position auto* graphic = new Graphic(locationPoint, m_locationSymbol, this); m_graphicsOverlay->graphics()->append(graphic);}
void CreateKmlMultiTrack::startRecordingKmlTrack(){ m_isRecordingTrack = true; emit isRecordingTrackChanged();
m_kmlTrackElements.clear(); emit elementsCountChanged();
m_polylineBuilder = new PolylineBuilder(SpatialReference::wgs84(), this);}
void CreateKmlMultiTrack::stopRecordingKmlTrack(){ if (m_kmlTrackElements.isEmpty()) { return; }
m_polylineBuilderList.append(m_polylineBuilder);
const KmlTrack kmlTrack(m_kmlTrackElements, KmlAltitudeMode::RelativeToGround); m_kmlTracks.append(kmlTrack); emit multiTrackCountChanged();
displayKmlTracks(); m_isRecordingTrack = false; emit isRecordingTrackChanged();}
void CreateKmlMultiTrack::displayKmlTracks(){ m_graphicsOverlay->graphics()->clear(); for (const auto* polyLineBuilder : m_polylineBuilderList) { // Add the polyline graphic to the map auto* graphic = new Graphic(polyLineBuilder->toPolyline(), m_lineSymbol, this); m_graphicsOverlay->graphics()->append(graphic); }}
// Exports the [KmlMultiTrack] as a kmz file to local storage.void CreateKmlMultiTrack::exportKmlMultiTrack(){ // Create a KML document auto* kmlDocument = new KmlDocument(this);
// Create a KML multi-track const KmlMultiTrack multiTrack(m_kmlTracks, false);
// Add the multi-track as a placemark auto* placemark = new KmlPlacemark(multiTrack, this); kmlDocument->childNodesListModel()->insert(0, placemark);
// Define the save file path const auto localKmlFilePath = defaultDataPath() + "/ArcGIS/Runtime/Data/kml/HikingTracks.kmz"; QFile localKmlFile(localKmlFilePath); if (localKmlFile.exists()) { localKmlFile.remove(); } // Save KML file to local storage // Write the KML document to the chosen path. kmlDocument->saveAsAsync(localKmlFilePath) .then(this, [localKmlFilePath, this]() { qDebug() << "Saved KmlMultiTrack: " + QFileInfo(localKmlFilePath).filePath(); stopNavigation(); }) .onFailed([](const ErrorException&) { qDebug() << "Error saving KML file"; });}
void CreateKmlMultiTrack::stopNavigation(){ if (m_simulatedLocationDataSource) { m_simulatedLocationDataSource->stop(); } m_isShowTracksFromFileEnabled = true; emit isShowTracksFromFileEnabledChanged();}
void CreateKmlMultiTrack::loadLocalKmlFile(){ const auto localKmlFilePath = defaultDataPath() + "/ArcGIS/Runtime/Data/kml/HikingTracks.kmz"; const QFile localKmlFile(localKmlFilePath); if (!localKmlFile.exists()) { qDebug() << "Error locating KML file"; return; }
auto* localKmlDataset = new KmlDataset(QUrl::fromLocalFile(localKmlFilePath), this); connect(localKmlDataset, &KmlDataset::doneLoading, this, [this, localKmlDataset]() { if (localKmlDataset->loadStatus() != LoadStatus::Loaded) { qDebug() << "Error parsing KML file " + localKmlDataset->loadError().message(); return; }
const auto* kmlDocument = dynamic_cast<KmlDocument*>(localKmlDataset->rootNodes().at(0)); if (!kmlDocument) { qDebug() << "Error: Root node is not a KmlDocument."; return; }
const auto* kmlPlacemark = dynamic_cast<KmlPlacemark*>(kmlDocument->childNodesListModel()->at(0)); if (!kmlPlacemark) { qDebug() << "Error: First child node is not a KmlPlacemark."; return; }
const auto kmlMultiTrack = static_cast<KmlMultiTrack>(kmlPlacemark->kmlGeometry());
QList<Geometry> geometries; for (const auto& track : kmlMultiTrack.tracks()) { geometries.append(track.geometry()); } const auto allTracksGeometry = GeometryEngine::unionOf(geometries); if (allTracksGeometry.isEmpty()) { qDebug() << "KmlMultiTrack has no geometry"; return; }
m_mapView->setViewpointGeometryAsync(allTracksGeometry, 25.0);
m_trackGeometries.append(allTracksGeometry); for (const auto& track : kmlMultiTrack.tracks()) { m_trackGeometries.append(track.geometry()); } emit trackGeometriesCountChanged(); });
localKmlDataset->load();}
void CreateKmlMultiTrack::previewKmlTrack(int index){ m_mapView->setViewpointGeometryAsync(m_trackGeometries[index], 25.0);}
void CreateKmlMultiTrack::recenter(){ m_mapView->locationDisplay()->setAutoPanMode(LocationDisplayAutoPanMode::Navigation); m_isRecenterButtonEnabled = false; emit isRecenterButtonEnabledChanged();}
void CreateKmlMultiTrack::reset(){ qDeleteAll(m_kmlTrackElements); m_kmlTrackElements.clear(); m_kmlTracks.clear(); qDeleteAll(m_polylineBuilderList); m_polylineBuilderList.clear(); m_trackGeometries.clear(); m_graphicsOverlay->graphics()->clear(); m_isShowTracksFromFileEnabled = false; emit isShowTracksFromFileEnabledChanged();}
int CreateKmlMultiTrack::elementsCount() const{ return m_kmlTrackElements.count();}
int CreateKmlMultiTrack::multiTrackCount() const{ return m_kmlTracks.count();}
int CreateKmlMultiTrack::trackGeometriesCount() const{ return m_trackGeometries.count();}// [WriteFile Name=CreateKmlMultiTrack, Category=EditData]]// [Legal]// Copyright 2025 Esri.//// Licensed under the Apache License, Version 2.0 (the "License");// you may not use this file except in compliance with the License.// You may obtain a copy of the License at// http://www.apache.org/licenses/LICENSE-2.0//// Unless required by applicable law or agreed to in writing, software// distributed under the License is distributed on an "AS IS" BASIS,// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.// See the License for the specific language governing permissions and// limitations under the License.// [Legal]
#ifndef CREATEKMLMULTITRACK_H#define CREATEKMLMULTITRACK_H
// Qt headers#include <QObject>#include <QString>
namespace Esri::ArcGISRuntime{ class Geometry; class Graphic; class GraphicsOverlay; class KmlTrack; class KmlTrackElement; class Map; class MapQuickView; class Point; class PolylineBuilder; class SimpleLineSymbol; class SimpleMarkerSymbol; class SimulatedLocationDataSource;} // namespace Esri::ArcGISRuntime
Q_MOC_INCLUDE("MapQuickView.h")
class CreateKmlMultiTrack : public QObject{ Q_OBJECT
Q_PROPERTY(Esri::ArcGISRuntime::MapQuickView* mapView READ mapView WRITE setMapView NOTIFY mapViewChanged) Q_PROPERTY(bool isRecordingTrack MEMBER m_isRecordingTrack NOTIFY isRecordingTrackChanged) Q_PROPERTY(bool isRecenterButtonEnabled MEMBER m_isRecenterButtonEnabled NOTIFY isRecenterButtonEnabledChanged) Q_PROPERTY(bool isShowTracksFromFileEnabled MEMBER m_isShowTracksFromFileEnabled NOTIFY isShowTracksFromFileEnabledChanged) Q_PROPERTY(int elementsCount READ elementsCount NOTIFY elementsCountChanged) Q_PROPERTY(int multiTrackCount READ multiTrackCount NOTIFY multiTrackCountChanged) Q_PROPERTY(int trackGeometriesCount READ trackGeometriesCount NOTIFY trackGeometriesCountChanged)
public: explicit CreateKmlMultiTrack(QObject* parent = nullptr); ~CreateKmlMultiTrack() override;
Q_INVOKABLE void startNavigation(); Q_INVOKABLE void stopNavigation(); Q_INVOKABLE void startRecordingKmlTrack(); Q_INVOKABLE void stopRecordingKmlTrack(); Q_INVOKABLE void exportKmlMultiTrack(); Q_INVOKABLE void loadLocalKmlFile(); Q_INVOKABLE void previewKmlTrack(int index); Q_INVOKABLE void recenter(); Q_INVOKABLE void reset();
static void init();
signals: void mapViewChanged(); void isRecordingTrackChanged(); void isShowTracksFromFileEnabledChanged(); void isRecenterButtonEnabledChanged(); void elementsCountChanged(); void multiTrackCountChanged(); void trackGeometriesCountChanged();
private: Esri::ArcGISRuntime::MapQuickView* mapView() const;
void setMapView(Esri::ArcGISRuntime::MapQuickView* mapView); void addTrackElement(const Esri::ArcGISRuntime::Point& locationPoint); void displayKmlTracks(); int elementsCount() const; int multiTrackCount() const; int trackGeometriesCount() const;
private: bool m_isRecenterButtonEnabled = false; bool m_isRecordingTrack = false; bool m_isShowTracksFromFileEnabled = false;
Esri::ArcGISRuntime::Map* m_map = nullptr; Esri::ArcGISRuntime::GraphicsOverlay* m_graphicsOverlay = nullptr; Esri::ArcGISRuntime::MapQuickView* m_mapView = nullptr; Esri::ArcGISRuntime::SimulatedLocationDataSource* m_simulatedLocationDataSource = nullptr; QList<Esri::ArcGISRuntime::Geometry> m_trackGeometries;
QList<Esri::ArcGISRuntime::KmlTrackElement*> m_kmlTrackElements; QList<Esri::ArcGISRuntime::KmlTrack> m_kmlTracks;
Esri::ArcGISRuntime::PolylineBuilder* m_polylineBuilder = nullptr; QList<Esri::ArcGISRuntime::PolylineBuilder*> m_polylineBuilderList;
Esri::ArcGISRuntime::SimpleMarkerSymbol* m_locationSymbol = nullptr; Esri::ArcGISRuntime::SimpleLineSymbol* m_lineSymbol = nullptr;};
#endif // CREATEKMLMULTITRACK_H// [WriteFile Name=CreateKmlMultiTrack, Category=EditData]// [Legal]// Copyright 2025 Esri.//// Licensed under the Apache License, Version 2.0 (the "License");// you may not use this file except in compliance with the License.// You may obtain a copy of the License at// http://www.apache.org/licenses/LICENSE-2.0//// Unless required by applicable law or agreed to in writing, software// distributed under the License is distributed on an "AS IS" BASIS,// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.// See the License for the specific language governing permissions and// limitations under the License.// [Legal]
import QtQuickimport QtQuick.Controlsimport Esri.Samplesimport QtQuick.Layouts
Item { MapView { id: view width: parent.width height: parent.height * 0.8 Component.onCompleted: { // Set the focus on MapView to initially enable keyboard navigation forceActiveFocus(); } } Rectangle { width: parent.width height: parent.height * 0.2 anchors.top: view.bottom color: palette.base Loader { anchors.fill: parent sourceComponent: multiTrackModel.isShowTracksFromFileEnabled ? trackBrowseOptions : trackSimulationOptions } }
// Track Browse Options Component Component { id: trackSimulationOptions ColumnLayout { anchors.fill: parent Component.onCompleted : multiTrackModel.startNavigation()
// Spacer Item { height: 10 }
Label { visible: multiTrackModel.isRecordingTrack text: multiTrackModel.isRecordingTrack ? qsTr("Recording KML track. Elements added = ") + multiTrackModel.elementsCount : "" font.pixelSize: 18 font.bold: true color: "red" Layout.alignment: Qt.AlignCenter }
Label { text: qsTr("Number of tracks in Multitrack: ") + multiTrackModel.multiTrackCount font.pixelSize: 15 font.bold: true Layout.alignment: Qt.AlignCenter }
RowLayout { spacing: 0 Layout.bottomMargin: 30 ToolButton { Layout.leftMargin: 30 width: 40 height: 40 padding: 0 display: AbstractButton.IconOnly enabled: multiTrackModel.isRecenterButtonEnabled icon { source: "qrc:/Samples/EditData/CreateKmlMultiTrack/point-24.svg" width: 40 height: 40 color: (hovered && enabled) ? palette.buttonText : palette.text } onClicked: { multiTrackModel.recenter() }
background: Rectangle { implicitWidth: 40 implicitHeight: 40 color: (parent.hovered && parent.enabled) ? palette.highlight : palette.base radius: 20 } }
// Spacer Item { Layout.fillWidth: true }
Button { id: startRecordingButton text: multiTrackModel.isRecordingTrack ? qsTr("Stop Recording") : qsTr("Record Track(s)") background: Rectangle { color: palette.button radius: 20 } onClicked: { if (multiTrackModel.isRecordingTrack) { multiTrackModel.stopRecordingKmlTrack(); } else { multiTrackModel.startRecordingKmlTrack(); } } }
// Spacer Item { Layout.fillWidth: true }
ToolButton { Layout.rightMargin: 30 width: 30 height: 30 padding: 0 display: AbstractButton.IconOnly enabled: !multiTrackModel.isRecordingTrack icon { source: "qrc:/Samples/EditData/CreateKmlMultiTrack/save-24.svg" width: 30 height: 30 color: (hovered && enabled) ? palette.buttonText : palette.text } onClicked: { multiTrackModel.exportKmlMultiTrack() }
background: Rectangle { implicitWidth: 30 implicitHeight: 30 color: (parent.hovered && parent.enabled) ? palette.highlight : palette.base radius: 4 } } } } }
// Track Browse Options Component Component { id: trackBrowseOptions ColumnLayout { anchors.fill: parent Component.onCompleted : multiTrackModel.loadLocalKmlFile() Label { width: parent.width text: qsTr("Browse KML Tracks") font.pixelSize: 18 font.bold: true Layout.alignment: Qt.AlignBottom | Qt.AlignHCenter }
RowLayout { Layout.alignment: Qt.AlignTop | Qt.AlignCenter // Dropdown Menu for Tracks ComboBox { id: trackDropdown height: 50 model: multiTrackModel.trackGeometriesCount onCurrentIndexChanged: { multiTrackModel.previewKmlTrack(currentIndex) } }
// Reset Button Button { text: qsTr("Reset") font { pixelSize: 15 bold: true } background: Rectangle { radius: 10 color: palette.button }
onClicked: multiTrackModel.reset() } } } }
// Declare the C++ instance which creates the map etc. and supply the view CreateKmlMultiTrackSample { id: multiTrackModel mapView: view }}// [WriteFile Name=CreateKmlMultiTrack, Category=EditData]// [Legal]// Copyright 2025 Esri.//// Licensed under the Apache License, Version 2.0 (the "License");// you may not use this file except in compliance with the License.// You may obtain a copy of the License at// http://www.apache.org/licenses/LICENSE-2.0//// Unless required by applicable law or agreed to in writing, software// distributed under the License is distributed on an "AS IS" BASIS,// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.// See the License for the specific language governing permissions and// limitations under the License.// [Legal]
// sample headers#include "CreateKmlMultiTrack.h"
// ArcGIS Maps SDK headers#include "ArcGISRuntimeEnvironment.h"
// Qt headers#include <QCommandLineParser>#include <QDir>#include <QGuiApplication>#include <QQmlApplicationEngine>
// Platform specific headers#ifdef Q_OS_WIN#include <Windows.h>#endif
void setAPIKey(const QGuiApplication& app, QString apiKey);
int main(int argc, char* argv[]){ QGuiApplication app(argc, argv); app.setApplicationName(QString("CreateKmlMultiTrack"));
// Use of ArcGIS location services, such as basemap styles, geocoding, and routing services, // requires an access token. For more information see // https://links.esri.com/arcgis-runtime-security-auth.
// The following methods grant an access token:
// 1. User authentication: Grants a temporary access token associated with a user's ArcGIS account. // To generate a token, a user logs in to the app with an ArcGIS account that is part of an // organization in ArcGIS Online or ArcGIS Enterprise.
// 2. API key authentication: Get a long-lived access token that gives your application access to // ArcGIS location services. Go to the tutorial at https://links.esri.com/create-an-api-key. // Copy the API Key access token.
const QString accessToken = QString(""); setAPIKey(app, accessToken);
// Initialize the sample CreateKmlMultiTrack::init();
// Initialize application view QQmlApplicationEngine engine; // Add the import Path engine.addImportPath(QDir(QCoreApplication::applicationDirPath()).filePath("qml"));
#ifdef ARCGIS_RUNTIME_IMPORT_PATH_2 engine.addImportPath(ARCGIS_RUNTIME_IMPORT_PATH_2);#endif
// Set the source engine.load(QUrl("qrc:/Samples/EditData/CreateKmlMultiTrack/main.qml"));
return app.exec();}
// Use of Esri location services, including basemaps and geocoding,// requires authentication using either an ArcGIS identity or an API Key.// 1. ArcGIS identity: An ArcGIS named user account that is a member of an// organization in ArcGIS Online or ArcGIS Enterprise.// 2. API key: API key: a permanent key that grants access to// location services and premium content in your applications.// Visit your ArcGIS Developers Dashboard to create a new// API key or access an existing API key.
void setAPIKey(const QGuiApplication& app, QString apiKey){ if (apiKey.isEmpty()) { // Try parsing API key from command line argument, which uses the following syntax "-k <apiKey>". QCommandLineParser cmdParser; QCommandLineOption apiKeyArgument(QStringList{"k", "api"}, "The API Key property used to access Esri location services", "apiKeyInput"); cmdParser.addOption(apiKeyArgument); cmdParser.process(app);
apiKey = cmdParser.value(apiKeyArgument);
if (apiKey.isEmpty()) { qWarning() << "Use of Esri location services, including basemaps, requires" << "you to authenticate with an ArcGIS identity or set the API Key property."; return; } }
Esri::ArcGISRuntime::ArcGISRuntimeEnvironment::setApiKey(apiKey);}// Copyright 2025 Esri.
// Licensed under the Apache License, Version 2.0 (the "License");// you may not use this file except in compliance with the License.// You may obtain a copy of the License at// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software// distributed under the License is distributed on an "AS IS" BASIS,// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.// See the License for the specific language governing permissions and// limitations under the License.
import QtQuick.Controlsimport Esri.Samples
ApplicationWindow { visible: true width: 800 height: 600
CreateKmlMultiTrack { anchors.fill: parent }}