AlarmManager dispara alarmas en el momento equivocado

Logré todo bien para crear un servicio de notificación utilizado para activar una notificación como resultado de una alarma. Desafortunadamente, configurar la alarma con AlarmManager no funciona bien. Dispara varios minutos más tarde (no exactamente horas, lo que indicaría un problema de zona horaria). El período recurrente es de 1 semana, así que usé la constante INTERVAL_DAY y la multipliqué con 7. Para asegurarme de que un PendingIntent no reemplaza al otro, paso el dayOfWeek como el segundo parámetro a PendingIntent.getService (). Compruebo la exactitud del tiempo para que la alarma se dispare al iniciar sesión:

Log.d(TAG, "next alarm " + df.format(cal.getTime())); 

¿Realmente no hay forma de enumerar todas las alarmas establecidas, al menos las de mi propia aplicación? Creo que esta es la única forma de rastrear el error.

Mi código:

 cal.setTimeInMillis(System.currentTimeMillis()); cal.add(Calendar.DATE, 1); cal.set(Calendar.HOUR_OF_DAY, hour); cal.set(Calendar.MINUTE, minute); Log.d(TAG, "next alarm " + df.format(cal.getTime())); Intent showNotificationIntent = new Intent(context, NotificationService.class); dayOfWeek = cal.get(Calendar.DAY_OF_WEEK); alarmIntent = PendingIntent.getService(context, dayOfWeek, showNotificationIntent, 0); getAlarmManager(context).setInexactRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), INTERVAL_WEEK, alarmIntent); 

Deseo ofrecer tener una alarma todos los días, pero en varias ocasiones, que puede establecer el usuario. Entonces uso hasta 7 alarmas, que deben disparar semanalmente.

Incluso después de leer las numerosas respuestas a preguntas similares (no tengo la intención de crear una pregunta duplicada), no he logrado encontrar el problema.

Para niveles de API por debajo de 19, debe usar AlarmManager.setRepeating() y sus alarmas se dispararán exactamente a la hora especificada. Tú en los niveles api 19 y superiores esto ya no funcionará. Hubo un cambio en Android para que todas las alarmas repetitivas sean inexactas. Por lo tanto, si desea obtener la alarma de repetición exacta, debe progtwigr la alarma con AlarmManager.setExact() y luego, cuando la alarma se dispare lo haga de nuevo la próxima semana y así sucesivamente cada semana.

Debido a setInexactRepeating. Use setRepeating y se procesará en el momento adecuado.

En lugar de:

 setInexactRepeating 

utilizar

 setRepeating 

setInexactRepeating, es amigable para el sistema operativo y la batería, agrupa todo el trabajo que se debe hacer en la recepción de alarma y funciona de a uno por uno, mientras que setRepeating dispara la alarma al instante

También una nota: las alarmas se borran una vez que se reinicia el teléfono, es posible que deba implementar un receptor de difusión de arranque para hacerlo persistente. Asegúrese de no hacer ese tiempo de ejecución, debe implementarlo en el Manifiesto, de lo contrario, cuando su aplicación no esté en segundo plano, no recibirá ninguna difusión.

Un pequeño ejemplo:

Esto es código de trabajo. Se activa la CPU cada 10 minutos hasta que el teléfono se apaga.

Agregar a Manifest.xml:

 ...  ...  ... 

Código:

  package YourPackage; import android.app.AlarmManager; import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.os.PowerManager; import android.widget.Toast; public class Alarm extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE); PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, ""); wl.acquire(); // Put here YOUR code. Toast.makeText(context, "Alarm !!!!!!!!!!", Toast.LENGTH_LONG).show(); // For example wl.release(); } public void SetAlarm(Context context) { AlarmManager am=(AlarmManager)context.getSystemService(Context.ALARM_SERVICE); Intent i = new Intent(context, Alarm.class); PendingIntent pi = PendingIntent.getBroadcast(context, 0, i, 0); am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 1000 * 60 * 10, pi); // Millisec * Second * Minute } public void CancelAlarm(Context context) { Intent intent = new Intent(context, Alarm.class); PendingIntent sender = PendingIntent.getBroadcast(context, 0, intent, 0); AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); alarmManager.cancel(sender); } } 

Establecer la alarma del servicio:

 package YourPackage; import android.app.Service; import android.content.Context; import android.content.Intent; import android.os.IBinder; public class YourService extends Service { Alarm alarm = new Alarm(); public void onCreate() { super.onCreate(); } public void onStart(Context context,Intent intent, int startId) { alarm.SetAlarm(context); } @Override public IBinder onBind(Intent intent) { return null; } } 

Si desea configurar la repetición de alarma al momento de inicio del teléfono:

Agregue permiso a Manifest.xml:

  ...      ... 

Y crea una nueva clase:

 package YourPackage; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; public class AutoStart extends BroadcastReceiver { Alarm alarm = new Alarm(); @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().equals("android.intent.action.BOOT_COMPLETED")) { alarm.SetAlarm(context); } } }