POST
|
Thanks for your reply @JoeHershman . The platform is iOS. The goal was to create an offline, local version of the feature service that we could use for display on map and edit attributes for. After consideration of client requirements, we decided that geodatabase sync with replica is too much of a headache to create client-side and/or download from REST. The solution we settled on is to create a local geodatabase with custom TableDescription created from FeatureService and populated with features from the service. To edit features (still being developed), I think we will use ApplyEdits instead of syncing with the service.
... View more
03-21-2025
01:55 PM
|
0
|
0
|
110
|
POST
|
@dotMorten_esri After discussing with my client, it seems like they want the ability to download pre-created (created from server, not mobile) replicas to the mobile app. Allowing hundreds of field workers to each create replicas is unmanageable when taking into account the bi-weekly data sync workflows I mentioned in my earlier comment. So they want to create replicas server-side and then the mobile app goes and downloads them. This is more an enterprise question and less a Maps SDK issue at this point, so I'm in the wrong place, but... Is there any way to download replica .geodatabase using REST request? I searched around the replica REST page and I can't find a way to do this.
... View more
03-12-2025
05:37 PM
|
0
|
0
|
524
|
POST
|
Ok, the syncId property is exactly what I was looking for. Yes, we query REST endpoints elsewhere in the app, so we're fine with those workflows. I think I searched for replicaId in the docs, and got zero results. I'll be going with this workflow instead. Thank you for pointing it out!
... View more
03-12-2025
02:11 PM
|
0
|
0
|
532
|
POST
|
We'd like to sync local changes to the service as well, but we were planning on using the SDK's ApplyEdits if the geodatabase replica workflow didn't pan out. I think preplanned workflow is out of the question because we don't know which areas of the map users will be performing work in. I think the best solution we have right now is a custom implementation of local databases that store attribute and geometry data: On first app-start, create local .sqlite database with table from FeatureService tables. Probably create a separate field for geometry and a single field to capture all fields-values as key-value pairs. This will give us all the features in the table saved locally. On the map page, create features from locally saved data and add as FeatureLayer items with client-side rendering. For user to edit this layer data while offline, we save the new attributes and geometry back to the table (or even a new table) and then use ApplyEdits to the service when the device is back online. On every app-start, I would like to not download all data from scratch everytime, so I'll probably use FeatureRequestMode enum and PopulateFromServiceAsync() method. Needs some looking into on my part
... View more
03-12-2025
12:20 PM
|
0
|
3
|
543
|
POST
|
We were able to create geodatabase replicas using Feature Service URLs. And these replicas show up on Enterprise in the list of replicas for the service. Great! But the problem is that the client has some complex workflows around data-sync between different staging environments that requires deleting all replicas and recreating them every few weeks. If the replicas are re-created, there is no way to associate the device-local geodatabase replicas to their replica-pairs in Enterprise. When we check the replica page, we see Replica name, ID, version etc. It seems like we cannot use Maps SDK for .NET to query any of this information. Furthermore, I cannot use the Geodatabase class to get the name or ID of replica in server that was just created. Am I correct? Is there a way to get replica ID using the SDK? Basically, there seems to be no way to know which device-local geodatabase replica is associated with which replica in the server. Thanks! Any insight appreciated!
... View more
03-12-2025
11:06 AM
|
0
|
5
|
555
|
POST
|
Thank you for your response @MarkBockenhauer . Assuming all the layers in the client's webmap are approved for offline use... If we were to take the webmap offline, we'd have to use an on-demand workflow, due to the different map areas that users would need to take offline. But also not sure how scalable this solution is to a large number of users, each of whom would need to take a different area offline.
... View more
03-12-2025
07:54 AM
|
0
|
0
|
579
|
POST
|
I have a requirement for my .NET MAUI application that I need to access a feature service from the client's Enterprise Portal and make it available to the user when their device is offline later. I started with geodatabase as a potential solution, but creating and managing replicas turned out to be a bigger headache for the client than I thought. Otherwise, geodatabases would've been a perfect solution. Is there a way to create a geodatabase with a feature service WITHOUT creating a replica? I won't use MMPKs, because I just need to take a single layer online. There are also other requirements for the application that prevents us from using MMPKs here. Is my best option to create a ServiceFeatureTable and then export the features to a custom .sqlite database and then load them into the map page? Or is this a workflow better done using REST to export features from the service to a .geojson and then somehow load them into the map? Thanks for the help! I would be at DevSummit this week asking the Maps SDK team myself, but unfortunately, couldn't make it out there this year. Community ESRI is the next best option!
... View more
03-11-2025
08:49 AM
|
0
|
11
|
742
|
POST
|
I'm using the Pro SDK to package up a python toolbox for distribution with my userbase. I use the directions given in the docs here to embed the .py files in the required project structure and use a button from the SDK to execute the toolbox (ExecuteToolAsync method). Here's the problem. When the add-in loads, the contents of my Toolboxes folder is directly copied to \Users\<username>\AppData\Local\ESRI\ArcGISPro\Toolboxes. Anyone who reads the docs knows to navigate to this location and access the python code. But I don't want to expose my python code to users. What are my options if I want to ship a single .addInX file to users that also contains a .pyt, without revealing my business logic? The python code is written with several machine learning libraries, so it's not feasible to rewrite the python code in C#. Thanks!
... View more
01-07-2025
12:56 PM
|
0
|
1
|
562
|
POST
|
Thanks! The SDK makes it incredible simple for iOS for location tracking. Hopefully similar things in store for Android soon 🤞 I'm out of the office, so getting my colleague and fellow developer @SeanS to move this forward. Thanks for your help!
... View more
12-16-2024
07:56 AM
|
0
|
1
|
402
|
POST
|
Thanks @dotMorten_esri ! With some elbow grease, we've managed to get background location tracking working on Android with Foreground service. When I get a chance (probably not anytime soon), I will update my Github repo with the code we used. Meanwhile here is what we used in LocationService.cs that we added to Platforms/Android directory using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using AndroidX.Core.App;
using Esri.ArcGISRuntime.Location;
using Microsoft.Maui.Controls.Compatibility.Platform.Android;
using Microsoft.Maui.Devices.Sensors;
using Resource = Microsoft.Maui.Resource;
using Location = Esri.ArcGISRuntime.Location.Location;
namespace MyApp.Platforms.Android.LS;
[Service(ForegroundServiceType = global::Android.Content.PM.ForegroundService.TypeLocation)]
public class LocationService : Service
{
public override IBinder OnBind(Intent intent) => null;
public event EventHandler<Location> LocationUpdated;
int count = 0;
public LocationDataSource locationDataSource;
private async void OnLocationChanged(Location newLocation)
{
LocationUpdated?.Invoke(this, newLocation);
}
public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
{
StartForeground(1, CreateNotification());
var locationIntent = new Intent(this, typeof(LocationService));
if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
{
StartForegroundService(locationIntent);
}
else
{
StartService(locationIntent);
}
return StartCommandResult.Sticky;
}
private Notification CreateNotification()
{
// don't really need notifications for our app, but examples online used it
var channelId = "location_notification";
var channelName = "Location Tracking";
var notificationManager = (NotificationManager)GetSystemService(NotificationService);
var channel = new NotificationChannel(channelId, channelName, NotificationImportance.Default);
notificationManager.CreateNotificationChannel(channel);
var notification = new NotificationCompat.Builder(this, channelId)
.SetContentTitle("Location Tracking")
.SetContentText("Tracking location in the background")
//.SetSmallIcon(Resource.Drawable.icon)
.Build();
return notification;
}
public async Task<LocationDataSource> StartLocationUpdates()
{
locationDataSource = new SystemLocationDataSource();
PermissionStatus status = await Permissions.CheckStatusAsync<Permissions.LocationWhenInUse>();
if (status == PermissionStatus.Denied || status == PermissionStatus.Unknown)
{
await Shell.Current.DisplayAlert("Access Requested", "Please allow precise location all the time to track while phone is locked or viewing other applications.", "OK");
status = await Permissions.RequestAsync<Permissions.LocationWhenInUse>();
}
if (status != PermissionStatus.Granted)
{
return null;
}
await locationDataSource.StartAsync();
locationDataSource.LocationChanged += async (sender, e) => OnLocationChanged(e);
return locationDataSource;
}
} We call StartLocationUpdates() from the MapPage.xaml.cs and set LocationDataSource await this.locationService.StartLocationUpdates();
mapViewModel.locationDataSource = this.locationService.locationDataSource;
if (mapViewModel.locationDataSource.Status == LocationDataSourceStatus.Started)
{
MyMapView.LocationDisplay.DataSource = mapViewModel.locationDataSource;
MyMapView.LocationDisplay.IsEnabled = status == PermissionStatus.Granted || status == PermissionStatus.Restricted;
MyMapView.LocationDisplay.InitialZoomScale = 1000;
MyMapView.LocationDisplay.AutoPanMode = LocationDisplayAutoPanMode.Recenter;
}
this.locationService.LocationUpdated += async (sender, e) => await LocationUpdated(sender, e); Works like a dream when it's not killing the battery. We're working on implementing this in iOS right now with CLLocation
... View more
12-12-2024
08:33 AM
|
0
|
4
|
2249
|
POST
|
Thanks @dotMorten_esri ! With some elbow grease, we've managed to get background location tracking working on Android with Foreground service. When I get a chance (probably not anytime soon), I will update my Github repo with the code we used. Meanwhile here is what we used in LocationService.cs that we added to Platforms/Android directory using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using AndroidX.Core.App;
using Esri.ArcGISRuntime.Location;
using Microsoft.Maui.Controls.Compatibility.Platform.Android;
using Microsoft.Maui.Devices.Sensors;
using Resource = Microsoft.Maui.Resource;
using Location = Esri.ArcGISRuntime.Location.Location;
namespace MyApp.Platforms.Android.LS;
[Service(ForegroundServiceType = global::Android.Content.PM.ForegroundService.TypeLocation)]
public class LocationService : Service
{
public override IBinder OnBind(Intent intent) => null;
public event EventHandler<Location> LocationUpdated;
public LocationDataSource locationDataSource;
private async void OnLocationChanged(Location newLocation)
{
LocationUpdated?.Invoke(this, newLocation);
}
public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
{
StartForeground(1, CreateNotification());
var locationIntent = new Intent(this, typeof(LocationService));
if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
{
StartForegroundService(locationIntent);
}
else
{
StartService(locationIntent);
}
return StartCommandResult.Sticky;
}
private Notification CreateNotification()
{
// don't really need notifications for our app, but examples online used it
var channelId = "location_notification";
var channelName = "Location Tracking";
var notificationManager = (NotificationManager)GetSystemService(NotificationService);
var channel = new NotificationChannel(channelId, channelName, NotificationImportance.Default);
notificationManager.CreateNotificationChannel(channel);
var notification = new NotificationCompat.Builder(this, channelId)
.SetContentTitle("Location Tracking")
.SetContentText("Tracking location in the background")
//.SetSmallIcon(Resource.Drawable.icon)
.Build();
return notification;
}
public async Task<LocationDataSource> StartLocationUpdates()
{
locationDataSource = new SystemLocationDataSource();
PermissionStatus status = await Permissions.CheckStatusAsync<Permissions.LocationWhenInUse>();
if (status == PermissionStatus.Denied || status == PermissionStatus.Unknown)
{
await Shell.Current.DisplayAlert("Access Requested", "Please allow precise location all the time to track while phone is locked or viewing other applications.", "OK");
status = await Permissions.RequestAsync<Permissions.LocationWhenInUse>();
}
if (status != PermissionStatus.Granted)
{
return null;
}
await locationDataSource.StartAsync();
locationDataSource.LocationChanged += async (sender, e) => OnLocationChanged(e);
return locationDataSource;
}
} We call StartLocationUpdates() from the MapPage.xaml.cs and set LocationDataSource await this.locationService.StartLocationUpdates();
mapViewModel.locationDataSource = this.locationService.locationDataSource;
if (mapViewModel.locationDataSource.Status == LocationDataSourceStatus.Started)
{
MyMapView.LocationDisplay.DataSource = mapViewModel.locationDataSource;
MyMapView.LocationDisplay.IsEnabled = status == PermissionStatus.Granted || status == PermissionStatus.Restricted;
MyMapView.LocationDisplay.InitialZoomScale = 1000;
MyMapView.LocationDisplay.AutoPanMode = LocationDisplayAutoPanMode.Recenter;
}
this.locationService.LocationUpdated += async (sender, e) => await LocationUpdated(sender, e); Works like a dream when it's not killing the battery. We're working on implementing this in iOS right now with CLLocation.
... View more
12-12-2024
08:04 AM
|
1
|
1
|
2230
|
POST
|
@PreetiMaske Here is a project on Github you can pull and run yourself: https://github.com/Cesium133/.netmaui-display-device-location I created this from the Display Device Location sample you provided and the Show Location History sample from the Maps SDK team. You will see that if you run this on a physical device, the location will not update if the app is suspended or minimized. Please let me know what else you may need to help us debug this issue! Thanks!
... View more
12-06-2024
05:09 PM
|
2
|
8
|
2362
|
POST
|
Hi @PreetiMaske , thank you for your reply. It's great to have your support on this issue. We are using 200.6.0 of Esri.ArcGISRuntime.Maui and are upgraded on pretty much all Nuget packages. I should apologize and say I neglected to include all Android permissions I'm using in the original post. I updated my post to reflect all permissions we're requesting in Android that are location related. As you can see, we are requesting FINE_LOCATION and COARSE_LOCATION permissions. I pulled the sample app you linked to and ran it locally. I'm experiencing the same issue with this sample, because the issue is NOT with being able to access user's location while the app is running in the foreground. The problem arises when the user needs to shut the screen off and hike with the phone in their pocket, or switch apps to take a picture of a squirrel. When they have to do this, the location stops being tracked. If you look at the below screenshot, the purple graphic shows the route the user takes with the phone in their pocket. There are sharp cuts to the user's current location when they turn their screen back on and go back to the app. In other words, the application only records location in the foreground. I notice that in the sample you provided, ACCESS_BACKGROUND_LOCATION permission is not enabled, implying it was meant to run only in the foreground. Are there are any samples out there for getting this info from the device on a background thread or using background/foreground services perhaps? I will try and upload a more complete solution of just this tracking feature from my application to a new repo, so you can pull it and check the code yourself. Thank you for your help! 🙂
... View more
12-06-2024
03:17 PM
|
2
|
0
|
2363
|
POST
|
This may not exactly be a question about the Maps SDK for .NET, but given that it's a .NET MAUI app that uses the SDK and location services, I thought I'd probe the mobile dev community for advice. I have a .NET MAUI app with a map page that I'm using to track the location of the user on a map. It basically shows the breadcrumb path the user has taken on their hike with a dashboard showing their distance, timer and average speed. It works exactly as it should when the screen is turned on and the app is on the foreground: path updates when location is changed and dashboard metrics change as expected. But when the app is minimized/suspended, or if another app is being used, or if the screen is turned off, location stops being tracked. And the timer pauses in the background as well. I restructured some of this code for location tracking to work on a background thread like following, but no changes in results. mapViewModel.locationDataSource.LocationChanged += async (sender, e) => await LocationChanged(sender, e); // call LocationChanged method when location changes in LocationDataSource
private async Task LocationChanged(object sender, Esri.ArcGISRuntime.Location.Location e)
{
await Task.Run(() => {
MapPoint mp = e.Position;
UpdatePolyline(mp)
}
private void UpdatePolyline(MapPoint mp)
{
polylineBuilder.AddPoint(mp);
Geometry polylineGeometry = polylineBuilder.ToGeometry();
// UI updates marshaled to the main thread.
MainThread.BeginInvokeOnMainThread(() =>
{
trackedHikePolylineGraphicsOverlay.Graphics.Clear();
trackedHikePolylineGraphicsOverlay.Graphics.Add(new Graphic(polylineGeometry));
});
} I've also added these permissions to my AndroidManifest.xml <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> I will also need to add similar permissions to the .plist for iOS permissions. Not sure what they are yet. What have other developers done to implement background location tracking in their .NET MAUI apps? I know Android and iOS apps can do this, because I can record a manual activity in Strava while my screen is turned off. Permissions for my Maui app is set to "Allow location all the time" for Precise location. Thanks in advance!
... View more
12-05-2024
09:57 AM
|
2
|
11
|
2781
|
POST
|
Thanks @dotMorten_esri . Is HorizontalAccuracy something I have to test on the field with trial and error to see what the appropriate threshold is for different devices and platforms? Or is there a generally accepted accuracy to check against?
... View more
12-04-2024
09:28 AM
|
0
|
2
|
989
|
Title | Kudos | Posted |
---|---|---|
1 | 12-12-2024 08:04 AM | |
2 | 12-06-2024 05:09 PM | |
2 | 12-06-2024 03:17 PM | |
2 | 12-05-2024 09:57 AM | |
1 | 06-07-2023 10:06 AM |
Online Status |
Offline
|
Date Last Visited |
3 weeks ago
|