With ArcGIS Runtime<\/A>, native apps can be created for all common platforms. Native apps are especially suitable for mobile scenarios in the field service. Since a stable internet connection is often not guaranteed in the field, the maps including all associated data should be stored locally on the device. There are already several ways to do this with ArcGIS Runtime:<\/P><\/P>On Demand export of data directly from ArcGIS Services (Feature<\/A>, Raster<\/A> and Vector Tile<\/A>)<\/LI>On Demand export of complete maps<\/A><\/LI>Preprocessing of ArcGIS Runtime Content<\/A> or Mobile Map Packages<\/A> with ArcGIS Desktop and subsequent copying to the device<\/LI><\/UL>These options are also used in ArcGIS Apps such as Collector<\/A>, Navigator<\/A> or Explorer<\/A>. Since ArcGIS Runtime version 100.2, there is now additionally the Preplanned Workflow<\/A> for continuous and automatable planning of mobile offline scenarios.<\/P>
<\/P>
These options are also used in ArcGIS Apps such as
{ \x22xmin\x22: -13184700, \x22ymin\x22: 3988556, \x22xmax\x22: -13004945, \x22ymax\x22: 4061479, \x22spatialReference\x22: { \x22wkid\x22: 102100 }}<span class= "line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span>
# Import modulesfrom arcgis.gis import GISfrom arcgis.mapping import WebMapfrom getpass import getpass# Setup the organization and user informationpassword=getpass()gis = GIS('https://www.arcgis.com', 'my named user', password)# get the webmap from the portal item idoffline_map_item = gis.content token">.<\/SPAN>get(<\/SPAN>"my webmap id"<\/SPAN>)<\/SPAN>\noffline_webmap =<\/SPAN> WebMap(<\/SPAN>offline_map_item)<\/SPAN>\n\n# Loop through the webmap's bookmarks and create a map area for each one bookmark<\/SPAN>\nfor<\/SPAN> bookmark in<\/SPAN> offline_webmap.<\/SPAN>definition.<\/SPAN>bookmarks:<\/SPAN>\n bookmark_name =<\/SPAN> bookmark.<\/SPAN>name\n item_prop =<\/SPAN> {<\/SPAN>'title'<\/SPAN>:<\/SPAN> offline_map_item.<\/SPAN>title +<\/SPAN> '_'<\/SPAN> +<\/SPAN> bookmark_name +<\/SPAN> '_MapArea'<\/SPAN>,<\/SPAN>\n 'snippet'<\/SPAN>:<\/SPAN> 'my snippet'<\/Span>,<\/span>\n 'description'<\/span>:<\/span> 'my description'<\/span>,<\/span>\n 'tags'<\/span>:<\/span> [<\/span>'python api'<\/span>,<\/span> 'MapArea'<\/span>,<\/span> 'my tag'<\/span>]<\/span>}<\/span>\n offline_area =<\/span> offline_webmap.<\/Span>offline_areas.<\/Span>create(<\/Span>area=<\/span>bookmark_name,<\/span> folder=<\/span>'my portal content folder'<\/Span>,<\/Span> item_properties=<\/span>item_prop)<\/Span> <\/<Span>\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/< Span >< \/ Span > < \/ CODE > < \/ PRE > < P > For a quick test, the Python Notebook attached to this blog can be used on notebooks.esri.com < \/ A > (Upload). < \/ P > < P > < \/ P > < H2 id = "toc-hId-1014640770" id = "toc-hId-1014640770" > Use of MapAreas in ArcGIS Runtime Apps in the field service < \/ H2 > < P > The MapAreas of a WebMap and the associated mobile data have now been created in the Portal. Now they just need to be downloaded and used with ArcGIS Runtime. The Preplanned Workflow functions in the SDKs are only available from ArcGIS Runtime version 100.2 onwards. Here are the rough steps for implementation using the .NET SDK as an example: < \/ P > < P > < \/ P > < P > 1. Loading the WebMap < \/ P > < PRE Class = "lia-code-sample line-numbers language-none" >< CODE >< Span Class = "keyword Token" > var </ Span > portal = await ArcGISPortal . CreateAsync ( ) ; \n \n var webmapItem = await PortalItem . CreateAsync ( portal , "WebMap Portal ID" ) ; \n var myMap = new Map ( webmapItem ) ; << EMOJI_22 >> < Span Class = "line-numbers-rows" >< Span >< EMOJI_23 >< \/ Span >< Span >< EMOJI_24 >< \/ Span >< Span >< EMOJI_25 >< \/ Span >< \/ Span >< \/ CODE >< \/ PRE > \n \n 2. Querying the MapAreas of a WebMap \n \n var offlineMapTask = await OfflineMapTask . CreateAsync ( myMap ) ; \n var preplannedMapAreas = await offlineMapTask . GetPreplannedMapAreasAsync ( ) ; << EMOJI_26 >> < Span Class = "line-numbers-rows" >< Span >< EMOJI_27 >< \/ Span >< Span >< EMOJI_28 >< \/ Span >< \/ Span >< \/ CODE >< \/ PRE > \n \n 3. Downloading the info and data of a MapArea as exploded Mobile Map Package \n \n var myArea = preplannedMapAreas . FirstOrDefault ( ) ; \n \n var downloadJob = offlineMapTask . DownloadPreplannedOfflineMap ( myArea , "Storage path" ) ; \n var results = await downloadJob . GetResultAsync ( ) ; << EMOJI_29 >> < Span Class = "line-numbers-rows" >< Span >< EMOJI_30 >< \/ Span >< Span >< EMOJI_31 >< \/ Span >< Span >< EMOJI_32 >< \/ Span >< Span >< EMOJI_33 >< \/ Span >< \/ Span >< \/ CODE >< \/ PRE > \n \n 4. Loading and displaying the locally stored MapArea in the Map \n \n var offlineMapArea = await MobileMapPackage . OpenAsync ( "Storage path" ) ; \n myMap = offlineMapArea . Maps [ 0 ] ; << EMOJI_34 >> < Span Class = "line-numbers-rows" >< Span >< EMOJI_35 >< \/ Span >< Span >< EMOJI_36 >< \/ Span >< \/ Span >< \/ CODE >< \/ PRE > \n \n Strong Synchronization of edits with the Feature Service Strong \n \n For synchronization of feature edits in both directions, the local SQLite Geodatabase is automatically registered by the OfflineMapTask with the Feature Service . Therefore, the developer does not have to worry about it. Synchronization works like this: \n \n var editLayer = class="punctuation token">(<\/SPAN>FeatureLayer)<\/SPAN>myMap.<\/SPAN>OperationalLayers[<\/SPAN>0<\/SPAN>]<\/SPAN>;<\/SPAN>\nvar<\/SPAN> featureTable =<\/SPAN> (<\/SPAN>GeodatabaseFeatureTable)<\/SPAN>editLayer.<\/SPAN>FeatureTable;<\/SPAN>\n\nvar<\/SPAN> syncTask =<\/SPAN> await<\/SPAN> GeodatabaseSyncTask.<\/SPAN>CreateAsync<\/SPAN>(<\/SPAN>featureTable.<\/SPAN>Geodatabase.<\/SPAN>Source)<\/SPAN>;<\/SPAN>\n\n\/\/ sync geodatabase<\/SPAN>\nvar<\/SPAN> taskParameters =<\/SPAN> await<\/SPAN> syncTask.<\/SPAN>CreateDefaultSyncGeodatabaseParametersAsync<\/SPAN>(<\/SPAN>featureTable.<\/span>Geodatabase)<\/span>;<\/span>\n\nvar<\/span> syncJob =<\/span> syncTask.<\/span>SyncGeodatabase<\/span>(<\/span>taskParameters,<\/span> featureTable.<\/span>Geodatabase)<\/span>;<\/span>\nvar<\/span> result =<\/span> await<\/span> syncJob.<\/span>GetResultAsync<\/span>(<\/span>)<\/span>;<\/span>\n<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/CODE><\/PRE><\/>Before a geodatabase on the device is to be deleted, it must first be deregistered with the Feature Service (otherwise it will eventually be cluttered with tons of replicas). Further information can be found in the documentation. It can be implemented like this:<\/>P>Var editLayer = (FeatureLayermyMap.< /Span >OperationalLayers[0];Var featureTable = (GeodatabaseFeatureTableeditLayer.< /Span >FeatureTable;Var syncTask = await GeodatabaseSyncTask.< /Span >CreateAsync(featureTable.< /Span >Geodatabase.< /Span >Source;// unregister geodatabaseawait</ span > syncTask::UnregisterGeodatabaseAsync( </ span > featureTable < span Class = \ " punctuation Token " >::Geodatabase ) ; < / span >< < EMOJI_12 >>::// delete geodatabase << EMOJI_13 >> </ span >< span Class = \ " line-numbers-rows " >< span >< < EMOJI_14 >> </ span >< span >< < EMOJI_15 >> </ span >< span >< < EMOJI_16 >> </ span >< span >< < EMOJI_17 >> </ span >< span >< < EMOJI_18 >> </ span >< span >< < EMOJI_19 >> </ span >< span >< < EMOJI_20 >> </ span >< span >< < EMOJI_21 >> </ span >< span >< < EMOJI_22 >> </ span ></ span ></ code ></ pre >< p ></ p >< h2 id = \ " toc-hId--1537516191 \ " id = \ " toc-hId--1537516191 \ " >Final Words
Var editLayer = (FeatureLayermyMap.< /Span >OperationalLayers[0];Var featureTable = (GeodatabaseFeatureTableeditLayer.< /Span >FeatureTable;Var syncTask = await GeodatabaseSyncTask.< /Span >CreateAsync(featureTable.< /Span >Geodatabase.< /Span >Source;// unregister geodatabaseawait</ span > syncTask::UnregisterGeodatabaseAsync( </ span > featureTable < span Class = \ " punctuation Token " >::Geodatabase ) ; < / span >< < EMOJI_12 >>::// delete geodatabase << EMOJI_13 >> </ span >< span Class = \ " line-numbers-rows " >< span >< < EMOJI_14 >> </ span >< span >< < EMOJI_15 >> </ span >< span >< < EMOJI_16 >> </ span >< span >< < EMOJI_17 >> </ span >< span >< < EMOJI_18 >> </ span >< span >< < EMOJI_19 >> </ span >< span >< < EMOJI_20 >> </ span >< span >< < EMOJI_21 >> </ span >< span >< < EMOJI_22 >> </ span ></ span ></ code ></ pre >< p ></ p >< h2 id = \ " toc-hId--1537516191 \ " id = \ " toc-hId--1537516191 \ " >Final Words
The Preplanned Workflow has brought the topic of mobile offline scenarios in ArcGIS to completion. The whole thing is now a well-rounded matter but still has optimization potential here and there, e.g., shapes as MapAreas would be more useful than just rectangular areas (which work area is exactly rectangular anyway). We will see improvements, and overall it is already very helpful. We will soon find the Preplanned Workflow again in some ArcGIS Apps (Collector, Explorer). Currently, it is only available in ArcGIS Online; in ArcGIS Enterprise, it will be implemented in a later version.
P.s.: The sections on creating MapAreas with the Python API (a new Python Notebook is attached) and synchronizing Feature Edits have been slightly revised. Many thanks to Antti Kajanus from the ArcGIS Runtime Team for the tip about the smart Python API implementation and his correction of Register/Unregister of geodatabases.
Sehr schön aufbereitet.
#offline #offline maps #take offline
Signed in members can post, follow updates, and more. New here? Register a free account.
Find useful guides, FAQs, and documents to help you navigate and make the most of Esri Community.