View on GitHub Sample viewer app
Create and share a mobile geodatabase.
Use case
A mobile geodatabase is a collection of various types of GIS datasets contained in a single file (.geodatabase) on disk that can store, query, and manage spatial and nonspatial data. Mobile geodatabases are stored in a SQLite database and can contain up to 2 TB of portable data. Users can create, edit and share mobile geodatabases across ArcGIS Pro, ArcGIS Maps SDK for Native Apps, or any SQL software. These mobile geodatabases support both viewing and editing and enable new offline editing workflows that donât require a feature service.
For example, a user would like to track the location of their device at various intervals to generate a heat map of the most visited locations. The user can add each location as a feature to a table and generate a mobile geodatabase. The user can then instantly share the mobile geodatabase to ArcGIS Pro to generate a heat map using the recorded locations stored as a geodatabase feature table.
How to use the sampleSelect "Create new .geodatabase" to create a new mobile geodatabase in a temporary directory. Click or tap on the map to add features to the mobile geodatabase. Select "View feature table" to view the contents of the geodatabase feature table. Select "Clear features" to remove all features from the geodatabase feature table. Select "Close .geodatabase" to save and close the geodatabase so it is ready to be shared or uploaded to ArcGIS Online.
How it worksGeodatabase
at a given path that does not already exist with the Geodatabase::createAsync()
static method.TableDescription
and add a list of FieldDescription
s to the table description.GeodatabaseFeatureTable
from the geodatabase with the TableDescription
using Geodatabase::createTableAsync(TableDescription* tableDescription)
.ArcGISFeature
on a selected map point using FeatureTable::createFeature(const QVariantMap &attributes, const Geometry& geometry, QObject* parent = nullptr)
.FeatureTable::addFeatureAsync(Feature* feature)
Geodatabase::close()
Learn more about mobile geodatabases and how to utilize them on the Mobile geodatabases page. The following mobile geodatabase behaviors are supported in ArcGIS Maps SDK for Native Apps: annotation, attachments, attribute rules, contingent values, dimensions, domains, feature-linked annotation, subtypes, utility network and relationship classes.
Visit ArcGIS field data types to learn more about the types of fields supported.
arcgis pro, database, feature, feature table, geodatabase, mobile geodatabase, sqlite
Sample CodeCreateMobileGeodatabase.cpp CreateMobileGeodatabase.cpp CreateMobileGeodatabase.h FeatureListModel.cpp FeatureListModel.h CreateMobileGeodatabase.qml
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
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
// [WriteFile Name=CreateMobileGeodatabase, Category=Features]
// [Legal]
// Copyright 2022 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 "CreateMobileGeodatabase.h"
#include "FeatureListModel.h"
// ArcGIS Maps SDK headers
#include "FeatureIterator.h"
#include "FeatureLayer.h"
#include "FeatureQueryResult.h"
#include "FieldDescription.h"
#include "FieldDescriptionListModel.h"
#include "Geodatabase.h"
#include "GeodatabaseFeatureTable.h"
#include "GeometryTypes.h"
#include "LayerListModel.h"
#include "Map.h"
#include "MapQuickView.h"
#include "MapTypes.h"
#include "Point.h"
#include "QueryParameters.h"
#include "ServiceTypes.h"
#include "SpatialReference.h"
#include "TableDescription.h"
#include "Viewpoint.h"
// Qt headers
#include <QFuture>
using namespace Esri::ArcGISRuntime;
CreateMobileGeodatabase::CreateMobileGeodatabase(QObject* parent /* = nullptr */):
QObject(parent),
m_map(new Map(BasemapStyle::ArcGISTopographic, this))
{
// The FeatureListModel is a helper class created specifically for this sample to display all features in the table view
m_featureListModel = new FeatureListModel(this);
}
CreateMobileGeodatabase::~CreateMobileGeodatabase() = default;
void CreateMobileGeodatabase::init()
{
// Register the map view for QML
qmlRegisterType<MapQuickView>("Esri.Samples", 1, 0, "MapView");
qmlRegisterType<CreateMobileGeodatabase>("Esri.Samples", 1, 0, "CreateMobileGeodatabaseSample");
}
MapQuickView* CreateMobileGeodatabase::mapView() const
{
return m_mapView;
}
// Set the view (created in QML)
void CreateMobileGeodatabase::setMapView(MapQuickView* mapView)
{
if (!mapView || mapView == m_mapView)
return;
m_mapView = mapView;
m_mapView->setMap(m_map);
m_mapView->setViewpointAsync(Viewpoint(39.3238, -77.7332, 10'000));
connect(m_mapView, &MapQuickView::mouseClicked, this, &CreateMobileGeodatabase::addFeature);
emit mapViewChanged();
}
// Create a Geodatabase in an empty directory
void CreateMobileGeodatabase::createGeodatabase()
{
m_gdbFilePath = QString{m_tempDir.path() + "/LocationHistory_%1.geodatabase"}.arg(QDateTime::currentSecsSinceEpoch() % 1000);
emit gdbFilePathChanged();
// We cannot overwrite an existing geodatabase
if (QFile::exists(m_gdbFilePath))
return;
// Use static Geodatabase::createAsync with an empty file path
Geodatabase::createAsync(m_gdbFilePath, this).then(this, [this](Geodatabase* geodatabase)
{
m_gdb = geodatabase;
createTable();
});
}
// Create a GeodatabaseFeatureTable from the new Geodatabase with a TableDescription
void CreateMobileGeodatabase::createTable()
{
m_gdbOpen = true;
emit gdbOpenChanged();
// Create a TableDescription to define the GeodatabaseFeatureTable's attributes and fields
TableDescription* tableDescription = new TableDescription("LocationHistory", SpatialReference::wgs84(), GeometryType::Point, this);
tableDescription->setHasAttachments(false);
tableDescription->setHasM(false);
tableDescription->setHasZ(false);
tableDescription->fieldDescriptions()->append(new FieldDescription("oid", FieldType::OID));
tableDescription->fieldDescriptions()->append(new FieldDescription("collection_timestamp", FieldType::Date));
m_gdb->createTableAsync(tableDescription, this).then(this, [this](GeodatabaseFeatureTable* gdbFeatureTableResult)
{
m_featureTable = gdbFeatureTableResult;
FeatureLayer* featureLayer = new FeatureLayer(m_featureTable, this);
m_map->operationalLayers()->append(featureLayer);
});
}
// Close the Geodatabase so that it can be safely shared
void CreateMobileGeodatabase::closeGdb()
{
if (!m_gdb)
return;
m_gdb->close();
m_gdbOpen = false;
m_map->operationalLayers()->clear();
m_featureListModel->clear();
m_featureCount = 0;
emit gdbOpenChanged();
emit featureCountChanged();
}
void CreateMobileGeodatabase::addFeature(QMouseEvent& mouseEvent)
{
if (!m_featureTable)
return;
const Point mousePoint = m_mapView->screenToLocation(mouseEvent.position().x(), mouseEvent.position().y());
QVariantMap attributes = {};
attributes.insert("collection_timestamp", QDateTime::currentDateTime());
Feature* feature = m_featureTable->createFeature(attributes, mousePoint, this);
m_featureTable->addFeatureAsync(feature).then(this, [this, feature]()
{
m_featureListModel->addFeature(feature);
emit featureListModelChanged();
m_featureCount = static_cast<int>(m_featureTable->numberOfFeatures());
emit featureCountChanged();
});
}
void CreateMobileGeodatabase::deleteFeatures()
{
QueryParameters params;
params.setWhereClause("1=1");
m_featureTable->queryFeaturesAsync(params).then(this, [this](FeatureQueryResult* rawQueryResult)
{
// Cast the FeatureQueryResult to a unique pointer to delete it when it goes out of scope
auto queryResults = std::unique_ptr<FeatureQueryResult>(rawQueryResult);
FeatureIterator resultIterator = queryResults->iterator();
auto deleteFeaturesFuture = m_featureTable->deleteFeaturesAsync(resultIterator.features());
Q_UNUSED(deleteFeaturesFuture)
m_featureCount = 0;
emit featureCountChanged();
});
}
void CreateMobileGeodatabase::clearFeatures()
{
if (m_featureTable->numberOfFeatures() > 0)
deleteFeatures();
m_featureListModel->clear();
}
FeatureListModel* CreateMobileGeodatabase::featureListModel() const
{
return m_featureListModel;
}
QString CreateMobileGeodatabase::gdbFilePath() const
{
return m_gdbFilePath;
}
int CreateMobileGeodatabase::featureCount() const
{
return m_featureCount;
}
bool CreateMobileGeodatabase::gdbOpen() const
{
return m_gdbOpen;
}
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4