我有一个基于用户位置自动执行的应用程序。我现在正在处理打瞌睡模式,因为打瞌睡会影响我根据位置变化在后台发送请求的能力。我想每 9 分钟或在维护窗口期间让我的服务访问互联网。我正在使用 AlarmManager 和 SetExactAndAllowWhileIdle,但由于某种原因,尽管我给了它们一个将来会出现的 AlarmType.RtcWakeup,但我的警报却一遍又一遍地发送垃圾邮件。我的位置服务在应用程序启动时启动,我的服务也在应用程序终止和设备重新启动时启动/重新启动。
我对何时何地设置闹钟感到困惑。现在我在定位服务启动时设置闹钟。警报不断设置,甚至立即触发,而不是我设置它们触发的时间。我正在使用 AlarmType.RtcWakeup 设置 SetExactAndAllowWhileIdle,我的时间看起来是正确的。我正在用敬酒将它打印出来,它清楚地表明它在未来约 9 分钟。
我应该什么时候设置闹钟?我不应该对从警报中收到的每个 OnHandleIntent 采取行动吗?我是否错误地设置了闹钟?
现在,当我的位置服务启动时,我正在调用它:
StartAlarm_Now();
我应该在应用程序终止或暂停时设置它吗?
// I'm using AlarmType.RtcWakeup, so I need to get current time in milliseconds
public static long GetDateTimesMillisecondsForToday()
{
var test = (DateTime.Now).Subtract(DateTime.Today);
var hours = test.TotalHours;
long milliseconds = (long)(test.TotalMilliseconds);
return milliseconds;
}
// Calling this will set the alarm for now. Should I ever need to do this??
public static void StartAlarm_Now()
{
string id = "Now_" + new Random().Next(1000, 9999).ToString();
StartAlarm(id, GetDateTimesMillisecondsForToday());
}
// Calling this will set the alarm for x seconds from now. This is the right way to do it?
public static void StartAlarm_SecondsFromNow(long a_secondsFromNow)
{
string id = "SecondsFromNow_" + new Random().Next(1000, 9999).ToString();
long millisecondsToUse = GetDateTimesMillisecondsForToday() + (a_secondsFromNow * 1000);
StartAlarm(id, millisecondsToUse);
}
private static void StartAlarm(string id, long a_milliseconds)
{
TimeSpan t = TimeSpan.FromMilliseconds(a_milliseconds);
string readableTime_fromMilliseconds = string.Format(
"{0:D2}h:{1:D2}m:{2:D2}s:{3:D3}ms",
t.Hours,
t.Minutes,
t.Seconds,
t.Milliseconds
);
string message = "StartAlarm " + id + " readableTime_fromMilliseconds = " + readableTime_fromMilliseconds;
SCoreAppContext.Instance.Container.Get<ISCoreAppGlobal<Activity>>().SafeInvokeOnMainThread(() =>
{
Toast.MakeText(Android.App.Application.Context, message, ToastLength.Short).Show();
});
using (AlarmManager alarmManager = (AlarmManager)AppContext.GetSystemService(Context.AlarmService))
{
Intent serviceIntent = new Intent(Android.App.Application.Context, typeof(TestService));
PendingIntent pendingIntent = PendingIntent.GetService(Android.App.Application.Context, 0, serviceIntent, PendingIntentFlags.CancelCurrent);
alarmManager.SetExactAndAllowWhileIdle(AlarmType.RtcWakeup, a_milliseconds, pendingIntent);
}
}
[Service(Exported = false)]
public class TestService : IntentService
{
public override void OnCreate()
{
base.OnCreate();
}
public override Android.OS.IBinder OnBind(Android.Content.Intent intent)
{
return null;
}
protected override async void OnHandleIntent(Intent intent)
{
// This part is spamming constantly while the app is running.
// Here is where I run my code that should execute when my alarm expires, right?... That's what I'm assuming, but this is spamming a LOT. And my alarms set for the future and this is getting called immediately
SCoreAppContext.Instance.Container.Get<ISCoreAppGlobal<Activity>>().SafeInvokeOnMainThread(() =>
{
Toast.MakeText(Android.App.Application.Context, "JoeyZTestService.OnHandleIntent", ToastLength.Short).Show();
});
// I read that if you want the alarm to repeat, you can set another one when this one fires. But I believe this is why mine are looping forever. So how can i repeat if not here?
// The 530 is the # of seconds in the future that the alarm should fire.
StartAlarm_SecondsFromNow(530);
}
}