Skip navigation
All Places > GeoDev Germany > Blog > 2015 > March
2015

Die Produktfamilie der ArcGIS Runtime SDKs ist seit der Version 10.2 offline-fähig. Dabei können Hintergrundkarten und Vektordaten von Diensten exportiert, und im Falle der Vektordaten auch synchronisiert werden. Um diese Funktionen zu veranschaulichen hat Esri Deutschland eine Demoanwendung entwickelt, welche die Offline Funktionalität von Collector for ArcGIS mit dem ArcGIS Runtime SDK for .NET und Java nachbildet. Diese Demo trägt den Namen Collector Light und ist auf GitHub veröffentlicht. Außerdem ist bereits ein Blog dazu erschienen.

In diesem Artikel wird jetzt, am Beispiel der Java Demo, der Ablauf zum Exportieren und Synchronisieren von Vektordaten genauer betrachtet.

Ein paar Vorbereitungen müssen sein

Die Demo verwendet als Datenquelle eine WebMap. Diese wäre aber nicht zwingend nötig. Um Vektordaten exportieren zu können wird lediglich ein FeatureService benötigt. Dieser kann sowohl bei ArcGIS Online, in Portal for ArcGIS oder auf einem eigenen ArcGIS for Server gehostet sein. Dabei ist zu beachten dass im Dienst der Vorgang „Synchronisieren“ aktiviert ist. Am ArcGIS for Server kann dies im ArcGIS Server Manager im jeweiligen Dienst unter Funktionen -> Feature Access gemacht werden.

SyncEnabled_ArcGISServer.png

In ArcGIS Online und Portal for ArcGIS in den Properties des Dienstes.

SyncEnabled_ArcGISOnline.png

Wird diese Funktion aktiviert bietet der Dienst zusätzliche REST-Schnittstellen an. Mit Hilfe der Operation „Create Replica“ können die Daten offline geholte werden. „Synchronize Replica“ ist für die Synchronisation der Daten und mit „Unregister Replica“ können die Daten gelöscht werden. Dazu aber später mehr.

ServiceDirectory_MitSync.png

Jetzt startet endlich die Programmierung

Wir müssen diese REST-Schnittstellen aber nicht direkt implementieren. Diese werden bereits vom ArcGIS Runtime SDK for Java gekapselt, so dass wir hierfür Java-Klassen und Methoden zur Verfügung haben. Die Verwendung zum Exportieren von Vektordaten findet man in der Demo in der Klasse action.CreateOfflineProject. Genauer gesagt in der Methode createGeodatabaseFromService.

Nach einer kleinen Aufbereitung der Daten, was der Verwendung einer WebMap geschuldet ist, beginnt der spannende Teil in Zeile 330 mit dem Erzeugen der GenerateGeodatabaseParameters.

 

//set up the parameters
  GenerateGeodatabaseParameters params = new GenerateGeodatabaseParameters(
       ArrayUtils.toPrimitive(layerIds.toArray(new Integer[layerIds.size()])),
       extent,
       map.getSpatialReference(),
       false,  
       SyncModel.GEODATABASE,
       map.getSpatialReference());

 

Hier zeigt sich, dass man die zu-exportierenden Daten einschränken kann. Zum einen besteht die Möglichkeit einzelne Layer des Diensts zu selektieren. Zum anderen kann ein Extent mitgegeben werden, so dass der Bereich eingeschränkt wird. Auch Anhänge können, müssen aber nicht geladen werden. Zudem ist es wichtig ein gewünschtes Koordinatensystem als Parameter mitzugeben, damit die Daten hinterher auch richtig auf unserer Karte dargestellt werden können. Anschließend werden zwei Callback Klassen benötigt. Eine wird verwendet um Statusinformationen während der Laufzeit entgegen zu nehmen. Die andere wird aufgerufen wenn der Task beendet ist und nimmt schlussendlich das Ergebnis entgegen. Jetzt kommt auch schon die Klasse GeodatabaseSyncTask ins Spiel, die den eigentlichen Aufruf generateGeodatabase macht.

 

// ------------------------------------------------------------------------ 
// Generate the geodatabase from the service and download 
// ------------------------------------------------------------------------ 
GeodatabaseSyncTask gdbTask = new GeodatabaseSyncTask(featureServiceUrl, PortalConnector.getUser(true));
gdbTask.generateGeodatabase(params, pathToGdb, false, statusCallback, gdbResponseCallback);

 

