<\/HEAD>
La familia de productos de los ArcGIS Runtime SDKs<\/A> es compatible con el modo offline desde la versión 10.2. En este contexto, se pueden exportar mapas base y datos vectoriales desde servicios, y en el caso de los datos vectoriales también sincronizarlos. Para ilustrar estas funciones, Esri Deutschland ha desarrollado una aplicación demo que reproduce la funcionalidad offline de Collector for ArcGIS<\/A> con el ArcGIS Runtime SDK para .NET<\/A> y Java<\/A>. Esta demo se llama Collector Light y está publicada en GitHub<\/A>. Además, ya se ha publicado un blog<\/A> al respecto.<\/SPAN><\/P>En este artículo se examina ahora, usando como ejemplo la demo en Java, el proceso para exportar y sincronizar datos vectoriales con más detalle.<\/SPAN><\/P>
<\/H2>Ahora finalmente comienza la programación<\/SPAN><\/H2>No tenemos que implementar directamente estas interfaces REST. Estas ya están encapsuladas por el ArcGIS Runtime SDK for Java, por lo que disponemos de clases y métodos Java para ello. El uso para exportar datos vectoriales se encuentra en la demo en la clase action.CreateOfflineProject. Más concretamente en el método createGeodatabaseFromService. <\/><\/><\/><\/><\/><\/><\/><\/><\/><\/><\/><\/><\/><\/><\/><\/><\/><\/><\/>.
Después de una pequeña preparación de los datos debido al uso de un WebMap comienza la parte interesante en la línea 330 con la creación de los GenerateGeodatabaseParameters<\\a>.
// configurar los parámetros
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;amp;amp;;
Aquí se muestra que es posible restringir los datos a exportar. Por un lado existe la posibilidad de seleccionar capas individuales del servicio. Por otro lado se puede proporcionar un Extent para limitar el área. También es posible cargar adjuntos aunque no es obligatorio. Además es importante proporcionar un sistema de coordenadas deseado como parámetro para que los datos puedan mostrarse correctamente en nuestro mapa posteriormente. A continuación se necesitan dos clases Callback. Una se usa para recibir información de estado durante la ejecución. La otra se llama cuando la tarea termina y finalmente recibe el resultado. Ahora entra en juego la clase GeodatabaseSyncTask<\\a> , que realiza la llamada real generateGeodatabase.
// ------------------------------------------------------------------------
// Generar la geodatabase desde el servicio y descargar
// ------------------------------------------------------------------------
GeodatabaseSyncTask gdbTask = new GeodatabaseSyncTask(featureServiceUrl, PortalConnector.getUser(true));
gdbTask.generateGeodatabase(params, pathToGdb, false, statusCallback, gdbResponseCallback);
Para crear esta clase solo se necesita la URL del FeatureService. Si se trata de un servicio protegido hay que pasar además las credenciales como en este ejemplo. Detalles sobre autorización y autenticación están disponibles en un blog aparte.
¿Dónde están mis datos ahora?
En el gdbResponseCallback de este ejemplo simplemente se le indica a un ProjectManager que hay nuevos datos disponibles. Por eso surge ahora la pregunta: ¿Dónde están mis datos? Los encontramos bajo la ruta y nombre que fue pasado como parámetro (pathToGdb) al llamar a la función. Al nombre se le añade la extensión .geodatabase. Los datos están almacenados en una estructura de base de datos, concretamente en formato SQLite y pueden ser visualizados con cualquier herramienta SQLite común.
¿Cómo pongo los datos en mi mapa?
Pero queremos ver los datos en nuestro mapa y no en alguna otra herramienta. Para ello el ArcGIS Runtime SDK for Java ofrece la clase FeatureLayer<\\a>. Esta puede ser creada usando diferentes fuentes de datos como base. Eso es lo bueno de esta clase. Independientemente de la fuente de datos el manejo siempre es igual. Una de estas fuentes es la GeodatabaseFeatureTable<\\a>. A estas tablas accedemos mediante nuestro Geodatabse. Para cada capa individual se crea una GeodatabseFeatureTable.<\/SPAN><\/P><\/P>Geodatabase localGeodatabase = new Geodatabase("PathToGeodatabase");
for (GeodatabaseFeatureTable table : localGeodatabase.getGeodatabaseTables()) {
FeatureLayer featureLayer = new FeatureLayer(table);
featureLayer.initializeAsync();
}<\/PRE><\/P>Quiero llamar a casa de nuevo<\/SPAN><\/H2>Así que ahora los datos están offline. Podemos movernos libremente, lejos de la civilización digital, y capturar, modificar o eliminar datos. Pero llegará el momento en que queramos compartir nuestros cambios con nuestros colegas. Además, quizás me interese saber qué han hecho durante mi ausencia. Por lo tanto, debemos contactar con la nave nodriza (el FeatureService). En la demo esto ocurre en la clase action.SyncProject. El método syncGeodatabase en la ya conocida clase GeodatabaseSyncTask nos ayuda con esto.<\/SPAN><\/P><\/P>gdbTask.syncGeodatabase(syncParams, gdb, statusCallback, syncResponseCallback);<\/PRE><\/P>Volvemos a ver los dos callbacks para mensajes de estado y para el resultado. Como parámetros adicionales necesitamos la Geodatabase (gdb) y parámetros especiales SyncGeodatabaseParameters. Ya hemos creado la Geodatabase en el paso anterior para visualizar los datos. Y tampoco tenemos que preocuparnos por los SyncParameters, ya que son generados por la Geodatabase.<\/SPAN><\/P><\/P>final SyncGeodatabaseParameters syncParams = gdb.getSyncParameters();<\/PRE><\/P>Esto tiene la ventaja de que no necesitamos conocer la compleja estructura de la base de datos para extraer nuestros cambios. Porque siempre se transmite solo el delta, no toda la base de datos completa. Además, durante la sincronización se transfieren todos los cambios del servicio a mi base de datos local para que pueda continuar trabajando con la información más actualizada. Aquí también solo se transfiere el delta. Esto también es visible en el siguiente gráfico que representa esquemáticamente todo el flujo de trabajo.<\/SPAN><\/P><\/P>
<\/P>Si varios colegas han realizado cambios en un registro, siempre gana el último cambio. Donde cuenta el sello temporal de la sincronización y no el sello temporal del cambio. En el futuro habrá otras opciones para resolver conflictos que podrán configurarse por servicio. Actualmente esto aún no es posible.<\/SPAN><\/P><\/H2>Terminemos con la vida de ermitaño<\/SPAN><\/H2>En algún momento uno espera volver a la oficina y ya no necesitará la copia local de los datos. Entonces es importante no simplemente eliminarla sino primero hacer un Unregister en el servicio. Por supuesto contamos nuevamente con la clase GeodatabaseSyncTask, esta vez con el método unregisterGeodatabase.<\/SPAN><\/P><\/P>gdbTask.unregisterGeodatabase(gdb, unregisterCallback);<\/SPAN><\/PRE><\/P>En la demo esta llamada se encuentra en la clase action.DeleteProject. ¿Pero por qué es tan importante esta llamada? El FeatureService crea para cada copia un llamado Replica. En él se almacenan informaciones sobre la copia como por ejemplo el momento de la última sincronización. Estos datos son necesarios para poder realizar el mecanismo de sincronización. Al hacer Unregister este Replica se elimina porque el servicio sabe entonces que ya no se necesita la copia local. Los Replicas de un servicio también pueden verse en su Service Directory.<\/SPAN><\/P><\/P>
<\/P><\/BODY><\/HTML>