安排警报管理器每周四运行一个方法

例如,我希望每周四中午12点发出警报我该怎么做?

我有一些实施,但没有正常工作,我的代码,今天是星期三15,如果将手机的日期更改为16星期四,该应用程序没有做任何事情,如果我在下周三更改手机的日期22电话发送通知,但只应在星期四发送。

这是我的代码:

主要活动:

protected override void OnCreate(Bundle bundle) { TabLayoutResource = Resource.Layout.Tabbar; ToolbarResource = Resource.Layout.Toolbar; base.OnCreate(bundle); AsNumAssemblyHelper.HoldAssembly(); global::Xamarin.Forms.Forms.Init(this, bundle); ImageCircleRenderer.Init(); Intent alarmIntent = new Intent(this, typeof(AlarmReceiver)); PendingIntent pending = PendingIntent.GetBroadcast(this, 0, alarmIntent, PendingIntentFlags.UpdateCurrent); AlarmManager alarmManager = GetSystemService(AlarmService).JavaCast(); //AlarmType.RtcWakeup – it will fire up the pending intent at a specified time, waking up the device alarmManager.SetRepeating(AlarmType.RtcWakeup,BootReceiver.FirstReminder(), BootReceiver.reminderInterval, pending); PendingIntent pendingIntent = PendingIntent.GetBroadcast(this, 0, alarmIntent, 0); LoadApplication(new App()); } 

BootReceiver:

 [BroadcastReceiver] [IntentFilter(new[] { Intent.ActionBootCompleted })] public class BootReceiver : BroadcastReceiver { //the interval currently every one minute //to set it to dayly change the value to 24 * 60 * 60 * 1000 public static long reminderInterval = AlarmManager.IntervalDay * 7; //public static long reminderInterval = 30 * 1000; public static long FirstReminder() { Java.Util.Calendar calendar = Java.Util.Calendar.Instance; calendar.Set(Java.Util.CalendarField.DayOfWeek, Calendar.Thursday); return calendar.TimeInMillis; } public override void OnReceive(Context context, Intent intent) { Console.WriteLine("BootReceiver: OnReceive"); var alarmIntent = new Intent(context, typeof(AlarmReceiver)); var pending = PendingIntent.GetBroadcast(context, 0, alarmIntent, PendingIntentFlags.UpdateCurrent); AlarmManager alarmManager = (AlarmManager)context.GetSystemService(Context.AlarmService); alarmManager.SetRepeating(AlarmType.RtcWakeup, FirstReminder(), reminderInterval, pending); PendingIntent pendingIntent = PendingIntent.GetBroadcast(context, 0, alarmIntent, 0); } } 

AlarmReceiver:

 [BroadcastReceiver] public class AlarmReceiver : BroadcastReceiver { public override void OnReceive(Context context, Intent intent) { try { var title = "Something"; var message = "Something"; Intent backIntent = new Intent(context, typeof(MainActivity)); backIntent.SetFlags(ActivityFlags.NewTask); var builder = new Notification.Builder(context) .SetContentTitle(title) .SetContentText(message) .SetAutoCancel(true) .SetSmallIcon(Resource.Drawable.icon) .SetDefaults(NotificationDefaults.All); var notification = builder.Build(); var manager = NotificationManager.FromContext(context); manager.Notify(1331, notification); } } catch (Exception) { } } } 

对于低于19的api级别,您应该使用AlarmManager.setRepeating()并且您的警报将在指定时间准确触发。 但正如文件所述,当你的设备api等级为19及以上时,这将不再有效。

注意 :从API 19(KITKAT)警报传递开始是不准确的:操作系统将移动警报以最小化唤醒和电池使用。 有新的API支持需要严格交付保证的应用程序; 请参阅setWindow(int,long,long,PendingIntent)和setExact(int,long,PendingIntent)。 targetSdkVersion早于API 19的应用程序将继续查看先前在请求时准确传递所有警报的行为。

同时使用alarmManager.SetExact()方法:

警报将尽可能地传递到请求的触发时间。

因此,如果您想要实现精确的重复警报,正如@Dus所说,这里有两个建议:

  • 接受时间延迟(但可以考虑使用更推荐的JobSchedular并节省电池电量)。

要么 :

  • 使用SetExactAndAllowWhileIdle可能会导致电池问题(请谨慎使用,太多警报会对您的电池造成不利影响)。 此方法不重复,因此您必须声明要在pendingIntent打开的服务上运行的下一个作业。

将Dus的代码转换为C#:

 AlarmManager alarmManager = (AlarmManager)this.GetSystemService(Context.AlarmService); var ALARM_TYPE = AlarmType.RtcWakeup; if (Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.M) { alarmManager.SetExactAndAllowWhileIdle(ALARM_TYPE, calendar.TimeInMillis, pendingIntent); } else if (Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.Lollipop) { alarmManager.SetExact(ALARM_TYPE, calendar.TimeInMillis, pendingIntent); } else if { alarmManager.Set(ALARM_TYPE, calendar.TimeInMillis, pendingIntent); } 

更新:

打瞌睡的想法是试图防止电池耗尽。 重复警报会耗尽电池,因此在Android 6中删除了通过传递额外参数重复警报的内置方式。因此,它需要您手动重新安排警报。

您可以在发生警报时立即重新安排警报,然后再做任何可能出错的事情并防止警报被重新安排。

更新2:

一个关于使用SetExactAndAllowWhileIdle方法实现重复警报的简单演示,希望这可以帮到你。

第一次设置闹钟:

 var intent = new Intent(this, typeof(RepeatingAlarm)); var source = PendingIntent.GetBroadcast(this, 0, intent, 0); // Schedule the alarm! var am = (AlarmManager)GetSystemService(AlarmService); //After 15s, use the RepeatingAlarm to show a toast am.SetExactAndAllowWhileIdle(AlarmType.ElapsedRealtimeWakeup, SystemClock.ElapsedRealtime() + 15 * 1000, source); 

RepeatingAlarm

 [BroadcastReceiver] public class RepeatingAlarm : BroadcastReceiver { public override void OnReceive(Context context, Intent intent) { //Every time the `RepeatingAlarm` is fired, set the next alarm var intentForRepeat = new Intent(context, typeof(RepeatingAlarm)); var source = PendingIntent.GetBroadcast(context, 0, intent, 0); var am = (AlarmManager)Android.App.Application.Context.GetSystemService(Context.AlarmService); am.SetExactAndAllowWhileIdle(AlarmType.ElapsedRealtimeWakeup, SystemClock.ElapsedRealtime() + 15 * 1000, source); Toast.MakeText(context, "repeating_received and after 15s another alarm will be fired", ToastLength.Short).Show(); } }