Zum Erzeugen dieser Klasse benötigt man nur die URL zum FeatureService. Falls es sich um einen abgesicherten Dienst handelt, muss man, wie in diesem Beispiel, zudem Credentials mit übergeben. Details zum Thema Autorisierung und Authentifizierung gibt es einem eigenen Blog.

 

Wo sind denn jetzt meine Daten?

Im gdbResponseCallback in diesem Beispiel wird lediglich einem ProjectManager gesagt, dass neue Daten verfügbar sind. Deshalb stellt sich jetzt die Frage: Wo sind denn meine Daten? Die finden wir unter dem Pfad und Namen, der beim Aufruf als Parameter (pathToGdb) übergeben wurde. An den Namen wird noch die Dateiendung .geodatabse angehängt. Die Daten liegen in einer Datenbankstruktur vor, genauer gesagt einem SQLite Format, und können mit jedem gängigen SQLite-Tool betrachtet werden.

Wie kommen die Daten in meine Karte?

Aber wir wollen die Daten ja in unserer Karte betrachten und nicht in irgendeinem anderen Tool. Hierfür bietet das ArcGIS Runtime SDK for Java die Klasse FeatureLayer. Dieser kann mit Hilfe von verschiedenen Datenquellen als Basis erzeugt werden. Das ist das Schöne an dieser Klasse. Unabhängig von der Datenquelle ist das Handling immer das Gleiche. Eine von diesen Datenquellen ist die GeodatabaseFeatureTable. An diese Tables kommen wir, indem wir unsere SQLite Datenbank mit Hilfe der Klasse Geodatabse initialisieren. Für jeden einzelnen Layer wird dabei eine GeodatabseFeatureTable erzeugt.

 

Geodatabase localGeodatabase = new Geodatabase("PathToGeodatabase");
  for (GeodatabaseFeatureTable table : localGeodatabase.getGeodatabaseTables()) {
  FeatureLayer featureLayer = new FeatureLayer(table);
  featureLayer.initializeAsync();
}

 

Ich will wieder nach Hause telefonieren

So, jetzt sind die Daten offline. Wir können uns nun frei, fernab der digitalen Zivilisation, bewegen und Daten erfassen, ändern oder löschen. Irgendwann wird aber der Moment kommen, in dem wir unsere Änderungen mit unseren Kollegen teilen wollen. Außerdem interessiert mich ja vielleicht auch was diese in meiner Abwesenheit getrieben haben. Wir müssen also mit dem Mutterschiff (dem FeatureService) Kontakt aufnehmen. In der Demo passiert dies in der Klasse action.SyncProject. Die Methode syncGeodatabase in der bereits bekannten Klasse GeodatabaseSyncTask hilft uns dabei.

 

gdbTask.syncGeodatabase(syncParams, gdb, statusCallback, syncResponseCallback);

 

Wir sehen wieder die zwei Callbacks für Statusmeldungen und für das Ergebnis. Als weitere Parameter brauchen wir die Geodatabase (gdb) und spezielle SyncGeodatabaseParameters. Die Geodatabase haben wir ja bereits im vorherigen Schritt zur Visualisierung der Daten erzeugt. Und auch wegen der SyncParameter müssen wir uns keine Gedanken machen, denn die werden von der Geodatabase erzeugt.

 

final SyncGeodatabaseParameters syncParams = gdb.getSyncParameters();

 

Das hat den Vorteil dass wir die komplexe Datenbankstruktur nicht kennen müssen, um unsere Änderungen zu extrahieren. Denn übertragen wird immer nur das Delta, nicht die komplette Datenbank. Bei der Synchronisation werden außerdem alle Änderungen am Dienst in meine lokale Datenbank übertragen, so dass ich auf dem aktuellsten Stand weiterarbeiten kann. Hier wird ebenfalls nur das Delta übertragen. Dies ist auch auf der folgenden Grafik erkennbar, die den gesamten Workflow schematisch darstellt.

 

SyncProcess.png

Haben mehrere Kollegen Änderungen an einem Datensatz vorgenommen, so gewinnt immer die letzte Änderung. Wobei dabei der Zeitstempel der Synchronisation und nicht der Zeitstempel der Änderung zählt. Zukünftig soll es auch andere Optionen zum Lösen von Konflikten geben, die dann pro Dienst eingestellt werden können. Aktuell ist das jedoch noch nicht möglich.

