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.