|
POST
|
Ah, ofc. I was using an offline map and not mmpk file so you cannot access the geodatabase directly. As a workaround you need to do something like this then. offlineMapPackage = await MobileMapPackage.OpenAsync(offlineDataFolder);
offlineMap = offlineMapPackage.Maps.First();
await offlineMap.LoadAsync();
var featureLayers = offlineMap.OperationalLayers.OfType<FeatureLayer>().ToList();
var featureLayer = featureLayers.First();
var gdbTable = featureLayer.FeatureTable as GeodatabaseFeatureTable;
var gdb = gdbTable.Geodatabase;
var pointLayers = new List<int>();
for (int i = 0; i < gdb.GeodatabaseFeatureTables.Count; i++)
{
var table = gdb.GeodatabaseFeatureTables[i] as GeodatabaseFeatureTable;
if (table.GeometryType == GeometryType.Point)
pointLayers.Add(i);
}
offlineMapPackage = await MobileMapPackage.OpenAsync(offlineDataFolder);
offlineMap = offlineMapPackage.Maps.First();
featureLayers = offlineMap.OperationalLayers.OfType<FeatureLayer>().ToList();
featureLayer = featureLayers.First();
gdbTable = featureLayer.FeatureTable as GeodatabaseFeatureTable;
foreach (var index in pointLayers)
{
var table = gdbTable.Geodatabase.GeodatabaseFeatureTables[index];
table.UseAdvancedSymbology = false;
} I couldn't figure other ways to workaround with this and the solution includes opening the mmpk twice. You can clean up the approach a bit but at least it works. The code below only work directly with mmpk that only has one geodatabase inside of it so if you have multiple, then you need to add logic to iterate the layers etc. I'm not sure what we can do to make this easier but I'll log an enhancement ticket for it.(EDIT: except fix the original issue so the workaround isn't needed)
... View more
07-14-2017
01:47 AM
|
0
|
6
|
1013
|
|
POST
|
Does this work? it's not very pretty but after I go through UseAdvancedSymbology values on loaded event, i get thing set properly. I didn't have a service that clearly has different symbology so not sure if the correct symbols was used though. offlineMapPackage = await MobileMapPackage.OpenAsync(offlineDataFolder);
offlineMap = offlineMapPackage.Maps.First();
var featureLayers = offlineMap.OperationalLayers.OfType<FeatureLayer>().ToList();
var featureLayer = featureLayers.First();
var gdbTable = featureLayer.FeatureTable as GeodatabaseFeatureTable;
var gdb = await Geodatabase.OpenAsync(gdbTable.Geodatabase.Path);
var pointLayers = new List<int>();
for (int i = 0; i < gdb.GeodatabaseFeatureTables.Count; i++)
{
var table = gdb.GeodatabaseFeatureTables[i] as GeodatabaseFeatureTable;
await table.LoadAsync();
if (table.GeometryType == GeometryType.Point)
pointLayers.Add(i);
}
foreach (var index in pointLayers)
{
var table = gdbTable.Geodatabase.GeodatabaseFeatureTables[index];
table.UseAdvancedSymbology = false;
}
... View more
07-13-2017
08:34 AM
|
0
|
9
|
6249
|
|
POST
|
Hmm, that sounds a bit weird. If you already have authenticated and you can access the portal with given credentials then it sounds that for some reason that isn't attached correctly or there are other privileges that doesn't match. You should see the error in the results object for the basemap, can you confirm that? Or is the await actually throwing an exception? How do you provide the credential for GenerateOfflineMapJob? OfflineMapTask (and job) doesn't support setting credentials directly since the task might be accessing multiple domain so you have to hook into AuthenticationManager. I added a simple example to this response. I assume that you are using a basemap from the basemap gallery which requires you to authenticate the user since using the export tiles operation is shared as subscriber content. The operation doesn't use credits but requires the user be authenticated. If you don't use our basemaps and those services exposes export tiles operation and none of the feature services requires authentication, you shouldn't see that prompted. Here is an example how to hook authentication to the job. using Esri.ArcGISRuntime.Geometry;
using Esri.ArcGISRuntime.Mapping;
using Esri.ArcGISRuntime.Portal;
using Esri.ArcGISRuntime.Security;
using Esri.ArcGISRuntime.Tasks.Offline;
using System;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
namespace WaterNetworkDemo
{
public partial class MainWindow : Window
{
private const string PORTAL_ITEM_ID = "19df6a8e2c694a3c958778ac25398f26";
private string offlineDataFolder;
public MainWindow()
{
InitializeComponent();
AuthenticationManager.Current.ChallengeHandler = new ChallengeHandler(CreateKnownCredentials);
Initialize();
}
private async void Initialize()
{
try
{
Map offlineMap = null;
MobileMapPackage offlineMapPackage = null;
offlineDataFolder = Path.Combine(Directory.GetCurrentDirectory(), "OfflineMaps", "WaterNetwork.mmpk");
try
{
// Try to open the package, if there isn't a valid package at this location an error will be thrown
offlineMapPackage = await MobileMapPackage.OpenAsync(offlineDataFolder);
offlineMap = offlineMapPackage.Maps.First();
}
catch (FileNotFoundException)
{
// If there isn't a valid offline map package in provided path, this is thrown.
}
// Package was not found, lets create it and download it to that location
if (offlineMapPackage == null)
{
loadingIndicator.Visibility = Visibility.Collapsed;
busyIndicator.Visibility = Visibility.Visible;
// Folder doesn't exist, lets create it and download the data
Directory.CreateDirectory(offlineDataFolder);
offlineMap = await GenerateOfflineMapAsync(offlineDataFolder, PORTAL_ITEM_ID);
}
// Hide loading indicators after the map has been opened / downloaded
loadingIndicator.Visibility = Visibility.Collapsed;
busyIndicator.Visibility = Visibility.Collapsed;
if (offlineMap != null)
{
// Zoom to last specific viewpoint when the map is added to the mapview.
// offlineMap.InitialViewpoint = offlineMap.Bookmarks.Last().Viewpoint;
// Show the offline map
MyMapView.Map = offlineMap;
}
else
{
// For some reason we don't have offline map available, show error message
mapNoAvailable.Visibility = Visibility.Visible;
}
}
catch (Exception ex)
{
// Something unexpected happened, handle properly
MessageBox.Show(ex.Message);
}
}
private async Task<Map> GenerateOfflineMapAsync(string path, string webmapItemId)
{
Map offlineMap = null;
try
{
#region 1) Create an offline map task
// Load portal, using ArcGIS Online in this case
ArcGISPortal portal = await ArcGISPortal.CreateAsync();
// Create a map that is taken offline based on item id
PortalItem webmapItem = await PortalItem.CreateAsync(portal, webmapItemId);
// Create the area that is taken offline, use extent defined in the portal item
var areaOfInterest = GeometryEngine.Project(webmapItem.Extent, SpatialReferences.WebMercator);
// Create task and parameters
OfflineMapTask task = await OfflineMapTask.CreateAsync(webmapItem);
#endregion
#region 2) Specify parameters
// Create default parameters
GenerateOfflineMapParameters parameters =
await task.CreateDefaultGenerateOfflineMapParametersAsync(areaOfInterest);
parameters.MinScale = 200000;
parameters.MaxScale = 1250;
#endregion
#region 3) Generate offline map, report progress and use offline map
// Create a job and hook progress changed reporting
var job = task.GenerateOfflineMap(parameters, path);
job.ProgressChanged += (s, e) =>
{
// Update progress to UI, ensure that this is done in UI thread
Dispatcher.Invoke(() =>
{
Percentage.Text = job.Progress > 0 ? $"{job.Progress.ToString()} %" : string.Empty;
});
};
// Execute job and wait until the map has been taken offline
GenerateOfflineMapResult results = await job.GetResultAsync();
// Set offline map from the results
offlineMap = results.OfflineMap;
#endregion
}
catch (TaskCanceledException)
{
// Thrown if the operation was cancelled
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Taking map offline failed.");
}
// Return offline map or null if taking the map offline failed
return offlineMap;
}
private string _username = "username";
private string _password = "password";
private async Task<Credential> CreateKnownCredentials(CredentialRequestInfo info)
{
// If this isn't the expected resource, the credential will stay null
Credential knownCredential = null;
try
{
// Create a credential for this resource
knownCredential = await AuthenticationManager.Current.GenerateCredentialAsync
(info.ServiceUri,
_username,
_password,
info.GenerateTokenOptions);
}
catch (Exception ex)
{
// Report error accessing a secured resource
MessageBox.Show("Access to " + info.ServiceUri.AbsoluteUri + " denied. " + ex.Message, "Credential Error");
}
// Return the credential
return knownCredential;
}
}
}
<Window x:Class="WaterNetworkDemo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:esri="http://schemas.esri.com/arcgis/runtime/2013"
xmlns:local="clr-namespace:WaterNetworkDemo"
xmlns:converters="clr-namespace:WaterNetworkDemo.DataConverters"
mc:Ignorable="d"
Title="MainWindow" Height="525" Width="790">
<Grid>
<esri:MapView x:Name="MyMapView"/>
<TextBlock x:Name="mapNoAvailable" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="18"
Text="Map isn't currently available." Visibility="Collapsed"></TextBlock>
<Grid x:Name="busyIndicator" Background="#807f7f7f" Visibility="Collapsed">
<Grid HorizontalAlignment="Center" VerticalAlignment="Center">
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<TextBlock Foreground="White" Margin="10" FontSize="18" HorizontalAlignment="Center" VerticalAlignment="Center">
<Run Text="Generating offline map... "></Run>
<Run x:Name="Percentage" Text=""></Run>
</TextBlock>
<ProgressBar x:Name="progressBar" Minimum="0" Maximum="100"
IsEnabled="True" IsIndeterminate="True" Width="100" HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Row="1" Height="10" Margin="0,0,0,10"/>
</Grid>
</Grid>
<Grid x:Name="loadingIndicator" Background="#807f7f7f" Visibility="Visible">
<Grid HorizontalAlignment="Center" VerticalAlignment="Center">
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<TextBlock Text="Loading online map..." Foreground="White" Margin="10" FontSize="18"/>
<ProgressBar IsEnabled="True" IsIndeterminate="True" Width="100" Height="10" HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Row="1"/>
</Grid>
</Grid>
</Grid>
</Window>
... View more
07-13-2017
02:48 AM
|
2
|
1
|
1940
|
|
POST
|
Hi Mark, I'm not aware a way to that without loading the metadata for the table since the layer doesn't have any information about it's content before that is done. If you are using MMPKs the loading operation shouldn't be too expensive since no network calls are done at that point.
... View more
07-13-2017
02:16 AM
|
0
|
11
|
6249
|
|
POST
|
It seems that this got answered in https://community.esri.com/thread/197650-popups-in-xamarin-android topic.
... View more
07-12-2017
03:25 AM
|
1
|
0
|
4880
|
|
POST
|
Hi Joe, Thanks for the feedback and this is actually something that we are now working with. It sounds like you have built very similar system yourself that we have been doing. In first roll out of OfflineMapTask we targeted to support Collector style ad-hoc or on-demand workflows and on a next phase we are we working to get a proper support to get pre-planned workflow. Where the ad-hoc or on-demand workflow generates all the used packages and creates the local copy of the map after the task is called, the pre-planned worklow will have a management UI built into the ArcGIS Online which handles the generation before the data needs to be downloaded to the clients. On runtime side, we are adding functionality to query and download these areas. If you can, could you share the requirements for the workflow with me? You could send it to my email (akajanus@esri.com). The pre-planned workflow is targeting to provide a framework that you can use in ArcGIS to define the areas that you want to take offline, create the packages, update them and ultimately download them to the clients. This will make the workflow a bit like a desktop workflow if you have seen our presentations or documentation where we have been describing the patterns before but supports synchronization. We know that if we want to create 500+ users on-demand offline package at 9 in the morning on Monday, servers wont be very pleased with it. Instead we can create the needed packages before that and only thing that users needs to do is to download the needed offline map (area). As you said, the offline map is nothing really special, it's just a folder that contains the definition files (.info / .mmap) and then the needed data for it. It's actually using the same specification with MobileMapPackages but just as an exploded format. At the moment you can use underlying sync tasks to register the geodatabases to the services as you mentioned. I think that we will still have the issue with large packages if the areas are large and they contain a lot of layers (with attachments) and you want to get everything downloaded to the client. Using vector tiles will make that better but ultimately it's a map design question. If the area is large and it contains a lot of data and tons of attachments, the size of the package will reflect that - no matter how the offline map is created. We try to get a good mix of easy to use, versatility and performance build into the tasks so you would have a good range of setting to optimize the package for your needs. Granted this does mean we sync the same data multiple times because those duplicated layers are synced individually, however, there is really no way (that I see) around that. Yes, this is why we omitted the support for multiple layers pointing into the same Feature Service endpoint for now. This is one of the points where we want to get more user feedback. When we create the offline map, we create only one geodatabase per Feature Service and that won't allow us to have multiple layers which would be handy in many cases. Do you think that it's reasonable hit to download the same data multiple times if needed to get the support for this? It would work ok in cases where you for example define expression on webmap to take only part of the data offline. At the moment you can point into the same underlying data for example by using a 'View' in ArcGIS Online (which generates a new rest endpoint but references the same data with other service) but if you use a layer level override (which only references the same rest endpoint), it won't work. They key here is the different url endpoint. Hopefully the OfflineMapTask and OfflineMapSyncTask comes in handy for many of the users who are building offline apps and as mentioned earlier we welcome all feedback. What should be supported? Does the classes actually make your life easier? Do you have workflows that cannot be solved with the current APIs? And so forth, the more feedback we get the better calls we can make for what is actually needed on the field.
... View more
07-11-2017
04:17 AM
|
1
|
0
|
817
|
|
POST
|
Do you see credentials being created? If you check knownCredential does it have token assigned to it?
... View more
06-22-2017
05:34 AM
|
0
|
1
|
448
|
|
POST
|
Can you try if this works? Just change it to use your credentials. public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
AuthenticationManager.Current.ChallengeHandler = new ChallengeHandler(CreateKnownCredentials);
Initialize();
}
private async void Initialize()
{
try
{
var task = await ExportTileCacheTask.CreateAsync(new Uri("https://tiledbasemaps.arcgis.com/arcgis/rest/services/World_Street_Map/MapServer"));
}
catch (Exception ex)
{
// Something unexpected happened, handle properly
MessageBox.Show(ex.Message);
}
}
private string _username = "abcd";
private string _password = "1234";
private async Task<Credential> CreateKnownCredentials(CredentialRequestInfo info)
{
// If this isn't the expected resource, the credential will stay null
Credential knownCredential = null;
try
{
// Create a credential for this resource
knownCredential = await AuthenticationManager.Current.GenerateCredentialAsync
(info.ServiceUri,
_username,
_password,
info.GenerateTokenOptions);
}
catch (Exception ex)
{
// Report error accessing a secured resource
MessageBox.Show("Access to " + info.ServiceUri.AbsoluteUri + " denied. " + ex.Message, "Credential Error");
}
// Return the credential
return knownCredential;
}
}
... View more
06-22-2017
03:01 AM
|
0
|
3
|
2141
|
|
POST
|
Can you sign into the ArcGIS Online with your credentials? If you sign in to https://www.arcgis.com/home/signin.html does the authentication go through without any problems?
... View more
06-22-2017
01:41 AM
|
0
|
5
|
2141
|
|
POST
|
You can see more about authentication from Use the Authentication Manager—ArcGIS Runtime SDK for .NET | ArcGIS for Developers or have a look to the samples arcgis-runtime-samples-dotnet/src/WPF/ArcGISRuntime.WPF.Samples/Samples/Security at master · Esri/arcgis-runtime-samples…
... View more
06-21-2017
06:28 AM
|
0
|
8
|
2141
|
|
POST
|
That is expected if you haven't signed in to ArcGIS Online since the export tiles feature is available to subscribed users (operation doesn't consume credits but you have to be signed in to have a access to it).
... View more
06-21-2017
06:23 AM
|
0
|
9
|
2141
|
|
POST
|
Hi, Can you give the exact code / url that you are using? Following seems to work without any problems. var task = await ExportTileCacheTask.CreateAsync(
new Uri("https://tiledbasemaps.arcgis.com/arcgis/rest/services/World_Street_Map/MapServer"));
Remember that you shouldn't use the service "For export" services as your basemaps, they are intended to be used for taking tiles offline and not visualization.
... View more
06-21-2017
05:46 AM
|
0
|
11
|
2141
|
|
POST
|
Have you tried to see if using the functions that will do identify to all operational layers in one go and compared how that does affect the performance? Do you have performance problems both in Debug and Release modes? GeoView.IdentifyLayersAsync Method (Point, Double, Boolean, Int64, CancellationToken)
... View more
06-19-2017
04:49 AM
|
0
|
1
|
2374
|
|
POST
|
Hi Karin, The new offline functionality isn't going to help with this issue. I think that this is very important workflow but unfortunately we don't have a proper support for this in current API. Could you provide more details on the use case so I can take that forward to the product group. The more details you can share of your workflow and use case you can provide, would help me to argue to get the proper support in easier for me. If you cannot or want to share this publicly you can send it to me to akajanus@esri.com. I'll have a look if there is a good way to implement this with the current API but I think that is going to involve quite a bit of code.
... View more
06-19-2017
03:14 AM
|
0
|
0
|
1014
|
| Title | Kudos | Posted |
|---|---|---|
| 1 | 11-12-2014 03:52 AM | |
| 1 | 08-27-2015 03:47 AM | |
| 1 | 12-08-2014 09:58 AM | |
| 1 | 05-05-2015 10:19 AM | |
| 1 | 07-30-2015 08:43 AM |
| Online Status |
Offline
|
| Date Last Visited |
11-11-2020
02:23 AM
|