Beenden wir das Einsiedlerleben

Irgendwann kehrt man hoffentlich wieder zurück ins Büro und benötigt die lokale Kopie der Daten nicht mehr. Dann ist es wichtig diese nicht einfach zu löschen, sondern vorher einen Unregister am Dienst zu machen. Natürlich steht uns hierfür wieder die Klasse GeodatabaseSyncTask zur Verfügung, diesmal mit der Methode unregisterGeodatabase.

 

gdbTask.unregisterGeodatabase(gdb, unregisterCallback);

 

In der Demo findet man diesen Aufruf in der Klasse action.DeleteProject. Aber warum ist dieser Aufruf so wichtig? Der FeatureService erzeugt für jede Kopie ein sogenanntes Replica. Darin sind Informationen zur Kopie abgelegt, wie z.B. der Zeitpunkt der letzten Synchronisation. Diese Daten werden benötigt um den Synchronisationsmechanismus bewerkstelligen zu können. Beim Unregister wird dieses Replica gelöscht, da der Dienst dann weiß dass die lokale Kopie nicht mehr benötigt wird. Die Replicas eines Dienstes kann man sich auch in dessen Service Directory ansehen.

 

Replicas.png

Eine digitale Karte besteht in der Regel aus Basemaps und Vektordaten, welche in Form von Layern übereinander dargestellt werden. Basemaps sind georeferenzierte Bilder ohne abrufbare geografische Informationen. Sie werden nicht sehr häufig aktualisiert und dienen im Wesentlichen der Orientierung. Vektordaten hingegen sind Geo-Objekte (Features), die jeweils aus einer Geometrie und zugehörigen Informationen bestehen. Sie werden meistens oberhalb der Basemaps mit einer geeigneten Symbologie dargestellt. Vektordaten können im Client zum Informieren, Analysieren und auch zur Datenerfassung genutzt werden.

 

ArcGIS bietet verschiedene Möglichkeiten, Basemaps und Vektordaten auch offline auf unterschiedlichen Geräten nutzen zu können. In diesem Blog wird sich näher mit Offline-Vektordaten beschäftigt. Im Folgenden werden wir uns näher mit Offline-Basemaps und deren Nutzung in Apps auf Basis von ArcGIS Runtime beschäftigen.

 

 

Wie komme ich zu einer Offline Basemap?

 

Vorbereitung

 

Vorab müssen sich grundlegende Gedanken über das Projekt gemacht werden, um die richtigen Entscheidungen zu treffen, zB:

 

  • Wie groß ist das geografische Gebiet und welche Skalierung wird offline benötigt? Das hat direkte Auswirkung auf die Größe des Datenpakets und kann sehr schnell Richtung vieler Gigabyte gehen.
  • Soll die Offline Basemap zentral erzeugt und anschließend auf die Geräte kopiert werden? Hierzu wird eine Infrastruktur zum Verteilen der Daten benötigt.
  • Soll die Offline Basemap in jeder App direkt von einem Tiled MapService exportiert werden? Hier muss unter anderem die Wartezeit der Anwender und die Performance des GIS Servers bei vielen gleichzeitigen Zugriffen geprüft werden.

 

Formate

 

Offline Basemaps können als ArcGIS for Server Compact Cache oder als Tile Package erzeugt werden. Ein Compact Cache ist eine Ordnerstruktur mit mehreren Dateien und ein Tile Package ist ein geziptes File mit der Endung *.tpk. Alle ArcGIS Runtime SDKs können mit beiden Formaten umgehen. Sie sind auch gleich performant. Für die Verteilung sind Tile Packages zu empfehlen, da es nur eine einzelne Datei ist.

 

Datenquellen

 

Es können Tiled MapServices und lokale Daten zur Erzeugung einer Offline Basemap genutzt werden.

 

 

In den Einstellungen der Services muss der Export erlaubt werden.

 

Noch eine Info speziell zum Export von ArcGIS Online Basemaps:

Die Standard Basemaps auf ArcGIS.com sind frei zugänglich und können nicht exportiert werden. Für den Export stellt Esri einen weiteren Server mit den gleichen Basemaps bereit. Dafür ist zwar eine Authentifizierung (ArcGIS Developer Account oder Mitglieder einer ArcGIS Online Subskription) notwendig, der Export selber verursacht aber keine Kosten. Das bedeutet für Entwickler, dass eventuell im Code der Host der URL ausgetauscht werden muss:

 

http://services.arcgisonline.com/arcgis/rest/services/World_Topo_Map/MapServer

                                                            zu

http://tiledbasemaps.arcgis.com/arcgis/rest/services/World_Topo_Map/MapServer

 

Werkzeuge zum Erstellen von Offline Basemaps

 

ArcGIS for Desktop bietet verschiedene Werkzeuge, um Offline Basemaps in den zwei Formaten sowohl aus lokalen Daten als auch von Services zu exportieren. Diese Aufgaben können auch mit Python automatisiert werden.

 

Weiterhin verfügen alle ArcGIS Runtime SDKs über Methoden zum Exportieren von Offline Basemaps von Services direkt in der App.

 

 

Exportieren von Offline Basemaps mit ArcGIS Runtime

 

Mit allen ArcGIS Runtime SDKs können Daten von Tiled MapServices exportiert und offline genutzt werden. Die Vorgehensweise dafür ist bei allen identisch. Für die folgenden Schritte wird ein Tiled MapService mit entsprechenden Einstellungen und Nutzerrechten vorausgesetzt.

 

So wird es gemacht (ArcGIS Runtime SDK for .NET):

 

     1. Erzeugen eines ExportTileCacheTask Objekts:

 

_exportTileCacheTask = new ExportTileCacheTask(exportArcGisTiledMapServiceLayerServiceUri);

 

     2. Parameter für den Export festlegen, wir wollen als Format ein Tile Package, nicht alle Scales und nur ein bestimmtes Gebiet

 

_generateTileCacheParameters = new GenerateTileCacheParameters
{
        Format = ExportTileCacheFormat.TilePackage,
        MinScale = CurrentEsriMapView.MinScale,
        MaxScale = CurrentEsriMapView.MaxScale,
        GeometryFilter = _areaToExportGraphic.Geometry.Extent
};

 

     3. Größe und Anzahl der angeforderten Tiles mit der Funktion EstimateTileCacheSizeAsync prüfen und falls notwendig Probleme abfangen.

 

var exportTileCacheJobStatusProgress = new Progress<ExportTileCacheJob>();
exportTileCacheJobStatusProgress.ProgressChanged += (p, q) =>

{
                if (q.Messages == null)
                               return;
                //do something
};

await _exportTileCacheTask.EstimateTileCacheSizeAsync(_generateTileCacheParameters,
                (result, ex) => // Callback for when estimate operation has completed
                {
                               if (ex == null) // Check whether operation completed with errors
                               {
                                               _model.SetMessageInfo(string.Format("Tiles: {0} - Size (kb): {1:0}", result.TileCount, result.Size/1024));
                               }
                               else
                               {
                                               _model.SetMessageInfo(string.Format("Error: {0}", ex.Message));
                               }
                }, TimeSpan.FromSeconds(5), CancellationToken.None, exportTileCacheJobStatusProgress);

 

     4. Erzeugen des Tile Packages auf dem Server und Download zum Client inklusive Abfrage des Status:

 

var downloadOptions = new DownloadTileCacheParameters(_exportMapPath)
{
         OverwriteExistingFiles = true
};

var generateStatusCheckProgress = new Progress<ExportTileCacheJob>();
generateStatusCheckProgress.ProgressChanged += (p, q) =>

{
         if (q.Messages.Count < 1)
                   return;
         _model.SetMessageInfo(string.Format("{0}", q.Messages[1].Description));
};

var downloadProgressChanged = new Progress<ExportTileCacheDownloadProgress>();
downloadProgressChanged.ProgressChanged += (p, q) =>

{
         //do something
};


var downloadTileCacheResult = await _exportTileCacheTask.GenerateTileCacheAndDownloadAsync(
         _generateTileCacheParameters,
         downloadOptions, TimeSpan.FromSeconds(5), CancellationToken.None, generateStatusCheckProgress,
         downloadProgressChanged);

 

Wenn alles sauber durchgelaufen ist haben wir nun eine Offline Basemap als Tile Package lokal auf unserem Gerät gespeichert.

 

 

Implementieren von Offline Basemaps in ArcGIS Runtime

 

Das Einbinden von Offline Basemaps in die Karte ist relativ simpel. In allen ArcGIS Runtime SDKs gibt es das Objekt ArcGisLocalTiledLayer. Diesem geben wir den Pfad zu unserem Tile Package und fügen es anschließend der LayerCollection der Karte hinzu.

 

So wird es gemacht (ArcGIS Runtime SDK for .NET):

 

var arcGisLocalTiledLayer = new ArcGISLocalTiledLayer(@"c:\temp\basemap.tpk");
var offlineMap = new Map();
offlineMap.Layers.Add(arcGisLocalTiledLayer);

var mapView = new MapView { Map = offlineMap };
CurrentEsriMapView = mapView;

 

 

Weitere Informationen

 

Am 19.3. fand unser 3. GeoDev Meetup in Berlin statt. "Klein, aber fein!", mit diesen Worten könnte man das Event zusammenfassen. Dieses mal gab es folgende Talks (Vorträge im Anhang):

 

  • "Debugging im Maisfeld: Android schlägt Schädlinge in die Flucht", Martin Krausmann, arc-greenlab
  • "State of OSM Buildings", Jan Marsch, OSM Buildings

 

Besonders die anschließende Diskussion zu 3D fand bei allen Teilnehmern Anklang. Es wurde diskutiert, wo die Technologie aktuell steht, wie sie sich weiter entwickeln wird und wo Einsatzmöglichkeiten erwartet werden. Wir merken uns das und werden künftige Meetups entsprechend gestalten.

 

Wie immer könnt Ihr Euch im Nachgang auf meetup.com Fotos anschauen, Eure Kommentare geben ... und Euch auch gleich für ein Meetup in Eurer Nähe anmelden. Weiter geht es am 18.6. in Köln, es folgt am 2.7. München.

 

Wir möchten Euch an dieser Stelle nochmals auf die im Mai anstehende GIS Talk, die deutsch-sprachige Esri Anwenderkonferenz, hinweisen. Wir werden dort einen dedizierten Developer Track sowie erstmals eine Startup Corner organisieren. Weitere Infos findet ihr in der zugehörigen GeoNet Gruppe zur GIS Talk.

 

Map Man Art_White.png

Am Dienstag, den 03. März 2015 fand ein Webinar für Entwickler zum Thema Mobile Apps mit JavaScript statt.

 

Falls ihr es nicht zum Webinar geschafft habt, könnt ihr euch nachträglich das Video weiter unten anschauen und auch die Folien herunterladen.

Auf GitHub haben wir euch alle Beispiele bereitgestellt.

 

Diesmal habt ihr keine Fragen gestellt. Wir werten das einfach mal als gutes Zeichen. Falls ihr dennoch Fragen habt, könnt ihr sie gerne an developers@esri.de schicken.

 

Am 19. März 2015 geht es mit dem GeoDev Meet-up in Berlin weiter. Weitere Meet-ups folgen in Köln und München.

 

Im Mai ist es soweit, dann öffnet die deutschsprachige Esri Anwenderkonferenz GIS Talk in München wieder ihre Tore. Entwickler-Themen widmen wir einen eigenen Developer Track. Darüber hinaus wird es erstmalig eine Startup-Corner geben.

 

Wir würden uns freuen, euch bei einer der nächsten Veranstaltungen zu treffen.

 

Im jüngsten Release von ArcGIS Online hat Esri sich dem Thema Kartografie erneut angenommen und es sehr einfach gemacht, schnell aussagekräftige Karten zu erstellen. Ich denke, das war ein guter Schritt. Mapbox und CartoDB haben uns jüngst gezeigt, wie wichtig dieses Thema ist. Lest in diesem und diesem Blog mehr zu Data-Driven Workflows, Smart Defaults, Heatmaps & Co.

 

SD_heatmap.jpg

Esri hat letzte Woche die Data Viz App Challenge gestartet. Entwickler weltweit sind aufgerufen, Apps zu entwickeln, die die Visualisierungsmöglichkeiten von ArcGIS demonstrieren. Der Gewinner erhält 10.000 USD! Also, worauf wartet Ihr noch? Reicht Eure Arbeiten bis spätestens 27. April ein und erfahrt am 11. Mai, ob Ihr der Glückliche seid.

 

Weitere Infos erhaltet Ihr auch auf Hacker League.

 

Data Viz App Challenge.JPG

Filter Blog

By date: By tag: