Display maps and use locators to enable search and routing offline using a Mobile Map Package.

Use case
Mobile map packages make it easy to transmit and store the necessary components for an offline map experience including: transportation networks (for routing/navigation), locators (address search, forward and reverse geocoding), and maps.
A field worker might download a mobile map package to support their operations while working offline.
How to use the sample
A list of maps from a mobile map package will be displayed. If the map contains transportation networks, the list item will have a navigation icon. Click on a map in the list to open it. If a locator task is available, click on the map to place a point. Click it again to reverse geocode the location’s address. If transportation networks are available, click the route icon in the top right corner a route will be calculated between geocode locations.
How it works
- Create a
MobileMapPackagepassing in the path to the constructor. - Get a list model of maps inside the package using the
mapsproperty. - If the package has a locator, access it using the
LocatorTaskproperty. - To see if a map contains transportation networks, check each map’s
TransportationNetworksproperty.
Relevant API
- GeocodeResult
- MobileMapPackage
- ReverseGeocodeParameters
- Route
- RouteParameters
- RouteResult
- RouteTask
- TransportationNetworkDataset
Offline data
Read more about how to set up the sample’s offline data here.
| Link | Local Location |
|---|---|
| Yellowstone mmpk File | <userhome>/ArcGIS/Runtime/Data/mmpk/Yellowstone.mmpk |
| SanFrancisco mmpk File | <userhome>/ArcGIS/Runtime/Data/mmpk/SanFrancisco.mmpk |
Tags
disconnected, field mobility, geocode, network, network analysis, offline, routing, search, transportation
Sample Code
// [WriteFile Name=MobileMap_SearchAndRoute, Category=Maps]// [Legal]// Copyright 2016 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 "MobileMap_SearchAndRoute.h"
// ArcGIS Maps SDK headers#include "AttributeListModel.h"#include "CalloutData.h"#include "Error.h"#include "GeocodeResult.h"#include "Graphic.h"#include "GraphicListModel.h"#include "GraphicsOverlay.h"#include "GraphicsOverlayListModel.h"#include "IdentifyGraphicsOverlayResult.h"#include "Item.h"#include "LocatorTask.h"#include "Map.h"#include "MapQuickView.h"#include "MapTypes.h"#include "MapViewTypes.h"#include "MobileMapPackage.h"#include "PictureMarkerSymbol.h"#include "Polyline.h"#include "ReverseGeocodeParameters.h"#include "Route.h"#include "RouteParameters.h"#include "RouteResult.h"#include "RouteTask.h"#include "SimpleLineSymbol.h"#include "SimpleRenderer.h"#include "Stop.h"#include "SymbolTypes.h"#include "TextSymbol.h"
// Qt headers#include <QDir>#include <QFile>#include <QFileInfoList>#include <QFuture>#include <QStandardPaths>#include <QUuid>#include <QtCore/qglobal.h>
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;}} // namespace
MobileMap_SearchAndRoute::MobileMap_SearchAndRoute(QQuickItem* parent): QQuickItem(parent), m_selectedMmpkIndex(0), m_canRoute(false), m_canClear(false), m_isGeocodeInProgress(false), m_dataPath(defaultDataPath() + "/ArcGIS/Runtime/Data/mmpk"), m_fileInfoList(QDir(m_dataPath).entryInfoList()){}
MobileMap_SearchAndRoute::~MobileMap_SearchAndRoute() = default;
void MobileMap_SearchAndRoute::init(){ qmlRegisterType<MapQuickView>("Esri.Samples", 1, 0, "MapView"); qmlRegisterType<MobileMap_SearchAndRoute>("Esri.Samples", 1, 0, "MobileMap_SearchAndRouteSample"); qmlRegisterUncreatableType<CalloutData>("Esri.Samples", 1, 0, "CalloutData", "CalloutData is an uncreatable type");}
void MobileMap_SearchAndRoute::componentComplete(){ QQuickItem::componentComplete();
// find QML MapView component m_mapView = findChild<MapQuickView*>("mapView"); m_mapView->setWrapAroundMode(WrapAroundMode::Disabled);
// initialize Callout m_mapView->calloutData()->setTitle("Address");
// set reverse geocoding parameters m_reverseGeocodeParameters.setMaxResults(1);
// identify and create MobileMapPackages using mmpk files in datapath createMobileMapPackages(0);
// create graphics overlays to visually display geocoding and routing results m_stopsGraphicsOverlay = new GraphicsOverlay(this); m_routeGraphicsOverlay = new GraphicsOverlay(this); m_routeGraphicsOverlay->setRenderer(new SimpleRenderer(new SimpleLineSymbol(SimpleLineSymbolStyle::Solid, QColor("#2196F3"), 4, this), this));
m_mapView->graphicsOverlays()->append(m_routeGraphicsOverlay); m_mapView->graphicsOverlays()->append(m_stopsGraphicsOverlay);
// create a pin symbol m_bluePinSymbol = new PictureMarkerSymbol(QUrl("qrc:/Samples/Maps/MobileMap_SearchAndRoute/bluePinSymbol.png"), this); m_bluePinSymbol->setHeight(36); m_bluePinSymbol->setWidth(36); m_bluePinSymbol->setOffsetY(m_bluePinSymbol->height() / 2);
connectSignals();}
void MobileMap_SearchAndRoute::createMobileMapPackages(int index){ if (index < m_fileInfoList.length()) { // check if file is a .mmpk file if (m_fileInfoList[index].completeSuffix() == "mmpk") { // create a new MobileMapPackage MobileMapPackage* mobileMapPackage = new MobileMapPackage(m_fileInfoList[index].absoluteFilePath(), this);
// once MMPK is finished loading, add it and its information to lists connect(mobileMapPackage, &MobileMapPackage::doneLoading, this, [mobileMapPackage, this](const Error& error) { if (error.isEmpty()) { // QList of MobileMapPackages m_mobileMapPackages.append(mobileMapPackage);
// QStringList of MobileMapPackage names. Used as a ListModel in QML m_mobileMapPackageList << mobileMapPackage->item()->title(); emit mmpkListChanged(); } });
// load the new MMPK mobileMapPackage->load(); }
createMobileMapPackages(++index); } else return;}
void MobileMap_SearchAndRoute::connectSignals(){ connect(m_mapView, &MapQuickView::mouseClicked, this, [this](QMouseEvent& mouseEvent) { if (!m_currentLocatorTask) return;\ m_clickedPoint = Point(m_mapView->screenToLocation(mouseEvent.position().x(), mouseEvent.position().y()));
// determine if user clicked on a graphic m_mapView->identifyGraphicsOverlayAsync(m_stopsGraphicsOverlay, mouseEvent.position(), 5, false, 2).then(this, [this](const IdentifyGraphicsOverlayResult* identifyResult) { if (!identifyResult) return;
// get graphics list QList<Graphic*> graphics = identifyResult->graphics(); if (!graphics.isEmpty()) { // use the blue pin graphic instead of text graphic to as calloutData's geoElement Graphic* graphic = graphics[0]; if (graphic->symbol()->symbolType() != SymbolType::PictureMarkerSymbol && graphics.count() > 1) graphic = graphics[1];
m_mapView->calloutData()->setGeoElement(graphic); m_mapView->calloutData()->setDetail(graphic->attributes()->attributeValue("AddressLabel").toString()); m_mapView->calloutData()->setVisible(true); } // if clicked a point with no graphic on it, reverse geocode else { m_currentLocatorTask->reverseGeocodeWithParametersAsync(m_clickedPoint, m_reverseGeocodeParameters).then(this, [this](const QList<GeocodeResult>& geocodeResults) { // make busy indicator invisible m_isGeocodeInProgress = false; emit isGeocodeInProgressChanged();
if (geocodeResults.isEmpty()) return;
// create parent for the graphic if (!m_stopGraphicParent) m_stopGraphicParent = new QObject(this);
// create a blue pin graphic to display location Graphic* bluePinGraphic = new Graphic(geocodeResults[0].displayLocation(), m_bluePinSymbol, m_stopGraphicParent); bluePinGraphic->attributes()->insertAttribute("AddressLabel", geocodeResults[0].label());
m_stopsGraphicsOverlay->graphics()->append(bluePinGraphic);
// make clear graphics overlay button visible m_canClear = true; emit canClearChanged();
// if routing is not enabled in map, return if (!m_currentRouteTask) return;
//Set up the Stops
// create a stop based on added graphic m_stops << Stop(geometry_cast<Point>(bluePinGraphic->geometry()));
// create a Text Symbol to display stop number TextSymbol* textSymbol = new TextSymbol(m_stopGraphicParent); textSymbol->setText(QString::number(m_stops.count())); textSymbol->setColor(QColor("white")); textSymbol->setSize(18); textSymbol->setOffsetY(m_bluePinSymbol->height() / 2);
// create a Graphic using the textSymbol Graphic* stopNumberGraphic = new Graphic(bluePinGraphic->geometry(), textSymbol, m_stopGraphicParent); stopNumberGraphic->setZIndex(bluePinGraphic->zIndex() + 1); m_stopsGraphicsOverlay->graphics()->append(stopNumberGraphic);
if (m_stops.count() > 1) { m_canRoute = true; emit canRouteChanged(); } }); m_isGeocodeInProgress = true; emit isGeocodeInProgressChanged(); } }); });}
void MobileMap_SearchAndRoute::resetMapView(){ // dismiss mapView controls m_canClear = false; emit canClearChanged(); m_canRoute = false; emit canRouteChanged();
// dimiss callout m_mapView->calloutData()->setVisible(false);
// clear the graphics overlays and stops m_stopsGraphicsOverlay->graphics()->clear(); if (m_stopGraphicParent) { delete m_stopGraphicParent; m_stopGraphicParent = nullptr; } m_routeGraphicsOverlay->graphics()->clear(); if (m_routeGraphicParent) { delete m_routeGraphicParent; m_routeGraphicParent = nullptr; } m_stops.clear();}
void MobileMap_SearchAndRoute::createMapList(int index){ m_mapList.clear(); m_selectedMmpkIndex = index;
int counter = 1;
const auto maps = m_mobileMapPackages[index]->maps(); for (const Map* map : maps) { QVariantMap mapList; mapList["name"] = map->item()->title() + " " + QString::number(counter); mapList["geocoding"] = m_mobileMapPackages[index]->locatorTask() != nullptr; mapList["routing"] = map->transportationNetworks().count() > 0;
m_mapList << mapList; ++counter; }
emit mapListChanged();}
void MobileMap_SearchAndRoute::selectMap(int index){ resetMapView();
// set the locatorTask //! [MobileMap_SearchAndRoute create LocatorTask] m_currentLocatorTask = m_mobileMapPackages[m_selectedMmpkIndex]->locatorTask(); //! [MobileMap_SearchAndRoute create LocatorTask]
// set the MapView m_mapView->setMap(m_mobileMapPackages[m_selectedMmpkIndex]->maps().at(index));
// create a RouteTask with selected map's transportation network if available if (m_mobileMapPackages[m_selectedMmpkIndex]->maps().at(index)->transportationNetworks().count() > 0) { m_currentRouteTask = new RouteTask(m_mobileMapPackages[m_selectedMmpkIndex]->maps().at(index)->transportationNetworks().at(0), this); m_currentRouteTask->load();
// create default parameters after the RouteTask is loaded connect(m_currentRouteTask, &RouteTask::loadStatusChanged, this, [this](LoadStatus loadStatus) { if (loadStatus == LoadStatus::Loaded) m_currentRouteTask->createDefaultParametersAsync().then(this, [this](const RouteParameters& routeParameters) { m_currentRouteParameters = routeParameters; }); }); } else m_currentRouteTask = nullptr;}
void MobileMap_SearchAndRoute::solveRoute(){ // clear previously displayed routes m_routeGraphicsOverlay->graphics()->clear(); if (m_routeGraphicParent) { delete m_routeGraphicParent; m_routeGraphicParent = nullptr; }
// set stops and solve route m_currentRouteParameters.setStops(m_stops); // create a graphic using the RouteResult m_currentRouteTask->solveRouteAsync(m_currentRouteParameters).then(this, [this](const RouteResult& routeResult) { if (!m_routeGraphicParent) m_routeGraphicParent = new QObject(this);
if (!routeResult.isEmpty()) { const auto routes = routeResult.routes(); Graphic* routeGraphic = new Graphic(routes[0].routeGeometry(), m_routeGraphicParent); m_routeGraphicsOverlay->graphics()->append(routeGraphic); } });}
QStringList MobileMap_SearchAndRoute::mmpkList() const{ return m_mobileMapPackageList;}
QVariantList MobileMap_SearchAndRoute::mapList() const{ return m_mapList;}
bool MobileMap_SearchAndRoute::isGeocodeInProgress() const{ return m_isGeocodeInProgress;}
bool MobileMap_SearchAndRoute::canRoute() const{ return m_canRoute;}
bool MobileMap_SearchAndRoute::canClear() const{ return m_canClear;}// [WriteFile Name=MobileMap_SearchAndRoute, Category=Maps]// [Legal]// Copyright 2016 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 MOBILEMAP_SEARCHANDROUTE_H#define MOBILEMAP_SEARCHANDROUTE_H
// ArcGIS Maps SDK headers#include "Point.h"#include "ReverseGeocodeParameters.h"#include "RouteParameters.h"#include "Stop.h"
// Qt headers#include <QFileInfoList>#include <QQuickItem>#include <QVariantMap>
namespace Esri::ArcGISRuntime{ class Map; class RouteTask; class LocatorTask; class MapQuickView; class GraphicsOverlay; class MobileMapPackage; class PictureMarkerSymbol; class ReverseGeocodeParameters;}
class MobileMap_SearchAndRoute : public QQuickItem{ Q_OBJECT
Q_PROPERTY(bool canRoute READ canRoute NOTIFY canRouteChanged) Q_PROPERTY(bool canClear READ canClear NOTIFY canClearChanged) Q_PROPERTY(bool isGeocodeInProgress READ isGeocodeInProgress NOTIFY isGeocodeInProgressChanged) Q_PROPERTY(QStringList mmpkList READ mmpkList NOTIFY mmpkListChanged) Q_PROPERTY(QVariantList mapList READ mapList NOTIFY mapListChanged)
public: explicit MobileMap_SearchAndRoute(QQuickItem* parent = nullptr); ~MobileMap_SearchAndRoute() override;
void componentComplete() override; static void init(); Q_INVOKABLE void resetMapView(); Q_INVOKABLE void createMapList(int index); Q_INVOKABLE void selectMap(int index); Q_INVOKABLE void solveRoute();
signals: void mmpkListChanged(); void mapListChanged(); void canClearChanged(); void canRouteChanged(); void isGeocodeInProgressChanged();
private: void connectSignals(); bool canRoute() const; bool canClear() const; void createMobileMapPackages(int index); QStringList mmpkList() const; QVariantList mapList() const; bool isGeocodeInProgress() const;
private: int m_selectedMmpkIndex = 0; bool m_canRoute = false; bool m_canClear = false; bool m_isGeocodeInProgress = false; QString m_dataPath; QFileInfoList m_fileInfoList; QStringList m_mobileMapPackageList; QVariantList m_mapList; Esri::ArcGISRuntime::Point m_clickedPoint; Esri::ArcGISRuntime::RouteParameters m_currentRouteParameters; Esri::ArcGISRuntime::ReverseGeocodeParameters m_reverseGeocodeParameters; QList<Esri::ArcGISRuntime::Stop> m_stops; QList<Esri::ArcGISRuntime::MobileMapPackage*> m_mobileMapPackages; Esri::ArcGISRuntime::Map* m_map = nullptr; Esri::ArcGISRuntime::MapQuickView* m_mapView = nullptr; Esri::ArcGISRuntime::MobileMapPackage* m_mobileMap = nullptr; Esri::ArcGISRuntime::LocatorTask* m_currentLocatorTask = nullptr; Esri::ArcGISRuntime::PictureMarkerSymbol* m_bluePinSymbol = nullptr; Esri::ArcGISRuntime::RouteTask* m_currentRouteTask = nullptr; Esri::ArcGISRuntime::GraphicsOverlay* m_stopsGraphicsOverlay = nullptr; Esri::ArcGISRuntime::GraphicsOverlay* m_routeGraphicsOverlay = nullptr; QObject* m_stopGraphicParent = nullptr; QObject* m_routeGraphicParent = nullptr;};
#endif // MOBILEMAP_SEARCHANDROUTE_H// [WriteFile Name=MobileMap_SearchAndRoute, Category=Maps]// [Legal]// Copyright 2016 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 Esri.ArcGISRuntime.Toolkit
MobileMap_SearchAndRouteSample { id: mobileMapSearchRoute clip: true width: 800 height: 600
property bool isMapOpen: false
// make background a light gray Rectangle { anchors.fill: parent color: "#E0E0E0"
// add a mapView component MapView { id: mapView objectName: "mapView"
Component.onCompleted: { // Set the focus on MapView to initially enable keyboard navigation forceActiveFocus(); }
// callout to display information Callout { calloutData: mapView.calloutData screenOffsetY: -19 accessoryButtonVisible: false leaderPosition: Callout.LeaderPosition.Automatic }
Rectangle { anchors { left: parent.left top: parent.top } opacity: 0.50 height: parent.height width: 25 color: "#E0E0E0"
Rectangle { anchors { left: parent.left top: parent.top } width: parent.width height: 100 color: "#283593"
Image { anchors.centerIn: parent mirror: true source: "qrc:/Samples/Maps/MobileMap_SearchAndRoute/forwardIcon.png" height: 33 width: height } }
MouseArea { anchors.fill: parent onClicked: { mapSelectionStack.pop(); } } }
// Map controls Column { anchors { top: parent.top right: parent.right margins: 10 } spacing: 10
// solve route button Rectangle { id: routeButton color: "#E0E0E0" height: 50 width: height border.color: "black" radius: 2 opacity: 0.90 visible: mobileMapSearchRoute.canRoute
Image { anchors { centerIn: parent margins: 5 } source: "qrc:/Samples/Maps/MobileMap_SearchAndRoute/routingSymbol.png" height: 44 width: height }
MouseArea { anchors.fill: parent onClicked: { mobileMapSearchRoute.solveRoute(); } } }
// clear graphics button Rectangle { id: clearButton color: "#E0E0E0" height: 50 width: height border.color: "black" radius: 2 opacity: 0.90 visible: mobileMapSearchRoute.canClear
Image { anchors { centerIn: parent margins: 5 } source: "qrc:/Samples/Maps/MobileMap_SearchAndRoute/discardSymbol.png" height: 44 width: height }
MouseArea { anchors.fill: parent onClicked: { mobileMapSearchRoute.resetMapView(); } } } } }
// use a StackView for the user interface StackView { id: mapSelectionStack anchors.fill: parent
// begin with the mobile map package selection options initialItem: Item {
Column { anchors { top: parent.top left: parent.left } width: parent.width spacing: 20
// UI navigation bar Rectangle { width: parent.width height: 100 color: "#283593"
// forward navigation button. Visible after first map is selected Image { anchors { verticalCenter: parent.verticalCenter right: parent.right margins: 10 } source: "qrc:/Samples/Maps/MobileMap_SearchAndRoute/forwardIcon.png" height: 44 width: height visible: isMapOpen
MouseArea { anchors.fill: parent onClicked: { mapSelectionStack.push(mapSelectView); } } }
Text { anchors.centerIn: parent color: "white" height: 40 font.pixelSize: 25 text: "Choose a Mobile Map Package" } }
// mobile map package ListView ListView { anchors.horizontalCenter: parent.horizontalCenter height: 400 width: 200 spacing: 10 model: mobileMapSearchRoute.mmpkList
delegate: Component { Rectangle {
width: 200 height: 50 color: "#283593" radius: 2 border.color: "darkgray"
Text { anchors.centerIn: parent horizontalAlignment: Text.AlignHCenter color: "white" width: 150 text: modelData elide: Text.ElideMiddle }
MouseArea { anchors.fill: parent propagateComposedEvents: false onClicked: { isMapOpen = false;
//generate list of maps and go to map selection view mobileMapSearchRoute.createMapList(index); mapSelectionStack.push(mapSelectView); } } } } } } }
Item { id: mapSelectView
Column { anchors { top: parent.top left: parent.left } width: parent.width spacing: 20
// UI navigation bar Rectangle { width: parent.width height: 100 color: "#283593"
// back button Image { anchors { verticalCenter: parent.verticalCenter left: parent.left margins: 10 } mirror: true source: "qrc:/Samples/Maps/MobileMap_SearchAndRoute/forwardIcon.png" height: 44 width: height
MouseArea { anchors.fill: parent onClicked: { mapSelectionStack.pop(); } } }
// forward button. Only visible after first map has been selected Image { anchors { verticalCenter: parent.verticalCenter right: parent.right margins: 10 } source: "qrc:/Samples/Maps/MobileMap_SearchAndRoute/forwardIcon.png" height: 44 width: height visible: isMapOpen
MouseArea { anchors.fill: parent onClicked: { mapSelectionStack.push(mapView); } } }
Text { anchors.centerIn: parent color: "white" height: 40 font.pixelSize: 25 text: "Choose a Map" } }
// list of maps ListView { anchors.horizontalCenter: parent.horizontalCenter height: 400 width: 200 spacing: 10 model: mobileMapSearchRoute.mapList
delegate: Component { Rectangle { width: 200 height: 50 color: "#283593" radius: 2 border.color: "darkgray"
Text { anchors.centerIn: parent horizontalAlignment: Text.AlignHCenter color: "white" width: 150 text: modelData.name elide: Text.ElideMiddle }
// geocoding available icon Image { anchors { left: parent.left top: parent.top margins: 5 } source: "qrc:/Samples/Maps/MobileMap_SearchAndRoute/pinOutlineSymbol.png" height: 20 width: height visible: modelData.geocoding }
// routing available icon Image { anchors { right: parent.right top: parent.top margins: 5 } source: "qrc:/Samples/Maps/MobileMap_SearchAndRoute/routingSymbol.png" height: 20 width: height visible: modelData.routing }
MouseArea { anchors.fill: parent propagateComposedEvents: false onClicked: { // set map and display mapView mobileMapSearchRoute.selectMap(index); isMapOpen = true; mapSelectionStack.push(mapView); } } } } } } } }
BusyIndicator { anchors.centerIn: parent visible: mobileMapSearchRoute.isGeocodeInProgress } }}// [Legal]// Copyright 2015 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 "MobileMap_SearchAndRoute.h"
// ArcGIS Maps SDK headers#include "ArcGISRuntimeEnvironment.h"
// Qt headers#include <QCommandLineParser>#include <QDir>#include <QGuiApplication>#include <QQmlEngine>#include <QQuickView>
// Other headers#include "Esri/ArcGISRuntime/Toolkit/register.h"
// Platform specific headers#ifdef Q_OS_WIN#include <Windows.h>#endif
#define STRINGIZE(x) #x#define QUOTE(x) STRINGIZE(x)
int main(int argc, char *argv[]){ Esri::ArcGISRuntime::ArcGISRuntimeEnvironment::setUseLegacyAuthentication(false); QGuiApplication app(argc, argv); app.setApplicationName(QString("MobileMap_SearchAndRoute"));
// 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("");
if (accessToken.isEmpty()) { qWarning() << "Use of ArcGIS location services, such as the basemap styles service, requires" << "you to authenticate with an ArcGIS account or set the API Key property."; } else { Esri::ArcGISRuntime::ArcGISRuntimeEnvironment::setApiKey(accessToken); }
// Initialize the sample MobileMap_SearchAndRoute::init();
// Initialize application view QQuickView view; view.setResizeMode(QQuickView::SizeRootObjectToView);
// Add the import Path view.engine()->addImportPath(QDir(QCoreApplication::applicationDirPath()).filePath("qml"));
QString arcGISRuntimeImportPath = QUOTE(ARCGIS_RUNTIME_IMPORT_PATH);
#if defined(LINUX_PLATFORM_REPLACEMENT) // on some linux platforms the string 'linux' is replaced with 1 // fix the replacement paths which were created QString replaceString = QUOTE(LINUX_PLATFORM_REPLACEMENT); arcGISRuntimeImportPath = arcGISRuntimeImportPath.replace(replaceString, "linux", Qt::CaseSensitive); #endif
// Add the Runtime and Extras path view.engine()->addImportPath(arcGISRuntimeImportPath);
Esri::ArcGISRuntime::Toolkit::registerComponents(*(view.engine()));
// Set the source view.setSource(QUrl("qrc:/Samples/Maps/MobileMap_SearchAndRoute/MobileMap_SearchAndRoute.qml"));
view.show();
return app.exec();}