Pianificare il gestore degli allarmi per eseguire un metodo ogni giovedì

Ad esempio voglio avere un allarme che si accenderà ogni giovedì alle 12.00. Come lo farei?

Ho implementato qualcosa ma non funziona correttamente, con il codice che ho, oggi è mercoledì 15, se cambia la data del telefono a 16 giovedì, l’app non fa nulla, se cambio la data del telefono per il prossimo mercoledì 22 il telefono invia una notifica, ma deve essere inviato solo il giovedì.

Ecco il mio codice:

Attività principale:

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) { } } } 

Per i livelli di API inferiori a 19, utilizzare AlarmManager.setRepeating() e gli allarmi si attiveranno esattamente al momento specificato. Ma come ha detto il documento , quando i livelli del dispositivo api 19 e superiori non funzioneranno più.

Nota : a partire dall’API 19 (KITKAT) l’invio dell’allarme è inesatto: il sistema operativo sposterà gli allarmi per ridurre al minimo il risveglio e l’uso della batteria. Ci sono nuove API per supportare applicazioni che richiedono rigide garanzie di consegna; vedere setWindow (int, long, long, PendingIntent) e setExact (int, long, PendingIntent). Le applicazioni con targetSdkVersion precedente all’API 19 continueranno a vedere il comportamento precedente in cui tutti gli allarmi vengono recapitati esattamente quando richiesto.

Anche durante l’utilizzo del metodo alarmManager.SetExact() :

L’allarme verrà consegnato il più vicino ansible al tempo di triggerszione richiesto.

Quindi, se si desidera ottenere un allarme ripetuto esatto, come @Dus ha detto qui ci sono due suggerimenti:

  • Accetta i ritardi di tempo (ma forse considera l’utilizzo di JobSchedular che è più raccomandato e ti farà risparmiare la batteria).

O :

  • Usa SetExactAndAllowWhileIdle che potrebbe causare problemi alla batteria (usa questo attentamente, troppi allarmi saranno dannosi per la batteria). Questo metodo non si ripete, pertanto è necessario dichiarare il lavoro successivo da eseguire nel servizio in cui si apre il pendingIntent.

Converti il ​​codice di Dus in 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); } 

Aggiornare :

L’idea dietro doze è di tentare di prevenire il drenaggio della batteria. Gli allarmi ripetuti consumano la batteria, quindi il modo integrato di ripetere gli allarmi passando un parametro aggiuntivo è stato rimosso in Android 6. Quindi è necessario riprogrammare manualmente l’allarme.

È ansible riprogrammare l’allarme immediatamente quando si triggers, prima di fare qualsiasi altra cosa che potrebbe andare storta e impedire che l’allarme venga riprogrammato.

Aggiornamento 2:

Una semplice demo sull’uso del metodo SetExactAndAllowWhileIdle per implementare un allarme SetExactAndAllowWhileIdle , spero che questo possa aiutarti.

La prima volta impostare un allarme:

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

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