安排警报管理器在每个星期四运行一种方法 [英] Schedule Alarm manager to run a method every Thursday

查看:83
本文介绍了安排警报管理器在每个星期四运行一种方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

例如,我想要一个警报,该警报将在每个星期四的中午12点启动。
我该怎么做?

For example i want to have an alarm that will fire every Thursday at 12PM How would i do this?

我已经实施了某些措施,但无法正常工作正确地,用我现在拥有的代码,今天是星期三15,如果将手机的日期更改为16星期三,则应用不会执行任何操作,如果我将手机的日期更改为下一个星期三22,则手机会发送通知,

I have something implemented but isnt working properly,with the code that i have, today is wednesday 15, if change the date of the phone to 16 thrusday, the app doesnt do anything, if i change the date of the phone for the next wednesday 22 the phone sends a notification, but only should send on thursdays.

这是我的代码:

MainActivity:

MainActivity:

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<AlarmManager>();

        //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:

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:

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以上时这将不再起作用。

For api levels below 19 you should use AlarmManager.setRepeating() and your alarms will trigger exactly at specified time. But as the document said, when your device api levels 19 and above this will no longer work.


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

Note: Beginning with API 19 (KITKAT) alarm delivery is inexact: the OS will shift alarms in order to minimize wakeups and battery use. There are new APIs to support applications which need strict delivery guarantees; see setWindow(int, long, long, PendingIntent) and setExact(int, long, PendingIntent). Applications whose targetSdkVersion is earlier than API 19 will continue to see the previous behavior in which all alarms are delivered exactly when requested.

使用 alarmManager.SetExact()方法:


警报将以接近

The alarm will be delivered as nearly as possible to the requested trigger time.

因此,如果您想实现精确的重复警报,则为@Dus说这是两个建议:

So if you would like to achieve exact repeating alarm, as @Dus said here is two suggestions :

  • Accept the time delays(but maybe consider using JobSchedular which is more recommended and will save you battery).

或:


  • 使用 SetExactAndAllowWhileIdle 这可能会导致您出现电池问题(请谨慎使用,过多的警报将对您的电池不利)。
    此方法不再重复,因此您必须声明下一个要在未完成的Intent打开的服务上运行的作业。

  • Use SetExactAndAllowWhileIdle which might cause you battery issues(use this carefully, too many alarms will be bad for your battery). This method isn't repeating, so you have to declare the next job to be run at the service which the pendingIntent opens.

将Dus的代码转换为C#:

Convert Dus's code to 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);
}



更新:



打ze睡的目的是防止电池电量耗尽。重复的闹钟会耗尽电池电量,因此在Android 6中删除了通过传递额外参数来重复闹钟的内置方法。因此,它需要您手动重新安排闹钟的时间。

Update :

The idea behind doze is to attempt to prevent draining the battery. Repeated alarms drain battery, so the builtin way to repeat alarms by passing an extra parameter was removed in android 6. So it requires you to manually reschedule the alarm.

您可以

有关使用 SetExactAndAllowWhileIdle 方法实现重复警报的简单演示,希望对您有所帮助。

A simple demo about use SetExactAndAllowWhileIdle method to implement a repeating alarm, hope this can help you.

第一次设置警报:

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();
    }
}

这篇关于安排警报管理器在每个星期四运行一种方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