For example i want to have an alarm that will fire every Thursday at 12PM How would i do this?
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.
Here is my code:
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:
[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)
{
}
}
}
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.Also while using
alarmManager.SetExact()
method :So if you would like to achieve exact repeating alarm, as @Dus said here is two suggestions :
Or :
Convert Dus's code to C# :
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.
You could reschedule the alarm immediately when it fires, before doing anything else that could go wrong and prevent the alarm from being rescheduled.
Update 2 :
A simple demo about use
SetExactAndAllowWhileIdle
method to implement a repeating alarm, hope this can help you.The first time set an alarm :
In the
RepeatingAlarm
: