<\/HEAD>
La famille de produits des ArcGIS Runtime SDKs<\/A> est capable de fonctionner hors ligne depuis la version 10.2. Il est possible d'exporter des fonds de carte et des données vectorielles à partir de services, et dans le cas des données vectorielles, elles peuvent également être synchronisées. Pour illustrer ces fonctionnalités, Esri Allemagne a développé une application de démonstration qui reproduit la fonctionnalité hors ligne de Collector for ArcGIS<\/A> avec l'ArcGIS Runtime SDK pour .NET<\/A> et Java<\/A>. Cette démo s'appelle Collector Light et est publiée sur GitHub<\/A>. De plus, un blog<\/A> a déjà été publié à ce sujet.<\/SPAN><\/P>Dans cet article, nous examinons maintenant plus en détail le processus d'exportation et de synchronisation des données vectorielles à l'aide de la démo Java.<\/SPAN><\/P>
<\/H2>La programmation commence enfin<\/SPAN><\/H2>Nous n'avons pas besoin d'implémenter directement ces interfaces REST. Elles sont déjà encapsulées par l'ArcGIS Runtime SDK for Java, ce qui met à disposition des classes et méthodes Java pour cela. L'utilisation pour exporter des données vectorielles se trouve dans la démo dans la classe action.CreateOfflineProject. Plus précisément dans la méthode createGeodatabaseFromService. <\/><\/><\/><\/><\/><\/><\/><\/><\/><\/><\/><\/><\/><\/><\/><\/><\/><\/><\/>.
Après une petite préparation des données due à l'utilisation d'une WebMap, la partie intéressante commence à la ligne 330 avec la création des GenerateGeodatabaseParameters<\\a>.
//set up the parameters
GenerateGeodatabaseParameters params = new GenerateGeodatabaseParameters(
ArrayUtils.toPrimitive(layerIds.toArray(new Integer[layerIds.size()])),
extent,
map.getSpatialReference(),
false, 
&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;;
Voici comment on peut restreindre les données à exporter. D'une part il est possible de sélectionner certains calques du service. D'autre part on peut fournir une étendue (extent) pour limiter la zone concernée. Les pièces jointes peuvent aussi être chargées mais ce n'est pas obligatoire. Il est également important de fournir un système de coordonnées souhaité en paramètre afin que les données soient correctement affichées sur notre carte par la suite. Ensuite deux classes Callback sont nécessaires : l'une sert à recevoir les informations d'état pendant l'exécution ; l'autre est appelée lorsque la tâche est terminée et reçoit finalement le résultat. C'est ici que la classe GeodatabaseSyncTask<\\a> entre en jeu et effectue l'appel réel generateGeodatabase.
// ------------------------------------------------------------------------
// Générer la géodatabase depuis le service et télécharger
// ------------------------------------------------------------------------
GeodatabaseSyncTask gdbTask = new GeodatabaseSyncTask(featureServiceUrl, PortalConnector.getUser(true));
gdbTask.generateGeodatabase(params, pathToGdb, false, statusCallback, gdbResponseCallback);
Pour créer cette classe il suffit d'avoir l'URL du FeatureService. Si le service est sécurisé comme dans cet exemple, il faut aussi fournir les Credentials correspondants. Des détails sur l'autorisation et l'authentification sont disponibles dans un blog dédié.
Où sont mes données maintenant ?
Dans le gdbResponseCallback de cet exemple on informe simplement un ProjectManager que de nouvelles données sont disponibles. La question se pose donc : où sont mes données ? Elles se trouvent sous le chemin et le nom passés en paramètre lors de l'appel (pathToGdb). L'extension .geodatabase est ajoutée au nom. Les données sont stockées dans une structure de base de données au format SQLite et peuvent être consultées avec n'importe quel outil SQLite courant.
Comment intégrer les données dans ma carte ?
Mais nous voulons visualiser les données dans notre carte et non dans un autre outil quelconque. Pour cela l'ArcGIS Runtime SDK for Java propose la classe FeatureLayer<\\a>. Celle-ci peut être créée à partir de différentes sources de données comme base. C'est là tout l'avantage de cette classe : quelle que soit la source de données utilisée le traitement reste toujours le même. Une de ces sources est la GeodatabaseFeatureTable<\\a>. Nous accédons à ces tables en utilisant notre SQLite<\\a> Initialiser la base de données à l'aide de la classe Geodatabse. Pour chaque couche individuelle, une GeodatabseFeatureTable est créée.<\/SPAN><\/P><\/P>Geodatabase localGeodatabase = new Geodatabase("PathToGeodatabase");
for (GeodatabaseFeatureTable table : localGeodatabase.getGeodatabaseTables()) {
FeatureLayer featureLayer = new FeatureLayer(table);
featureLayer.initializeAsync();
}<\/PRE><\/P>Je veux téléphoner à la maison<\/H2>Alors, maintenant les données sont hors ligne. Nous pouvons maintenant nous déplacer librement, loin de la civilisation numérique, et collecter, modifier ou supprimer des données. Mais un jour viendra où nous voudrons partager nos modifications avec nos collègues. De plus, je suis peut-être aussi curieux de savoir ce qu'ils ont fait en mon absence. Nous devons donc contacter le vaisseau mère (le FeatureService). Dans la démo, cela se passe dans la classe action.SyncProject. La méthode syncGeodatabase dans la classe déjà connue GeodatabaseSyncTask nous aide pour cela.<\/SPAN><\/P><\/P>gdbTask.syncGeodatabase(syncParams, gdb, statusCallback, syncResponseCallback);<\/PRE><\/P>Nous voyons à nouveau les deux callbacks pour les messages d'état et pour le résultat. Comme autres paramètres, nous avons besoin de la Geodatabase (gdb) et des SyncGeodatabaseParameters spécifiques. Nous avons déjà créé la Geodatabase à l'étape précédente pour visualiser les données. Et nous n'avons pas non plus à nous soucier des SyncParameters car ils sont générés par la Geodatabase.<\/SPAN><\/P><\/P>final SyncGeodatabaseParameters syncParams = gdb.getSyncParameters();<\/PRE><\/P>Cela a l'avantage que nous n'avons pas besoin de connaître la structure complexe de la base de données pour extraire nos modifications. Car seul le delta est toujours transféré, pas la base de données complète. Lors de la synchronisation, toutes les modifications du service sont également transférées vers ma base de données locale afin que je puisse continuer à travailler avec les données les plus récentes. Ici aussi, seul le delta est transféré. Cela est également visible sur le graphique suivant qui illustre schématiquement tout le flux de travail.<\/SPAN><\/P><\/P>
<\/P>Si plusieurs collègues ont apporté des modifications à un enregistrement, c'est toujours la dernière modification qui prévaut. Le timestamp pris en compte est celui de la synchronisation et non celui de la modification. À l'avenir, il devrait également y avoir d'autres options pour résoudre les conflits qui pourront être configurées par service. Actuellement, cela n'est cependant pas encore possible.<\/SPAN><\/P><\/H2>Mettons fin à la vie d'ermite<\/SPAN><\/H2>Un jour on espère revenir au bureau et ne plus avoir besoin de la copie locale des données. Il est alors important de ne pas simplement supprimer cette copie mais d'abord de faire un désenregistrement auprès du service. Bien sûr, pour cela nous avons à nouveau la classe GeodatabaseSyncTask, cette fois avec la méthode unregisterGeodatabase.<\/SPAN><\/P><\/P>gdbTask.unregisterGeodatabase(gdb, unregisterCallback);<\/SPAN><\/PRE><\/P>Dans la démo on trouve cet appel dans la classe action.DeleteProject. Mais pourquoi cet appel est-il si important ? Le FeatureService crée pour chaque copie ce qu'on appelle un Replica. Celui-ci contient des informations sur la copie comme par exemple le moment de la dernière synchronisation. Ces données sont nécessaires pour pouvoir gérer le mécanisme de synchronisation. Lors du désenregistrement ce Replica est supprimé car le service sait alors que la copie locale n'est plus nécessaire. On peut aussi consulter les Replicas d'un service dans son Service Directory.<\/SPAN><\/P><\/P>
<\/P><\/BODY><\/HTML>