Hesoyam is a cross-platform background task scheduler for .NET MAUI that enables scheduling and executing tasks even when the application is closed. Supports Android (WorkManager), iOS (BGTaskScheduler), macOS Catalyst (BGTaskScheduler), and Windows (BackgroundTaskBuilder). Features include periodic/one-shot/immediate scheduling, network/charging/battery constraints, automatic retries with exponential backoff, state persistence across app restarts and device reboots, and full AOT/Trimming compatibility.
$ dotnet add package HesoyamA cross-platform background task scheduler for .NET MAUI applications. Hesoyam enables you to schedule and execute background tasks that run even when your application is closed.
| Platform | Technology | Minimum Version |
|---|---|---|
| Android | WorkManager | API 21 (Android 5.0) |
| iOS | BGTaskScheduler | iOS 15.0 |
| macOS Catalyst | BGTaskScheduler | macOS 15.0 |
| Windows | BackgroundTaskBuilder | Windows 10 1809 |
dotnet add package Hesoyam
// MauiProgram.cs
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp<App>()
.UseHesoyam();
// Register your background tasks
builder.Services.AddBackgroundTask<DataSyncTask>();
public class DataSyncTask : IBackgroundTask
{
private readonly IDataService _dataService;
public DataSyncTask(IDataService dataService)
{
_dataService = dataService;
}
public async Task ExecuteAsync(ITaskContext context, CancellationToken cancellationToken)
{
// Report progress
await context.ReportProgressAsync("Starting sync...");
// Do your work
await _dataService.SyncAsync(cancellationToken);
// Save state for resumable tasks
await context.SetStateAsync("lastSync", DateTime.UtcNow);
}
}
var scheduler = services.GetRequiredService<ITaskScheduler>();
var config = new TaskConfiguration
{
Identifier = "data-sync",
Type = TaskType.Periodic,
Interval = TimeSpan.FromHours(1),
NetworkRequirement = NetworkType.Connected,
PersistAcrossReboots = true
};
await scheduler.ScheduleAsync<DataSyncTask>(config);var config = new TaskConfiguration
{
// Required: Unique task identifier
Identifier = "my-task",
// Scheduling
Type = TaskType.Periodic, // OneShot, Periodic, Immediate
Interval = TimeSpan.FromHours(1), // For periodic tasks
InitialDelay = TimeSpan.FromMinutes(5),
// Constraints
NetworkRequirement = NetworkType.Connected, // None, Connected, Unmetered, WiFi
RequiresCharging = false,
RequiresDeviceIdle = false,
RequiresBatteryNotLow = false,
// Retry Policy
MaxRetries = 3,
InitialRetryDelay = TimeSpan.FromSeconds(30),
RetryBackoffMultiplier = 2.0,
// Other
ExecutionTimeout = TimeSpan.FromMinutes(10),
PersistAcrossReboots = true,
Tags = ["sync", "user-data"],
Metadata = new() { ["userId"] = "12345" }
};// Check if scheduled
bool isScheduled = await scheduler.IsScheduledAsync("data-sync");
// Get status
TaskExecutionStatus? status = await scheduler.GetStatusAsync("data-sync");
// Cancel by identifier
await scheduler.CancelAsync("data-sync");
// Cancel by tag
int cancelled = await scheduler.CancelByTagAsync("sync");
// Cancel all
int total = await scheduler.CancelAllAsync();
// Get all scheduled tasks
IReadOnlyList<string> tasks = await scheduler.GetScheduledTasksAsync();RECEIVE_BOOT_COMPLETED permission for reboot persistenceBGTaskSchedulerPermittedIdentifiers in Info.plistMIT License - see LICENSE file for details.