2010-12-13 22 views
15

Actualmente estoy tratando de escribir gestor de alarma que hará que una alarma se apaga en un plazo determinado de tiempo, todos los días. En primer lugar comprobar para ver si el usuario ha tenido un ajuste de la alarma de que para ese día:Cómo conjunto recurrente AlarmManager ejecutar código diaria

 if ((User.getReminderTime(Home.this) > 0) 
    && (dt.getDate() != today.getDate() || dt.getDay() != today 
     .getDay())) { 
    AppointmentManager.setFutureAppointmentCheck(this 
    .getApplicationContext()); 
    User.setLongSetting(this, "futureappts", today.getTime()); 
    } 

entonces voy y ajustar la alarma para que suene real entre el 12 y 12:10 del día siguiente:

 public static void setFutureAppointmentCheck(Context con) { 
    AlarmManager am = (AlarmManager) con 
    .getSystemService(Context.ALARM_SERVICE); 

    Date futureDate = new Date(new Date().getTime() + 86400000); 
    Random generator = new Random(); 

    futureDate.setHours(0); 
    futureDate.setMinutes(generator.nextInt(10)); 
    futureDate.setSeconds(0); 

    Intent intent = new Intent(con, FutureAppointmentReciever.class); 

    PendingIntent sender = PendingIntent.getBroadcast(con, 0, intent, 
    PendingIntent.FLAG_ONE_SHOT); 

    am.set(AlarmManager.RTC_WAKEUP, futureDate.getTime(), sender); 

} 

Ahora puedo configurar un entorno de prueba para que esto se apaga cada dos minutos y parece estar funcionando bien, sin embargo, cuando despliego a un dispositivo real, no parece ser el receptor de recibir a las alarmas. Pensé que podría ser un problema con el dispositivo de estar dormido, por lo que añade el gestor de energía. Pero aún así no funciona:

 PowerManager pm = (PowerManager) context 
    .getSystemService(Context.POWER_SERVICE); 
    PowerManager.WakeLock wl = pm.newWakeLock(
    PowerManager.PARTIAL_WAKE_LOCK, "keepAlive"); 
    wl.acquire(); 
    setFutureAppointments(context.getApplicationContext()); 
    AppointmentManager.setFutureAppointmentCheck(context 
    .getApplicationContext()); 
    User.setLongSetting(context.getApplicationContext(), "futureappts", 
    new Date().getTime()); 
    wl.release(); 

Alguien ve algo que estoy haciendo mal o descaradamente voy de esta manera incorrecta? Gracias por cualquier y toda la ayuda.

Respuesta

43

por lo general hago algo más en la línea de:

Intent i = new Intent(this, MyService.class); 
PendingIntent pi = PendingIntent.getService(this, 0, i, 0); 
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE); 
am.cancel(pi); // cancel any existing alarms 
am.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, 
    SystemClock.elapsedRealtime() + AlarmManager.INTERVAL_DAY, 
    AlarmManager.INTERVAL_DAY, pi); 

De esta manera, usted no tiene que preocuparse de volver a establecer el AlarmManager en su Service.

Normalmente ejecuto este código cuando mi aplicación se inicia (onResume en mi actividad principal) y en un BroadcastReceiver que está configurado para recibir BOOT_COMPLETED.

He escrito una guía en la creación de Service s y con el AlarmManager, que se basa en mi propia experiencia y algunos consejos & trucos que sorprendido fuera de ver una charla Google I/O. Si está interesado, puede leerlo here.


Para responder a su pregunta a continuación, todo lo que puedo hacer es cita the docs:

public void setInexactRepeating (int type, long triggerAtTime, long interval, PendingIntent operation) 

Planificar una alarma que se repite que tiene requisitos de tiempo de disparo inexactas; por ejemplo, una alarma que se repite cada hora, pero no necesariamente en la parte superior de cada hora. Estas alarmas son más eficientes en términos de energía que las recurrencias estrictas proporcionadas por setRepeating (int, long, long, PendingIntent), ya que el sistema puede ajustar la fase de las alarmas para hacer que disparen simultáneamente, evitando que el dispositivo se apague más de lo necesario.

El primer activador de su alarma no será antes del tiempo solicitado, pero podría no ocurrir durante casi un intervalo completo después de ese momento. Además, aunque el período total de la alarma de repetición será el requerido, el tiempo entre dos disparos sucesivos de la alarma puede variar. Si su aplicación exige una fluctuación de fase muy baja, utilice setRepeating (int, long, long, PendingIntent) en su lugar.

En conclusión, no está muy claro. Los documentos solo dicen que la alarma "puede variar". Sin embargo, debería ser importante que sepa que el primer disparador podría no ocurrir durante casi un intervalo completo después de ese tiempo.

+0

Creo que un servicio puede ser más de lo que necesito para lo que estoy haciendo, pero su blog era una buena lectura! ¿Sabes por casualidad cuánto offset es el SetInexactRepeating usualmente? – ninjasense

+1

Edité mi respuesta para explicar el problema 'setInexactRepeating'. – Felix

+3

como bonificación, en lugar de cancelar antes de configurar uno nuevo, puede recuperar el PendingIntent con PendingIntent.FLAG_CANCEL_CURRENT como último parámetro, que tiene el mismo efecto. – nsL

4

Esto está trabajando, esto va a disparar la alarma después de cada 5 segundos

private void setRecurringAlarm() { 

     Logger.d(IConstants.DEBUGTAG, "Setting Recurring Alarm"); 

     Calendar updateTime = Calendar.getInstance(); 

     updateTime.set(Calendar.SECOND, 5); 

     Intent alarmIntent = new Intent(this, AlarmReceiver.class); 
     PendingIntent recurringDownload = PendingIntent.getBroadcast(this, 0, alarmIntent, PendingIntent.FLAG_CANCEL_CURRENT); 
     AlarmManager alarms = (AlarmManager) getSystemService(Context.ALARM_SERVICE); 
     alarms.cancel(recurringDownload); 
     alarms.setInexactRepeating(AlarmManager.RTC_WAKEUP, updateTime.getTimeInMillis(), 1000 * 5, recurringDownload); //will run it after every 5 seconds. 
    } 
+0

¿cuál es la diferencia entre setInexactRepeating y setRepeating? –

+0

http://developer.android.com/reference/android/app/AlarmManager.html –

+1

Programe una alarma repetitiva que tenga requisitos de tiempo de activación inexactos; por ejemplo, una alarma que se repite cada hora, pero no necesariamente en la parte superior de cada hora. Estas alarmas son más eficientes en términos de energía que las recurrencias estrictas proporcionadas por setRepeating (int, long, long, PendingIntent), ya que el sistema puede ajustar la fase de las alarmas para hacer que disparen simultáneamente, evitando que el dispositivo se apague más de lo necesario. –