【发布时间】:2018-02-19 15:32:27
【问题描述】:
我们无法让后台服务正常工作。即使应用程序关闭并且手机被锁定,计时器也应该每秒执行一次代码。只要应用程序处于打开状态或在后台并且手机正在使用中,此功能就可以正常工作,但是当手机处于锁定状态并处于待机状态时,服务会在一段时间后自动停止。
代码仿照本例:http://arteksoftware.com/backgrounding-with-xamarin-forms/
这段代码在MainActivity中执行:
MessagingCenter.Subscribe<StartBackgroundTimer>(this, "StartBackgroundTimer", message =>
{
var intent = new Intent(this, typeof(LongRunningTaskService));
StartService(intent);
});
MessagingCenter.Subscribe<StopBackgroundTimer>(this, "StopBackgroundTimer", message =>
{
var intent = new Intent(this, typeof(LongRunningTaskService));
StopService(intent);
});
这是 LongRunningTaskService 类:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using System.Threading;
using System.Threading.Tasks;
using OurAppNamespace.Classes;
using Xamarin.Forms;
namespace OurAppNamespace.Droid
{
[Service]
public class LongRunningTaskService : Service
{
CancellationTokenSource _cts;
public override IBinder OnBind(Intent intent)
{
return null;
}
public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
{
_cts = new CancellationTokenSource();
Task.Run(() =>
{
try
{
//INVOKE THE SHARED CODE
var timer = new BackgroundTimer();
timer.RunBackgroundTimer(_cts.Token).Wait();
}
catch (System.OperationCanceledException)
{
}
finally
{
if (_cts.IsCancellationRequested)
{
var message = new BackgroundTimerCancelledMessage();
Device.BeginInvokeOnMainThread(
() => MessagingCenter.Send(message, "BackgroundTimerCancelledMessage")
);
}
StopSelf();
}
}, _cts.Token);
return StartCommandResult.Sticky;
}
public override void OnCreate()
{
base.OnCreate();
}
public override void OnDestroy()
{
if (_cts != null)
{
_cts.Token.ThrowIfCancellationRequested();
_cts.Cancel();
}
base.OnDestroy();
}
}
}
然后,在 PCL 中:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Xamarin.Forms;
namespace OurAppNamespace.Classes
{
public class StartBackgroundTimer { }
public class StopBackgroundTimer { }
public class BackgroundTimerMessage
{
}
public class BackgroundTimerCancelledMessage { }
public class BackgroundTimer
{
public async Task RunBackgroundTimer(CancellationToken token)
{
await Task.Run(async () =>
{
while (true)
{
token.ThrowIfCancellationRequested();
await Task.Delay(1000);
Device.BeginInvokeOnMainThread(() =>
{
MessagingCenter.Send<BackgroundTimerMessage>(new BackgroundTimerMessage(), "BackgroundTimer");
});
}
}, token);
}
}
}
最后,BackgroundTimer 调用后要执行的代码:
private static void UpdateActiveTimers()
{
MessagingCenter.Subscribe<BackgroundTimerMessage>(instance, "BackgroundTimer", message =>
{
(unrelated code)
DependencyService.Get<INotificationHandling>().UpdateTimerNotification(timeText);
}
});
}
开启定时器10分钟,不同手机会有不同的结果。
小米红米 Note 3 Pro 可以在应用程序在后台执行此代码并锁定手机 10 分钟(不再测试)。
Blackberry Priv 在后台运行应用程序并锁定手机(然后进入待机状态)大约 2 分钟,然后计时器冻结/通知不再更新,直到手机再次打开(解锁不需要)。
通知显示计时器的剩余时间。当手机被锁定时,计时器似乎暂停并在手机再次解锁时恢复。当手机在计时器上剩余 20 分钟时锁定并在 10 分钟后解锁时,计时器会在大约 18 分钟时恢复计数。
HOMTOM HT16 显示与 Blackberry Priv 相同的行为,但它会在大约 30 秒后更早地暂停计时器。
如何修改代码,让手机在锁屏休眠状态下后台服务在所有设备上都能成功运行?
提前致谢!
【问题讨论】:
-
非常感谢!我将该服务提升为前台服务,它现在正在运行。这听起来很明显,但我们没有想到。
-
我在 Xamarin Forms 上遇到了同样的问题。我搜索过类似的东西:没有运气。如果有人能指出我正确的方向,我将不胜感激。谢谢!
标签: android xamarin service background xamarin.forms