Greetings!
Working on my first Qt app but have not been able to get past the first basic steps. For the app I have a feature service with two layers, layer 0 is for device location (points) and layer 1 is for service areas (polygons). I want to sync service areas from the server to the device (SyncDirectionDownload) and sync device location from the device to the server (SyncDirectionUpload ). I am expecting upon initial sync to the geodatabase, the service areas should be downloaded to the device's geodatabase, but this is not the case. I have tried a few different ways but either no features are downloaded or there are errors. Any input on what I am doing wrong or if I need to go about this a different way is greatly appreciated!
Thanks,
Josh
Each step is connected to separate buttons. Here is the output for each button:
getServiceButton:
(onFeatureServiceInfoStatusChanged): qml: capabilities: Create,Delete,Query,Sync,Update,Uploads,Editing
(onFeatureServiceInfoStatusChanged): qml: max record count: 1000
(onFeatureServiceInfoStatusChanged): qml: sync enabled?: true
(onFeatureServiceInfoStatusChanged): qml: server version: 10.41
generateButton:
(onClicked): qml: Generating geodatabase...
(onGenerateStatusChanged): qml: Generate geodatabase in progress...
(onGeodatabaseSyncStatusInfoChanged): qml: Sync status: 0
(onGenerateStatusChanged): qml: Generate geodatabase complete.
(onGenerateStatusChanged): qml: path: data/localdata.geodatabase
(onGenerateStatusChanged): qml: sync enabled: true
(onGenerateStatusChanged): qml: sync model: 1
(onGenerateStatusChanged): qml: valid: true
registerButton: not sure if this is functioning properly
(onClicked): qml: Registering geodatabase...
(onGeodatabaseSyncStatusInfoChanged): qml: Sync status: 0
syncButton: will error
(onClicked): qml: Syncing geodatabase...
(onSyncStatusChanged): qml: Sync geodatabase in progress...
(onSyncStatusChanged): qml: Error: Invalid or missing input parameters. code= 400 Replica with this GUID does not exist on the server
(onGeodatabaseSyncStatusInfoChanged): qml: Sync status: 0
(onSyncStatusChanged): qml: Error: Protocol "" is unknown code= 301 Protocol "" is unknown
(onGeodatabaseSyncStatusInfoChanged): qml: Sync status: 0
(onSyncStatusChanged): qml: Error: Protocol "" is unknown code= 301 Protocol "" is unknown
(onGeodatabaseSyncStatusInfoChanged): qml: Sync status: 0
(onSyncStatusChanged): qml: Error: Sync failed. Unable to import changes to server. code= -1
Info from the feature server:
Sync Capabilities:
Supports Registering Existing Data: true
Supports Sync Direction Control: true
Supports PerLayer Sync: true
Supports PerReplica Sync: false
Supports RollbackOnFailure : false
Supports Async: true
Supports ApplyEdits With Global Ids: true
Child Resources: Info Uploads Replicas
Supported Operations: Query Apply Edits Create Replica Synchronize Replica Unregister Replica
The code snippet below is what I believe is the closest to what I need (my apologies on the formatting from copy/paste), but it will error when trying to sync.
import QtQuick 2.3
import QtQuick.Controls 1.2
import QtPositioning 5.2
import QtQuick.Dialogs 1.2
import QtQuick.Layouts 1.1
import QtQuick.Controls.Styles 1.2
import ArcGIS.Runtime 10.26
ApplicationWindow {
id: appWindow
width: 800
height: 600
title: "my cool app"
property string featureServerUrl: // ** url left out on purpose**
property string gdbPath: "data/localdata.geodatabase"
Envelope {
id: env
xMin: -100
xMax: -85
yMin: 40
yMax: 50
}
SpatialReference{
id: sr
wkid: 4326
}
ServiceInfoTask {
id: featureServiceInfoTask
url: featureServerUrl
onFeatureServiceInfoStatusChanged: {
if (featureServiceInfoStatus === Enums.FeatureServiceInfoStatusReady) {
console.log("Fetch feature server info ready...")
}
else if (featureServiceInfoStatus === Enums.FeatureServiceInfoStatusInProgress) {
console.log("Fetch feature server info in progress...")
}
else if (featureServiceInfoStatus === Enums.FeatureServiceInfoStatusCompleted) {
Enums.FeatureServiceInfoStatusErrored
Enums.FeatureServiceInfoStatusInProgress
Enums.FeatureServiceInfoStatusReady
var featureServiceInfo = featureServiceInfoTask.featureServiceInfo
console.log("capabilities:", featureServiceInfo.capabilities)
console.log("max record count:",
featureServiceInfo.maximumRecordCount)
console.log("sync enabled?:", featureServiceInfo.isSyncEnabled)
console.log("server version:", featureServiceInfo.version)
}
else if (featureServiceInfoStatus === Enums.FeatureServiceInfoStatusErrored) {
console.log("Fetch feature server info ERRORED...")
}
}
}
GenerateGeodatabaseParameters {
id: generateGeodatabaseParameters
extent: env
layerIds: [0, 1]
syncModel: Enums.SyncModelLayer
outSpatialReference: sr
}
LayerSyncInfo {
id: layerSyncInfoPoints
layerId: 0
syncDirection: Enums.SyncDirectionUpload
}
LayerSyncInfo {
id: layerSyncInfoPolygons
layerId: 1
syncDirection: Enums.SyncDirectionDownload
}
SyncGeodatabaseParameters {
id: syncGeodatabaseParameters
layerSyncInfos: [layerSyncInfoPoints, layerSyncInfoPolygons]
}
Geodatabase {
id: gdb
path: gdbPath
}
GeodatabaseSyncStatusInfo {
id: geodatabaseSyncStatusInfo
}
GeodatabaseSyncTask {
id: geodatabaseSyncTask
url: featureServerUrl
onGenerateStatusChanged: {
// generate in progress
if (generateStatus === Enums.GenerateStatusInProgress) {
console.log("Generate geodatabase in progress...")
}
// generate complete
else if (generateStatus === Enums.GenerateStatusCompleted) {
console.log("Generate geodatabase complete.")
console.log("path: " + gdb.path)
console.log("sync enabled: " + gdb.isSyncEnabled)
console.log("sync model: " + gdb.syncModel)
console.log("valid: " + gdb.valid)
}
// generate error
else if (generateStatus === GeodatabaseSyncTask.GenerateError) {
console.log("Error: " + generateGeodatabaseError.message
+ " Code= " + generateGeodatabaseError.code.toString(
) + " " + generateGeodatabaseError.details)
}
}
onSyncStatusChanged: {
// sync is ready
if (syncStatus === Enums.SyncStatusReady) {
console.log('Sync geodatabase ready...')
}
// sync in progress
if (syncStatus === Enums.SyncStatusInProgress) {
console.log('Sync geodatabase in progress...')
}
// sync complete
else if (syncStatus === Enums.SyncStatusCompleted) {
console.log("Sync Geodatabase Complete.")
var gdbtables = gdb.geodatabaseFeatureTables
for (var i in gdbtables) {
var geodatabaseFeatureTable = gdbtables
console.log(geodatabaseFeatureTable.featureServiceLayerName)
;
console.log(geodatabaseFeatureTable.features.length)
}
}
// sync error
else if (syncStatus === Enums.SyncStatusErrored) {
console.log("Error: " + syncGeodatabaseError.message + " code= "
+ syncGeodatabaseError.code.toString(
) + " " + syncGeodatabaseError.details)
}
}
onGeodatabaseSyncStatusInfoChanged: {
// uploading status
if (geodatabaseSyncStatusInfo.status === Enums.GeodatabaseStatusUploadingDelta) {
var deltaProgress = geodatabaseSyncStatusInfo.deltaUploadProgress / 1000
var deltaSize = geodatabaseSyncStatusInfo.deltaSize / 1000
console.log(geodatabaseSyncStatusInfo.statusString + " " + String(
deltaProgress) + " of " + String(
deltaSize) + " KBs...")
}
else{
console.log("Sync status: " + geodatabaseSyncStatusInfo.status)
}
}
}
Column {
id: controlsColumn
width: 800
height: 600
anchors.leftMargin: 0
anchors.topMargin: 0
anchors {
left: parent.left
top: parent.top
margins: 20
}
spacing: 7
Button {
id: getServiceButton
text: "Get Service Info"
enabled: true
onClicked: {
console.log("Getting service info...")
featureServiceInfoTask.fetchFeatureServiceInfo()
console.log(featureServiceInfoTask)
}
}
Button {
id: generateButton
text: "Generate Database"
enabled: true
onClicked: {
generateGeodatabaseParameters.initialize(featureServiceInfoTask.featureServiceInfo)
generateGeodatabaseParameters.extent = env
generateGeodatabaseParameters.returnAttachments = false
console.log("Generating geodatabase...")
geodatabaseSyncTask.generateGeodatabase(generateGeodatabaseParameters, gdbPath)
}
}
Button {
id: registerButton
text: "Register Database"
enabled: true
onClicked: {
// register geodatabase
console.log("Registering geodatabase...")
geodatabaseSyncTask.registerGeodatabase(gdb)
}
}
Button {
id: syncButton
text: "Sync Database"
enabled: true
onClicked: {
console.log("Syncing geodatabase...")
geodatabaseSyncTask.syncGeodatabase(
syncGeodatabaseParameters, gdb)
}
}
}
}