MAUI: iOS: Issue with backgrounding to send location on every 10 seconds

Sreejith Sreenivasan 1,001 Reputation points
2025-05-13T16:34:35.6966667+00:00

I want to send the user's location to MQTT in all modes (background, foreground or device locked) from my MAUI application. I have implemented it on Android platform using the foreground services.

Now I want to implement the same on iOS platform and I did below integrations.

Added ILocationService interface in single project:

public interface ILocationService
{
    void StartLocationUpdates();
    void StopLocationUpdates();
}

IosLocationService in platform/ios: From here I am sending the user's location details to MQTT on every 10 seconds

public class IosLocationService : CLLocationManagerDelegate, ILocationService
{
    CLLocationManager locationManager;

    public void StartLocationUpdates()
    {
        locationManager = new CLLocationManager();
        locationManager.Delegate = this;

        locationManager.DesiredAccuracy = CLLocation.AccuracyBest;
        locationManager.DistanceFilter = 10; // minimum distance change
        locationManager.AllowsBackgroundLocationUpdates = true;
        locationManager.PausesLocationUpdatesAutomatically = false;
        locationManager.RequestAlwaysAuthorization();
        locationManager.StartUpdatingLocation();
    }

    [Export("locationManager:didUpdateLocations:")]
    public async void UpdatedLocation(CLLocationManager manager, CLLocation[] locations)
    {
        var location = locations?.LastOrDefault();
        if (location == null)
            return;

        Preferences.Default.Set("latitude", location.Coordinate.Latitude.ToString());
        Preferences.Default.Set("longitude", location.Coordinate.Longitude.ToString());
        Preferences.Default.Set("speed", location.Speed.ToString());
        Preferences.Default.Set("direction", GetCompassDirection(location?.Course));

        if (Preferences.Default.Get("islogin", "") == "true")
        {
            string userId = Preferences.Default.Get("userId", "");
            string latitude = Preferences.Default.Get("latitude", "");
            string longitude = Preferences.Default.Get("speed", "");
            string speed = Preferences.Default.Get("userId", "");
            string direction = Preferences.Default.Get("direction", "");
            long timestamp = DateTime.Now.MillisecondsTimestamp();

            string groupId = Preferences.Default.Get("groupId", "");
            string message = $"{{" +
                    $"\"userId\": \"{userId}\"," +
                    $"\"ts\": {timestamp}," +
                    $"\"latitude\": {latitude}," +
                    $"\"longitude\": {longitude}," +
                    $"\"speed\": {speed}," +
                    $"\"direction\": \"{direction}\"" +
                    $"}}";

            _ = MqttService.Instance.PublishMessage("alertbuddies/live-location/" + groupId, message);
        }
    }

    string GetCompassDirection(double? course)
    {
        if (!course.HasValue)
            return "Unknown";

        double heading = course.Value;

        string[] directions = { "N", "NE", "E", "SE", "S", "SW", "W", "NW", "N" };
        int index = (int)Math.Round(heading / 45.0);
        return directions[index];
    }


    public void StopLocationUpdates()
    {
        locationManager?.StopUpdatingLocation();
    }
}

Entitlements.plist.xaml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
    <dict>
        <key>aps-environment</key>
        <string>development</string>
        <key>com.apple.background-mode</key>
        <array>
            <string>location</string>
        </array>
    </dict>
</plist>

Info.plist

<key>UIBackgroundModes</key>
<array>
    <string>remote-notification</string>
    <string>location</string>
</array>

MauiProgram.cs:

        builder.Services.AddSingleton<ILocationService>(serviceProvider =>
        {
#if IOS
            return new IosLocationService();
#else
            return null;
#endif
        });

And I start the background service from home like below:

#if IOS
        var locationService = MauiUIApplicationDelegate.Current.Services.GetService<ILocationService>();
        locationService?.StartLocationUpdates();
#endif

After integrating bakgrounding the location details are sending to MQTT on all modes, but the time interval is not correct. I set 10 seconds as the time interval but when the app is in background or locked the time interval is more than 1 minute.

In foreground mode the message correctly publishing on every 10 seconds. Issue I am facing is only on background and locked states.

Developer technologies .NET .NET MAUI
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. Bruce (SqlWork.com) 77,686 Reputation points Volunteer Moderator
    2025-05-13T21:30:46.2866667+00:00

    when your IOS app is in background, to preserve battery, there are several restrictions on network access. this will include how often, and how much data. your app should cache the data, and make less frequent updates. (android typically follows IOS battery saving, so I expect them to do the same at some point).

    sending network traffic every 10 seconds is way too much. You should switch to a cache even if in foreground.

    note: background access to network is a permission I seldom able for an app. I'd probably not enable location services either.

    1 person found this answer helpful.
    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.