2012-02-01 20 views
22

Editar: Se ha aclarado la cuestión sobre la base de la respuesta de CommonsWareComo crear un persistente AlarmManager

Estamos programar una alarma a través de un AlarmManager para disparar cada 60 segundos. Cuando se elimina nuestra aplicación, nuestras alarmas parecen no ejecutarse más. ¿Hay alguna manera de hacer que estas alarmas persistan incluso cuando la aplicación es eliminada manualmente o por el sistema?

Esto es un problema para nosotros porque tenemos una aplicación de widget que muestra la hora. Esto significa que necesitamos actualizar el tiempo cada minuto. Para superar el límite de actualización de 30 minutos en el método onUpdate de AppWidgetProvider, utilizamos AlarmManager. Por lo general, funciona bastante bien, pero algunos usuarios han informado que el tiempo no está sincronizado. Después de hablar con varios de ellos, mi sospecha es que nuestra aplicación se está matando manualmente a través de una aplicación asesina de tareas o Android en sí está matando a nuestra aplicación.

Cualquier otra solución alternativa al problema raíz (mantener el tiempo sincronizado en un widget) también es bienvenido.

Este es el código que ejecutamos para programar nuestra alarma:

Intent intent = new Intent(UPDATE_TIME); 
PendingIntent pIntent = PendingIntent.getBroadcast(ctx, 
    0 /* no requestCode */, intent, PendingIntent.FLAG_UPDATE_CURRENT); 

// get alarm params 
Date d = new Date(); 
long timeTilMinuteChange = 60*1000-d.getSeconds()*1000; 
long startTime = System.currentTimeMillis() + + timeTilMinuteChange; 

AlarmManager am = (AlarmManager) ctx.getSystemService(Context. 
am.cancel(pIntent); 
am.set(AlarmManager.RTC, System.currentTimeMillis(), pIntent); 
     am.setRepeating(AlarmManager.RTC, startTime, 60000, pIntent); 
+0

Creo que el Alarm Manager no se está destruyendo, pero tal vez los datos se estén volviendo obsoletos. ¿Estás usando variables estáticas? Recuerde que el proceso del appwidget puede y será cerrado por Android (es un receptor) ¿está utilizando alguna variable que esté vinculada a la clase AppWidgetProvider? –

+0

No estoy usando variables estáticas, pero estoy usando una clase estática. Básicamente, la forma en que funciona es que nuestro AppWidgetProvider llama a TimeManager.start (contexto). TimeManager.start establece una alarma de repetición. – christoff

+0

@EfiMK Sé que es una publicación muy antigua, pero como no pude encontrar respuestas en ningún otro lugar, por favor guíese sobre el problema del uso de variables estáticas en la clase appwidgetprovider. – Atihska

Respuesta

1

Sobre el gestor de alarma en el Docs - la explicación es un tanto confuso y, sinceramente, todavía no lo entiendo totalmente. Tengo este código para la parte del widget que resolvió el problema en mi caso.

package com.test.mytestwidget; 

import java.util.Calendar; 
import android.app.AlarmManager; 
import android.app.PendingIntent; 
import android.appwidget.AppWidgetManager; 
import android.appwidget.AppWidgetProvider; 
import android.content.Context; 
import android.content.Intent; 

public class MyWidgetProvider extends AppWidgetProvider { 

    private PendingIntent service = null; 

    public void onUpdate(Context context, AppWidgetManager appWidgetManager, 
      int[] appWidgetIds) { 
     super.onUpdate(context, appWidgetManager, appWidgetIds);     

     final AlarmManager m = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); 

     final Calendar TIME = Calendar.getInstance(); 
     TIME.set(Calendar.MINUTE, 0); 
     TIME.set(Calendar.SECOND, 0); 
     TIME.set(Calendar.MILLISECOND, 0); 

     final Intent i = new Intent(context, UpdateWidgetService.class); 

     if (service == null) 
     { 
      service = PendingIntent.getService(context, 0, i, PendingIntent.FLAG_CANCEL_CURRENT); 
     } 

     m.setRepeating(AlarmManager.RTC, TIME.getTime().getTime(), 30000, service); 

    } 

    @Override 
    public void onDisabled(Context context) 
    {    
     final AlarmManager m = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); 

     m.cancel(service); 
     super.onDisabled(context); 
    }  

} 
12

Siempre que nuestra aplicación es asesinada, el AlarmManager también muere.

AlarmManager no se elimina. Su alarma, sin embargo, se cancela. Si el usuario fuerza la detención o la tarea lo mata, sus alarmas no están programadas. En Android 3.1+, si el usuario lo detiene, no se ejecutará nada de su código hasta que el usuario inicie manualmente una de sus actividades.

Después de hablar con varios de ellos, mi sospecha es que nuestra aplicación está siendo eliminada manualmente a través de una aplicación asesina de tareas o que el propio Android está matando nuestra aplicación.

Lo ideal es que su aplicación no se escriba de forma tal que Android tenga alguna razón para deshacerse de usted. Para algo similar a lo que describe, debe usar un getBroadcast()PendingIntent apuntando a un manifiesto BroadcastReceiver registrado, o debe estar usando un getService()PendingIntent apuntando a un IntentService. En cualquier caso, su código se ejecutará brevemente, y luego su proceso será elegible para reclamación por parte de Android sin problema si surge la necesidad.

Los asesinos de tareas, ya sean manuales o automáticos, parecen ser un culpable mucho más probable de que se cancelen las alarmas, en mi humilde opinión.

+0

Re alarma cancelada: gracias por la aclaración.Lo pregunté en las horas de oficina del equipo de Android en g + hangout e incluso parecían confundidas acerca de este comportamiento. Está documentado en cualquier lugar? – christoff

+0

Re getBroadcast/getService Intención pendiente: Estoy usando getBroadcast() como usted describe. Agregué un código relevante arriba. – christoff

+0

Re Android 3.1: ¿Qué pasa con los servicios? Intenté matar una aplicación con mi Galaxy Nexus y uno de sus servicios se reinició automáticamente. – christoff

Cuestiones relacionadas