Reputation: 107
//from app.xaml.cs protected override void OnSleep() { void ScheduleNotification() { // Start a timer that runs after 5 seconds. Device.StartTimer(TimeSpan.FromSeconds(5), () => { System.Threading.Tasks.Task.Factory.StartNew( () => { // Do the actual request and wait for it to finish. PerformNotification(); // Switch back to the UI thread to update the UI Device.BeginInvokeOnMainThread(() => { // Update the UI // ... // Now repeat by scheduling a new request ScheduleNotification(); count++; }); }, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); // Don't repeat the timer (we will start a new timer when the request is finished) return false; }); } void PerformNotification() { CrossLocalNotifications.Current.Show("title", "body"+ count.ToString()); } ScheduleNotification(); }
Upvotes: 4
Views: 9226
Reputation: 547
On iOS, apps that don't request to be run in the Background, can not run in the Background for longer than 10 seconds. In order to make some code run in the Background you could implement a DependencyService on iOS and on android. You would put the following code inside that service on iOS:
public async Task RunCodeInBackgroundMode(Func<Task> action, string name = "MyBackgroundTaskName")
{
nint taskId = 0;
var taskEnded = false;
taskId = UIApplication.SharedApplication.BeginBackgroundTask(name, () =>
{
//when time is up and task has not finished, call this method to finish the task to prevent the app from being terminated
Console.WriteLine($"Background task '{name}' got killed");
taskEnded = true;
UIApplication.SharedApplication.EndBackgroundTask(taskId);
});
await Task.Factory.StartNew(async () =>
{
//here we run the actual task
Console.WriteLine($"Background task '{name}' started");
await action();
taskEnded = true;
UIApplication.SharedApplication.EndBackgroundTask(taskId);
Console.WriteLine($"Background task '{name}' finished");
});
await Task.Factory.StartNew(async () =>
{
//Just a method that logs how much time we have remaining. Usually a background task has around 180 seconds to complete.
while (!taskEnded)
{
Console.WriteLine($"Background task '{name}' time remaining: {UIApplication.SharedApplication.BackgroundTimeRemaining}");
await Task.Delay(1000);
}
});
}
On Android you could use the following code:
public async Task RunCodeInBackgroundMode(Func<Task> action, string name = "MyBackgroundTaskName")
{
var powerManager = (PowerManager)Application.Context.GetSystemService(Context.PowerService);
var wakeLock = powerManager.NewWakeLock(WakeLockFlags.Partial,
name);
//acquire a partial wakelock. This prevents the phone from going to sleep as long as it is not released.
wakeLock.Acquire();
var taskEnded = false;
await Task.Factory.StartNew(async () =>
{
//here we run the actual code
Console.WriteLine($"Background task '{name}' started");
await action();
Console.WriteLine($"Background task '{name}' finished");
wakeLock.Release();
taskEnded = true;
});
await Task.Factory.StartNew(async () =>
{
//just a method to keep track of how long the task runs
var stopwatch = new Stopwatch();
stopwatch.Start();
while (!taskEnded)
{
Console.WriteLine($"Background '{name}' task with wakelock still running ({stopwatch.Elapsed.TotalSeconds} seconds)");
await Task.Delay(1000);
}
stopwatch.Stop();
});
}
Inside the shared project, you could call those methods in the following way:
var deviceInfoServic = ServiceLocator.Instance.Get<YourService Interface here>();
await deviceInfoServic.RunCodeInBackgroundMode(async () =>
{
//your code here
});
Upvotes: 3